2011-11-07 8 views
9

Ho un gioco OpenGL consistente in texture che mi piacerebbe ottimizzare in base alla quantità di RAM del dispositivo. Le trame ad alta risoluzione che ho lavorato bene su un iPhone 4 o iPad2, ma i dispositivi precedenti si bloccano nel mezzo del caricamento delle trame. Ho versioni a bassa risoluzione di queste trame, ma ho bisogno di sapere quando usarle.Risposta alla disponibilità della RAM in iOS

mia tattica attuale è quella di rilevare i dispositivi specifici anziani (3GS ha una bassa risoluzione dello schermo; iPad non ha fotocamera), quindi caricare solo le texture ad alta risoluzione per iPad2 e superiori e iPhone 4 e superiori - e suppongo Dovrò fare qualcosa per l'iPod touch. Ma preferirei utilizzare il rilevamento di funzionalità piuttosto che i modelli di dispositivi hard-coding, dal momento che il rilevamento dei modelli è fragile rispetto alle future modifiche alle API e all'hardware.

Un'altra possibilità che sto considerando è caricare prima le trame ad alta risoluzione, quindi rilasciarle e sostituirle con lo-res nel momento in cui viene visualizzato un avviso di memoria insufficiente. Tuttavia, non sono sicuro che avrò la possibilità di risposta; Ho notato che l'app spesso muore prima che venga visualizzata una notifica sulla console di debug.

Come posso rilevare se il dispositivo su cui sto lavorando ha RAM insufficiente per caricare versioni ad alta risoluzione delle mie trame?

Facendo un passo indietro, c'è qualche altra tecnica adattiva che posso usare specifica per la memoria texture OpenGL?

Note:

  1. Ho cercato on e off SO di risposte relative alla rilevazione di RAM disponibile, ma tutti fondamentalmente consigliamo profiling utilizzo della memoria e l'eliminazione degli sprechi (ridurre al minimo la durata di provvisori, e tutto ciò che guff). Ho fatto tutto ciò che posso, e non ho intenzione di spremere le texture ad alta risoluzione nei vecchi dispositivi.

  2. PVRTC non è un'opzione. Le trame contengono dati che devono essere utilizzati da frammenti shader e devono essere archiviati in un formato senza perdita di dati.

+0

