Sollevamento di coscienza: uso di memoria & perdite

Il 25 luglio 2010, in Programmazione, che Parla Da Esperienza, cocos2d, da Steffen Itterheim by Steffen Itterheim

Aiutando altri a risolvere i loro problemi di progetto di cocos2d durante l'anno passato diventò ovvio che molti progetti hanno almeno un gran problema in una di queste aree:

  • direzione di memoria
  • direzione di risorsa
  • struttura di codice

Esempi

I problemi di direzione di memoria normalmente variano da assegnare troppa memoria, caricando troppe strutture sul fronte che solo stanno per essere necessari più tardi, o da perdite di memoria come scene non deallocating cambiando scene. La gamma di problemi di direzione di risorsa da non aggiungere le risorse giuste all'obiettivo giusto, spesso avendo come conseguenza aumentò dimensioni App perché le risorse sono aggiunte al fascio, ma mai usate dall'App. Questo poteva anche intendere caricare file di risorsa identici salvo che loro hanno nomi di file diversi (le copie?), esaurendo la memoria supplementare. O non i folletti strettamente facenti i bagagli in Atlanti di Struttura ma invece utilizzazione di un Atlante di Struttura per oggetto di gioco – mentre questo è comprensibile da un luogo di osservazione di seperation logico proprio spreca opportunità per ottimizzazione. It could also mean loading identical resource files except that they have different filenames (copies?), using up additional memory. Or not tightly packing sprites into Texture Atlases but instead using one Texture Atlas per game object – while this is understandable from a standpoint of logical seperation it does waste opportunities for optimization.

Finalmente, la struttura di codice o la mancanza di ciò regolarmente conducono “a tutto in una classe” il progetto di codice che è il più probabile un processo evolutivo, piuttosto che intenzionale. È abbastanza comune vedere classi con migliaia di linee di codice, qualche volta perfino 10 000 linee passate andanti di codice in una classe. Altre cose stanno usando troppi CCLayers senza loro aggiungendo un vantaggio chiaro, ad esempio soltanto per raggruppare tutti i nodi a un ordine di z specifico insieme o raggrupparli da funzionalità, eg uno strato per nemici, un per giocatori, un per sfondo, un per UI, un per punteggio, un per effetti di particella, e così via – senza alcuno di questi strati usati per che loro sono veramente bravi: la modificazione di nodi multipli subito, come movimento, scalata, rotazione o z-riordinamento loro. E certamente ci sono l'inferno di pasta & di copia, i grandi blocchi di codice riprodotto in vari posti solo per modificare alcuni parametri invece creare un metodo che prende i parametri modificabili come argomenti. Perfino i professionisti che feci lavorare con ricevuto così solito di fare che diventò duro soltanto vincere la resistenza d'affitto vanno d'abitudini vecchie. Ma loro impararono. Other things are using too many CCLayers without them adding a clear benefit, for example just to group all nodes at a specific z order together or to group them by functionality, eg one layer for enemies, one for players, one for background, one for UI, one for score, one for particle effects, and so on – without any of these layers being used for what they’re really good at: modifying multiple nodes at once, like moving, scaling, rotating or z-reordering them. And of course there’s the copy & paste hell, large blocks of code reproduced in various places only to modify some parameters instead of creating a method which takes the modifiable parameters as arguments. Even professionals I worked with got so used to doing that it became hard just to overcome the resistance of letting go of old habits. But they learned.

Riassunto

Niente di questo progetto di codice e strutturazione mi sembra strano o sorprendente. Ho scritto il codice come questo io stesso. Anche credo se è abbastanza buono e i lavori, allora perché diavolo no? È una questione d'esperienza e è solo con esperienza che Lei chiaramente vede come migliorare cose. Questo si riduce alla curva d'erudizione regolare dove solo la formazione professionale e l'istruzione e soltanto semplicemente la fabbricazione di sbagli e l'erudizione di loro aiutano nella corsa lunga. Questo è come impariamo cose. I also believe if it’s good enough and works, then why the hell not? It’s a matter of experience and it’s only with experience that you clearly see how to improve things. This boils down to the regular learning curve where only training and tutoring and just simply making mistakes and learning from them helps in the long run. That’s how we learn things.

