Distributore autonomo

- Jun 25, 2018-

Uno dei motivi principali per definire un allocatore personalizzato è il miglioramento delle prestazioni. L'utilizzo di un allocatore personalizzato dedicato può migliorare le prestazioni del programma o migliorare l'efficienza di utilizzo della memoria o entrambe. L'allocatore predefinito utilizza il nuovo operatore per allocare lo spazio di archiviazione, che viene spesso implementato utilizzando la funzione di allocazione dell'heap del linguaggio C (malloc ()). Poiché la funzione di allocazione dell'heap è spesso ottimizzata per allocazioni di memoria sporadiche, l'allocatore predefinito è generalmente efficiente quando si alloca memoria per contenitori che devono allocare grandi quantità di memoria contemporaneamente (ad esempio, vettore, deque). Tuttavia, per i contenitori associativi e gli elenchi doppiamente collegati, che devono allocare una piccola quantità di memoria frequentemente, se l'allocatore predefinito alloca la memoria, di solito è inefficiente. Inoltre, l'allocatore predefinito basato su malloc () ha molti problemi, come una scarsa localizzazione referenziale, e può causare la frammentazione della memoria.

In considerazione di ciò, in questo caso, le persone utilizzano spesso allocatori basati su pool di memoria per risolvere il problema delle frequenti piccole allocazioni. A differenza del metodo predefinito "assegnazione su richiesta", quando si utilizza un allocatore basato su pool di memoria, il programma allocherà una grande quantità di memoria ("pool di memoria") in anticipo, e quindi quando è necessario allocare memoria, l'allocatore personalizzato solo A puntatore alla memoria nel pool deve essere restituito al richiedente. Quando l'oggetto viene distrutto, non è necessario effettivamente deallocare la memoria. Invece, la vera deallocazione viene ritardata fino alla fine del ciclo di vita del pool di memoria.

Sull'argomento "Dispenser personalizzato", molti esperti di C ++ e autori correlati hanno già partecipato a discussioni, come "Effective STL" di Scott Meyers e "Modern C + + Design" di Andre Alexandre Rescu è stato menzionato. Meyers ritiene che se tutte le istanze di un distributore per un certo tipo T sono richieste per essere uguali, le istanze di distributori portatili non devono contenere alcuno stato. Sebbene lo standard C ++ incoraggi gli implementatori di librerie a supportare dispensatori di stato, Meyers ha detto che i paragrafi pertinenti sono "(sembra) un punto di vista meraviglioso", ma sono parole quasi vuote e affermano che le restrizioni del distributore sono "troppo dure". Ad esempio, l'elenco di STL consente il metodo di giunzione, ovvero un nodo dell'elenco oggetto A può essere spostato direttamente in un altro oggetto di elenco B. Ciò richiede che la memoria allocata dall'allocatore di A possa essere liberata dall'allocatore di B, derivando così le istanze di distributore per A e B devono essere uguali. Myers conclude che il distributore è definito al meglio come un tipo che utilizza metodi statici. Ad esempio, secondo lo standard C ++, gli allocatori devono fornire un modello di altra classe che implementa il metodo rebind.

Inoltre, nel "Linguaggio di programmazione C + +", Bianni Strawstrup crede che "'limitare strettamente il distributore, in modo da non diffondere informazioni su ciascun oggetto', questo ovviamente non è un problema" (per l'effetto), e viene sottolineato che la maggior parte dei distributori non ha bisogno di stato, e anche se non c'è stato, le prestazioni sono migliori. Ha proposto tre casi d'uso del dispensatore personalizzato: un tipo di pool di memoria, un tipo di memoria condivisa e un tipo di garbage collection e ha dimostrato l'implementazione di uno splitter, utilizzando un pool di memoria interno per essere più veloce. Assegna / Deallocate una piccola quantità di memoria. Tuttavia, ha anche detto che tale ottimizzazione potrebbe essere stata implementata nel distributore campione che ha fornito.

Un altro utilizzo dell'allocatore personalizzato è il debug degli errori relativi alla memoria. Per fare ciò, è possibile scrivere un allocatore che alloca memoria aggiuntiva quando viene allocato e lo utilizza per memorizzare le informazioni di debug. Questo tipo di allocatore non solo garantisce che la memoria sia allocata / de-allocata dallo stesso tipo di allocatore, ma protegge anche il programma dall'overflow del buffer in una certa misura.