Nota che puoi ottenere sia la RAM totale che le statistiche di RAM gratuite come descritto in questo thread [memoria libera su iOS] (http://stackoverflow.com/questions/5012886). Inoltre, ho testato il codice sul mio iPhone 4 e funziona bene! –

risposta

11

Per ottenere la RAM fisica totale (massima) del dispositivo utilizzare [NSProcessInfo processInfo].physicalMemory.

Vedere Documentation.

0

Per quanto ne so le 3 cose più importanti che si possono fare è -

  1. implementare - (void)didReceiveMemoryWarning e risponde quando iOS manda avvertimenti 1 & 2.
  2. codice di profilo in Strumenti a cercare di trovare perdite & meglio mem modi ottimali di attuazione.
  3. Rileva i tipi di dispositivo & forse usa quelle informazioni.
  4. Utilizzare alcune forme di compressione texture come PVRTC per risparmiare spazio.

Penso che tu stia facendo la maggior parte di loro. Il fatto è che non si sa nemmeno con precisione quanti dispositivi RAM iOS ha. Apple non pubblica le specifiche tecniche per i dispositivi iOS.

Inoltre, non si può presumere che solo dopo aver detto 100mb di consumo si riceverà un avvertimento mem. Le avvertenze fornite da iOS variano a seconda dello stato corrente del dispositivo & quali altre app sono in esecuzione & la quantità di mem che stanno consumando. Quindi diventa complicato.

posso suggerire 2 deve leggere le sezioni - Best Practices for Working with Texture Data e Tuning Your OpenGL ES Application

2

Il più importante che avete bisogno di sapere per la gestione della memoria, in questo caso è se utilizzare alti o bassi res texture. Il modo più semplice che uso è di controllare questo

CGFloat scale = [[UIScreen mainScreen] scale]; 
if ((scale > 1.0) || (self.view.frame.size.width > 320)) { 
     highRes = TRUE; 
} 

Questo funziona per tutti i dispositivi finora e dovrebbe essere a prova di futuro, nuovi dispositivi utilizzeranno i di buona qualità. Si potrebbe anche calcolare proprio lì il rapporto di aspetto (aiuta in seguito iPad vs iPhone)

aspect = self.view.frame.size.width/self.view.frame.size.width 

Non caricare highres prima uccide il vostro tempo applicazioni di carico, sul mio 3G la maggior parte del mio avvio è speso di carico (anche le texture a bassa risoluzione), basta testare questo all'inizio e non toccare la roba di highres.

Su dispositivi precedenti il ​​programma morirà senza preavviso a causa di trame grandi, potrebbe avere qualcosa a che fare con de debugger non essere in grado di intrappolare il consumo di memoria video e di morire.

Per maggiori ottimizzazioni, prendere in considerazione la colorazione di mipmap per verificare la dimensione minima della trama effettivamente utilizzata (solo se si utilizzano oggetti 3D).

Dimenticate il problema dimensione del video RAM, la memoria è in realtà condivisa, in modo che stai in competizione per la memoria di sistema, sui vecchi dispositivi che hai avuto un limite di MB per l'uso, ma è ancora la memoria di sistema.

Informazioni sulla gestione della memoria, ci sono molti modi per farlo, il più semplice dovrebbe essere contrassegnare le trame che vengono caricate e le trame che sono necessarie, quando arriva un avviso di memoria, scaricare le trame che vengono caricate ma non necessarie .. .

+0

Grazie per la risposta dettagliata. Non posso accettarlo, perché non risponde alla domanda principale su come rilevare la RAM invece di usare il rilevamento di funzionalità (o stai insinuando che è impossibile o non vale la pena perseguire?), Ma +1 per indicare la scala. 1.0' per rilevare l'iPhone 4. Non ci avevo pensato. –

+0

L'unico modo per provare a rilevare la memoria senza jailbreaking è cercare di riempire tutto e misurare quanto hai ottenuto. Inoltre, poiché la memoria è condivisa con tutte le altre app che potrebbero essere in esecuzione (quelle di sistema, come la posta, ecc.) Anche conoscere la quantità di memoria fisica non vale molto. Ecco perché ho detto di dimenticare quella strada, non è il terreno solido che stai cercando. – led42

+0

La tua formulazione era ambigua se non dovessi pensare alla memoria video come separata o rinunciare alla misurazione della RAM. Non mi importa di altre app in esecuzione; empiricamente, i dispositivi con 256 MB si bloccano sempre, mentre quelli con 512 MB non funzionano mai. Inoltre, il tuo test proposto fallisce con l'ultimo iPod Touch - retina e 256 MB - sottolineando le mie paure sulla fragilità del rilevamento dei modelli. Per inciso, la ricerca di una soluzione al problema dell'iPod Touch mi ha portato a una possibile risposta, che posterò separatamente. –

7

totale RAM fisica disponibile tramite sysctl(), come documentato in this blog post e implementato come un bel API pulito here (vedere l'implementazione della totalMemory nel file .m corrispondenti).

ho sollevato il codice del blog per convenienza e posteri:

#include <sys/sysctl.h> 

size_t phys_mem() 
{ 
int mib[] = { CTL_HW, HW_PHYSMEM }; 
size_t mem; 
size_t len = sizeof(mem); 
sysctl(mib, 2, &mem, &len, NULL, 0); 
return mem; 
} 

Non so se Apple approverà un app che utilizza sysctl() in questo modo. È documentato, ma solo per Mac OS X.

+1

Hai mai finito per ottenere l'approvazione in un'app App Store? – Nate

+2

@Nate: Sì. [Your World] (http://itunes.apple.com/us/app/your-world/id412566625?mt=8) carica una terra da 96 megapixel su dispositivi con più di 384 MB; in caso contrario, torna a una versione da 24 megapixel. Non c'è niente di speciale nel numero; è solo a metà strada tra i dispositivi che possono e quelli che non possono. –

+2

Basta usare [NSProcessInfo processInfo] .physicalMemory – Steve