D'altra parte, le cose come direzione di Risorsa e di Memoria possono anche esser imparate ma loro hanno una natura diversa. Loro possono esser statisticamente valutati, loro potevano esser calcolati e verificati automaticamente. Questo mi fa chiedermi se non ci sono i dei certi attrezzi d'informazione e d'automazione che aiuterebbero progettisti a portare a termine risultati migliori in termini d'uso di memoria e direzione di risorsa? Nel frattempo è tutto su sollevamento di coscienza … This makes me wonder if there isn’t some kind of automation and information tools that would help developers achieve better results in terms of memory usage and resource management? In the meantime it’s all about raising awareness …

Sollevamento di Coscienza di Memoria

Il più significativamente penso che abbiamo bisogno di alzare più coscienza a questi problemi a progettisti cocos2d. Un passo verso questo sarebbe per cocos2d per esporre un “banco di memoria disponibile” di fianco al banco di FPS. Avevo l'abitudine di rattoppare CCDirector per esporre semplicemente la memoria invece di FPS poiché fu sempre più importante per me. Il compagno cocos2d il progettista Joseph mi mandò la sua versione per esporre entrambi – semplicemente non ho pensato all'ovvio. Così se Le piacerebbe vedere FPS e memoria disponibile vicino all'un l'altro penso che Lei può toccare i cambiamenti a CCDirector abbozzato qui: I used to patch CCDirector to simply display memory instead of FPS since that was always more important to me. Fellow cocos2d developer Joseph sent me his version to display both – I simply didn’t think of the obvious. So if you’d like to see FPS and available memory next to each other I think you can handle the changes to CCDirector outlined here:


//CCDirector.h, aggiungono sotto @interface:
+ getAvailableBytes (doppio);
+ getAvailableKiloBytes (doppio);
+ getAvailableMegaBytes (doppio);

//CCDirector.m, aggiungono come adatto:
#include <sys/sysctl.h>  
#import <mach/mach.h>
#import <mach/mach_host.h>

[...]

+ getAvailableBytes (doppio)
{
  vm_statistics_data_t vmStats;
  il mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
  il kern_return_t kernReturn = host_statistics (mach_host_self (), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);

  se (kernReturn! = KERN_SUCCESS)
  {
    restituisca NSNotFound;
  }

  ritorni (vm_page_size * vmStats.free_count);
}

+ getAvailableKiloBytes (doppio)
{
  ritorni [CCDirector getAvailableBytes] / 1024.0;
}

+ getAvailableMegaBytes (doppio)
{
  ritorni [CCDirector getAvailableKiloBytes] / 1024.0;
}

[...]

- (vuoto) showFPS
{
  strutture ++;
  l'accumDt + = dt;

  se (accumDt> CC_DIRECTOR_FPS_INTERVAL)  {
    frameRate = frames/accumDt;
    strutture = 0;
    accumDt = 0;

    //l'unico cambiamento in showFPS è questa linea:
    Il NSString *str = [[NSString alloc] initWithFormat:@" il %.1f  il %.1f", frameRate, [CCDirector getAvailableMegaBytes]];

    [Il FPSLabel setString:str];
    [rilascio di str];
  }
}

Sollevamento di coscienza a Scene perdenti

