È sicuramente una domanda che potrebbe sembrare vaga ad alcuni;)
Ma penso di sapere da dove vieni.
Hai un milione di scelte su come potresti scegliere di implementarlo. Alcune di queste scelte dovrebbero riguardare sia le piattaforme target sia gli obiettivi generali di progettazione. Queste considerazioni spezzeranno ogni legame, fino a quando non ti sentirai abbastanza a tuo agio con costi di implementazione diversi abbastanza da far crescere prima il design dalla piattaforma e le preoccupazioni generali di design. Quindi fino ad allora, ecco alcuni modi che non ti costeranno in termini di complessità (onere di gestione) o di gestione della rimozione o dei cambiamenti se cambi idea ...
Se l'obiettivo è misurare e allocare, con la possibilità di utilizzare i pool, è necessario innanzitutto pensare al set minimo di codice vivibile per iniziare. Per motivi di spiegazione, se sei parziale alle classi, puoi creare una classe, lasciare che rappresenti un heap o utilizzare invece un set di funzioni che prendono un handle o un nome di heap. È davvero un problema di semantica per essere onesti. La prossima decisione è nuova o malloc; Sono parziale di malloc perché molte volte ho a che fare con costrutti di basso livello e so nella maggior parte delle implementazioni che i nuovi chiamano malloc e non devo preoccuparmi della complessità del sovraccarico di nuovi e di preoccuparmi di ciò su tutte le piattaforme . Tuttavia, molte volte ho costruito sistemi o componenti per sovraccaricare o collegare nuovi. E ovviamente il problema principale o la differenza, è che "nuovo" deve conoscere il tipo prima dell'allocazione, dove a "malloc" non importa e con malloc si risolve in un tipo dopo l'allocazione. Tutto quel dettaglio è darti un'idea e un po 'di contesto per prendere decisioni di progettazione in questi tipi è importante :)
Quindi sceglierò classe e malloc, perché è più facile da spiegare qui, ma alla fine non importa. Gli interni finiranno per portare poca differenza di materiale rispetto al resto del design complessivo.
Quindi, in questo ipotetico, so che (o assumerò che) potrei finire con 7-8 istanze di classe di sottosistemi reali e anticipare centinaia di migliaia di chiamate per allocazione e libero. Dato che gran parte della mia curiosità e della mia vera spinta in tutto questo, riguarda davvero le dimensioni e il profilo, non voglio appesantire le prestazioni dell'app. Per i principianti potrei decidere di lasciare tutto aperto e pubblico fino a quando non lo avrò inchiodato, mentre passo attraverso l'implementazione in tutto il resto dell'app; una struttura lo farà bene. 'S_' indica quali variabili sono chiaramente destinate alla statistica.
struct Mem
{
int s_allocs;
int s_frees;
int s_peak;
int s_current;
void* heap; // if you wanted to go into having real actual separate heaps, else ignore
void* alloc(int size);
void free(void* p);
Mem() {memset(this,0,szieof(Mem));} // want this to be inlined with the call site constructor (a design decision example)
}
class MySubSystem
{
Mem mem;
.... you get the idea
}
Questo è estremamenteleggero su molti fronti, e forse un buon posto per iniziare a perfezionare dove mai davvero hai voluto andare con questo. E hai subito un problema, come fai a sapere le dimensioni dell'articolo liberato. (Questo sarebbe un problema da risolvere per quasi tutti gli approcci.) Dato che si tratta di un forum di gioco, potresti prendere in considerazione il doping dei primi byte con le dimensioni, oppure devi avvolgere o ricordare in qualche altro modo. La maggior parte della sensibilità degli sviluppatori di giochi non dovrebbe essere troppo contro il doping, ed è l'esempio più semplice, considerando che ho già creato un muro di testo. Fondamentalmente va così: non vuoi che possa essere aiutato a distruggere l'allineamento intrinseco, vuoi sapere, quasi gratis, se la dimensione è coerente. Quindi qualcosa di semplice come "s_allocs ++; s_total + = size; uint64 * p = (uint64 *) malloc / calloc (size + = 8); * p = 0xDEADDAED00000000 | dimensione; return p + 1; "dove le allocazioni saranno inferiori a 4 GB e uint64 è qualunque cosa il compilatore ritenga che sia un int senza segno a 64 bit e dove è possibile controllare gratuitamente il valore di integrità.
Questo è tutto un modo per ottenere il minimo indispensabile a un minimo costo che soddisfa i requisiti. Lo fa Nonindirizzare le classi di allocazione che hanno funzioni virtuali se sono nell'ambito della profilazione o della gestione, poiché non si può prevedere la dimensione dell'ambiente c ++ che si sta utilizzando per quelli senza sovraccarico o collegamento di nuovi, oppure se si fa affidamento sul costruttore in uno dei modi strani che non potevano essere gestiti da un'altra funzione "init". Altrimenti uno stuct è una classe è un'allocazione arbitraria ed è lo stesso quando lanci. Se sei parziale con il nuovo e hai bisogno della tabella virtuale intrinseca o della semantica del costruttore, allora devi agganciarne di nuovi, ma quello è un altro "altro animale", che devi davvero studiare per assicurarti di fare ciò che le nuove esigenze e dovrebbero segnalare il tuo codice è nuovo, a cui si applica questo bucket. Ma per il resto il concetto sopra è lo stesso.
Ancora più importante, questo dovrebbe far andare il tuo cervello, e si spera sulla falsariga di ciò di cui hai bisogno e quali sono le tue tolleranze, ora che hai visto un po 'di più dietro il sipario. Non esiste un mago :)