Inoltre molto, fortemente e con rinforzo massimo (senza tirare fuori un'arma) raccomando a progettisti cocos2d di controllare frequentemente metodi dealloc della Sua scena. Preferibilmente aggiunga un punto di arresto di una esecuzione là, o come minimo aggiunga la linea di taglio e trasporto dei tronchi: CCLOG (”dealloc: il %”, stesso). Se Lei vuole un metodo più visibile ma meno importuno Lei poteva fare qualcosa come luccichio dello schermo o interpretazione di un suono ogni volta che l'ultima scena è deallocated, in modo che Lei diventi così solito di questo che quando Lei non lo sta vedendo o sentendo più questo immediatamente alza la Sua attenzione. CCLOG(@”dealloc: %@”, self). If you want a more visible but less intrusive method you could do something like flashing the screen or playing a sound whenever the last scene is deallocated, so that you get so used to it that when you’re not seeing or hearing it anymore it immediately raises your attention.

Se in qualsiasi momento durante lo sviluppo del Suo progetto il metodo dealloc di una scena non è chiamato quando Lei cambia scene, Lei sta perdendo la memoria. Fuoriuscita della scena intera è una perdita di memoria del genere più cattivo. Lei vuole prendere questo presto mentre Lei può ancora ripercorrere i Suoi passi che potrebbero aver causato il problema. Appena Lei arriva a utilizzazione di centinaia di beni e migliaia di linee di codice e poi si rende conto che la scena non è deallocated, Lei sarà in per un giro divertente che prova a riuscire a capire dove questo sta venendo da. In quel caso, togliendo nodi infacendoli commenti finché Lei possa avvicinarsi la colpevole è probabilmente la strategia migliore, vicino a utilizzazione di Strumenti (che non ho trovato troppo utile in quei casi). You want to catch that early while you can still retrace your steps that might have caused the problem. Once you get to using hundreds of assets and thousands of lines of code and then realize the scene isn’t deallocated, you’ll be in for a fun ride trying to figure out where that’s coming from. In that case, removing nodes by uncommenting them until you can close in on the culprit is probably the best strategy, next to using Instruments (which I haven’t found too helpful in those cases).

Collisi con un tal problema come perché passavo l'oggetto di CCScene a subclassi in modo che loro abbiano l'accesso a metodi della scena. La subclasse ritenne la scena e fu derivata da CCNode e aggiunse al CCScene come bambino. Il problema con questo: durante ripulita della scena questo correttamente tolse tutti i nodi di bambino ma alcuni nodi di bambino ancora hanno ritenuto la scena. Per questo il loro metodo dealloc non fu mai chiamato, e a sua volta la scena fu mai deallocated. The problem with that: during cleanup of the scene it correctly removed all child nodes but some of the child nodes still retained the scene. Because of that their dealloc method was never called, and in turn the scene was never deallocated.

15 Risposte a “Sollevamento di coscienza: l'uso di memoria & le perdite”

  1. Barry dice:

    #include
    #import
    #import

    sono vuoti?

    Come devono quelli essere?

    Grazie :)

  2. Steve dice:

    Ehi Steffen,

    Sto avendo alcuni problemi con questa linea:

    il kern_return_t kernReturn = host_statistics (mach_host_self (), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);

    L'acquisizione d'errori che dicono l'ampere è non dichiarata e non ci sono sufficienti parametri.

    Qualche idee?

    Gran articolo a proposito.

  3. Steve dice:

    Grazie per la risposta pronta.

    Lavori grandi!

  4. Shelton dice:

    Il gran posto, sto avendo lo stesso problema con il mio progetto. Ho CCLayers multiplo. Lo strato di gioco di gioco è un bambino della scena e gli altri strati sono un bambino dello strato principale. The game play layer is a child of the scene and the other layers are a child of the main layer.

    - Un per gioco di gioco
    - Un per pausa, risposta, menù di gioco di fine
    - Un per roba di HUD (il punteggio, la salute, eccetera)
    - Un per animazioni di potere su

    E dopo interpretazione di giochi multipli nella stessa seduta la mia memoria alloc qualche volta salterà sebbene il tetto sostituendo scene e alla fine faccia il gioco a pezzi. Voglio tenere gli strati perché sto compiendo azioni come appassimento dello strato intero.

    Comunque non posso trovare un esempio di codice decente da qualche parte che mostra come a in modo conveniente alloc e rilasciano strati multipli in una scena. Sa Lei d'alcuno?

    - L'aspettare del libro, Grazie.

    • GamingHorror dice:

      Se Lei conta su meccanismo di direzione di memoria cocos2d’s Lei solo ha bisogno di togliere lo strato dal suo genitore:

      Lo strato di CCLayer* = [il nodo di CCLayer];
      [stesso addChild:layer];

      //più tardi
      [stesso removeChild:layer];

      Lei deve usare alloc/retain solo possibile programmando con cocos2d.

      Per quello che è che vale spiegai l'uso di parecchi strati nella stessa scena nel libro, e in generale come lavorare con Scene e Strati. È il Capitolo 5 e adesso disponibile nel programma d'Alfa.

      • Shelton dice:

        Grazie, che fu certamente la parte del problema. Anche dimenticai di improgrammare e aggiornare il metodo. Ho la mia memoria indietro. :) I have my memory back. :)

  5. Ashu dice:

    Ciao,

    Tante grazie per il Suo seminario universitario sotto la guida di un tutor meraviglioso. Sto di fronte a problema di memoria e seriamente ho bisogno di un po' di consiglio adesso :(

    Le mie funzioni di de-alloc sono chiamate. Controllo ogni oggetto che creai è de-alloced. Comunque quando mai inizio il gioco di nuovo da menù principale, la dimostrazione di strumento la memoria supplementare di 120 megabyte. Leggevo in linea che lo strumento non può essere perfetto la maggior parte dei tempi, è là alcune installazioni, ho bisogno di cambiare? However when ever I start the game again from main menu, the instrument show additional memory of 120MB. I was reading online that instrument can’t be perfect most of the times, is there some settings, I need to change?

    Qualsiasi consiglio sarà molto apprezzato.

    POSCRITTO: sto chiedendo se l'oggetto è de-alloced prendendo "il banco del riferimento" dopo [dealloc fantastici] amd il rilascio sono chiamati.

    Grazie.

  6. Alexis E. dice:

    Ricevei la perdita su folletti di bambini..

    quando aggiungo molto bambino su un folletto [il folletto addChild:another il folletto];

    ci saranno perdite su [[i bambini alloc] initwithcapacity:4 – non sicure

    ma questo fa un salto fuori sull'attrezzo di perdita,

    quello che debba io fare..?

    mi aiuti in un momento di difficoltà per favore

    • È questo nel Suo codice:
      [[i bambini alloc] initwithcapacity:4]

      Questo sembra quello che sarebbe la parte di Cocos2D. Se è, è una perdita nel motore. Ma dubito che dall'attrezzo di perdita (gli Strumenti?) spesso riferisce di negative false. Finchè la memoria perdè è soltanto alcuni byte (di solito 16 a 64 byte) che non deve essere un problema. But I doubt that since the leak tool (Instruments?) often reports false negatives. As long as the memory leaked is just a few bytes (usually 16 to 64 bytes) that shouldn’t be an issue.

  7. David dice:

    Questo non lavora con il cocos2d ultimo v0.99.5-rc1, può investigarlo Lei?

  8. David dice:

    Fissai il problema per questo, c'è solo una piccola cosa cambiare dentro questa linea:

    Il NSString *str = [[NSString alloc] initWithFormat: ”%. 1f il %.1f”, frameRate, [CCDirector getAvailableMegaBytes]];1f %.1f”, frameRate, [CCDirector getAvailableMegaBytes]];

    Cambi con questo:

    Il NSString *str = [[NSString alloc] initWithFormat: ”%. 1f il %.1f”, frameRate _, [CCDirector getAvailableMegaBytes]];1f %.1f”, frameRate_, [CCDirector getAvailableMegaBytes]];

    L'unico cambiamento fu il sottolineare a frameRate_

    questo mi diede un po' di mal di testa all'inizio ma allora realizzai che semplice fu …

Lasci una Risposta