Esistono alternative allo stack + heap + modello di memoria statica?


9

Tutti i programmi che ho visto organizzano la loro memoria di dati in uno o più stack di chiamate (di solito dimensioni fisse, ma a volte no), heap e memoria statica. Anche in questo caso è stata aggiunta una memoria statica locale thread-local.

Ci sono stati tentativi di organizzare il layout della memoria dei dati in modo radicalmente diverso, ad esempio senza lo stack di chiamate? O organizzare la memoria in un modo diverso che compie la stessa cosa?


Dipende da cosa intendi per "pila". È possibile inserire i frame dello stack di chiamate nell'heap (collegarli con i puntatori). Quindi non hai un'area di memoria lineare dedicata per lo stack, ma concettualmente hai ancora uno stack di chiamate.

e dipende da cosa intendi per "recentemente". Penso che l'archiviazione locale dei thread sia vecchia quanto i thread. Ma in precedenza era accessibile tramite chiamate di sistema, mentre ora le nuove lingue ti danno accesso direttamente.
DXM,

Lo stack di chiamate è necessario perché le funzioni procedurali devono sapere chi li ha chiamati in modo da poter restituire risultati e continuare l'esecuzione. L'attuale meccanismo se lo fa è in realtà abbastanza economico in termini di cicli della CPU e con almeno x64, quasi tutti gli argomenti della funzione vengono passati attraverso i registri
James,

2
Potresti trovare il post di Eric Lippert, Why Have a Stack? di interesse. Il suo punto principale è che uno stack fornisce un modo semplice ed efficiente per tenere traccia delle posizioni di memoria. Discute un'alternativa in molti post molto più vecchi, Continuation Passing Style .
Brian,

Risposte:


8

Potresti voler fare un passo indietro e vedere da dove e perché provengono quei modelli esistenti. Quando viene creato un processo, viene semplicemente assegnata un'area di archiviazione piatta che viene semplicemente indicizzata da 0 a N. Poiché questa area di archiviazione (parlando di RAM qui) è supportata da un hardware dedicato e da alcuni semiconduttori fantasiosi sembra essere abbastanza veloce, ma non è l'unico nel suo genere. Altri dispositivi come i dischi rigidi sono essenzialmente la stessa cosa, spazio piatto indirizzabile da un indice, ma molti ordini di grandezza più lenti.

Il motivo per cui esiste un "heap" è perché non sarebbe pratico per ogni applicazione tentare di gestire l'utilizzo della RAM da solo. Nel passato, è esattamente così che è successo, i programmatori hanno pianificato in anticipo esattamente ciò per cui ogni posizione RAM sarebbe stata utilizzata. Man mano che il software diventa più complesso qualcuno ha detto, non sarebbe bello se potessi semplicemente andare in una scatola nera e dire "Ho bisogno di 10 byte così dammi" e non doversi preoccupare di tutti i dettagli intricati di dove e come quei 10 byte provengono o come vengono recuperati. Questo è ciò che è un heap, non diventa davvero più semplice di così.

Ogni volta che viene creato un thread, ci sono alcune strutture di dati (e uno stack), che vengono acquisite usando la stessa "operazione dammi" che ho appena descritto. Uno stack quasi universalmente usato perché si adatta perfettamente ai frame dello stack di chiamate di funzione e alla loro natura LIFO. In teoria, ogni invocazione di funzione e variabili locali potrebbero essere allocate sull'heap, ma sarebbe semplicemente troppo costoso, rispetto a poche istruzioni di assemblaggio necessarie per aggiornare il registro del puntatore dello stack (ESP su x86).

Anche l'archiviazione locale thread (TLS) è costruita in cima all'heap. Quando viene creato un thread, come parte di un viaggio nell'heap per allocare memoria per le strutture di gestione, viene allocato anche uno spazio separato per TLS dall'heap.

Quindi, alla fine, tutto ciò che hai davvero è un allocatore di memoria generico (cioè l'heap) e tutto il resto è un modulo specializzato. In altre parole, se sei disposto a rinunciare a qualche aspetto di "Voglio allocare tutto (o meno) quanto voglio, tienilo per tutto il tempo che voglio e libero quando voglio", potresti fare trading off allocatore di heap generico per un altro modello che offre velocità ma a costo di qualche altra limitazione.

Prendi lo stack. È incredibilmente veloce rispetto all'heap, ma i due compromessi sono 1) che non controlli quando la memoria viene liberata; invece, una volta terminata la funzione, qualunque cosa sia stata allocata scompare e 2) poiché le pile sono generalmente di dimensioni limitate, è necessario prestare molta attenzione nell'allocare grandi quantità di dati direttamente nello stack.

Un altro tipo di "modello di memoria" è il Virtual Memory Manager (VMM) offerto da quasi tutti i principali sistemi operativi tramite chiamate di sistema. VMM è molto simile all'heap, nel senso che puoi richiedere qualsiasi quantità di memoria e conservarla per tutto il tempo che desideri. Tuttavia, la limitazione è che è possibile allocare memoria solo in multipli di dimensioni di pagina (ad es. 4KB), quindi l'utilizzo diretto di VMM causerebbe un notevole sovraccarico in un'applicazione tipica che spesso alloca 8-24 byte alla volta. In effetti, quasi tutte le implementazioni di heap sono costruite su VMM appositamente allo scopo di consentire un'allocazione molto generica, non specializzata, di piccoli blocchi. Heap va su VMM ogni volta che necessita di più memoria e quindi distribuisce all'applicazione molti piccoli blocchi di tale memoria.

Se hai un'app, che ha bisogno di allocare blocchi di grandi dimensioni, potresti prendere in considerazione di andare direttamente a VMM, anche se alcuni heap hanno un'istruzione if all'interno di malloc () e se la dimensione del blocco è maggiore di qualche soglia, passa semplicemente a VMM per te.

Un'altra forma di allocatori invece di utilizzare direttamente l'heap, sarebbero i pool. Un pool è un allocatore specializzato in cui tutti i blocchi hanno le stesse dimensioni. I pool (proprio come stack e TLS) sono basati su heap o VMM. I pool sono utili in luoghi in cui si allocano molti (milioni) oggetti piccoli e di breve durata della stessa dimensione. Pensa a un servizio di rete che elabora le richieste in arrivo. Ogni richiesta client può comportare l'allocazione della stessa struttura N byte per gestire quella richiesta. Il compromesso con l'utilizzo di pool è che ogni pool gestisce solo una dimensione di blocco (ma è possibile creare più pool). Il vantaggio dei pool è che, poiché tutti gli oggetti hanno le stesse dimensioni, non richiede una logica complessa. Invece, ogni volta che hai bisogno di un nuovo blocco, ti dà solo quello che è stato recentemente liberato.

E infine, ricorda quella cosa sul disco rigido che ho citato in alto. Potresti avere un modello di memoria che si comporta come un file system e duplica la stessa idea di voci di directory e i-nodi per consentire l'allocazione gerarchica dei blocchi di dati in cui ciascun blocco di dati viene indirizzato con un percorso. Questo è esattamente ciò che fa tmpfs .

Oltre alle cose che ho citato, sono sicuro che ci sono altri modelli più specializzati, ma alla fine poiché tutto è basato sullo spazio di indirizzamento piatto (cioè fino a quando alcuni genuis non escono con una sorta di spazio strano-a $$ non piatto ), tutto risale all'allocatore "gimme" generico che è VMM o heap.


1

Gli unici casi a cui riesco a pensare sono in hardware specializzato in cui potresti avere tutto in esecuzione in posizioni fisse in memoria. Praticamente tutto ciò che è necessario nell'attuale modello di memoria è necessario se si desidera programmi completamente flessibili.

Senza lo stack non puoi avere variabili locali, chiamare stack, ecc. Qualsiasi altra cosa che scrivi per implementare finirà per assomigliare molto allo stack.

Memoria statica e heap che potresti potenzialmente rilasciare per determinate applicazioni, ma di nuovo ti serviranno di nuovo in un modo o nell'altro per fare qualcosa di più avanzato.

Quindi tutto ciò che inventi per sostituire uno di questi tre finirà per assomigliare molto a uno di questi tre alla fine ...

Per avvicinarlo dall'altra prospettiva, cosa potresti aggiungere di nuovo? Potresti potenzialmente sostenere argomenti come la grafica / i processori di fisica / le cache della cpu / etc sono una nuova posizione di memoria, ma in realtà sono solo un'istanza separata o un modo per accelerare l'accesso ai modelli esistenti.

... quindi fino a quando qualcuno non farà un salto concettuale di qualche tipo, penso che difficilmente vedremo cambiamenti importanti in quest'area per molto tempo ...


4
La maggior parte delle persone tende a supporre che il modo attuale sia il migliore / unico modo, e se gli venisse data una lavagna vuota si limiterebbe a copiare ciò che già esiste. Le altre persone sono quelle che effettivamente avanzano nel progresso tecnologico. Per non dire che io personalmente conosco modelli seri concorrenti (a meno che non si contino i computer quantistici), ma affermando che tutto ciò che si potrebbe inventare sembrerebbe lo stesso di ciò che già esiste è essenzialmente una forma di ragionamento circolare.
Aaronaught il

@Aaronaught: il rovescio della medaglia della tua discussione è che altre persone spendono tonnellate di tempo, denaro ed energia pensando fuori dagli schemi e per ogni 1000 (forse molto di più) di loro, uno potrebbe eventualmente far avanzare il progresso tecnologico, mentre il resto non arriva da nessuna parte . Considerando che il primo gruppo, che si potrebbe considerare più pratico, prende questi modelli esistenti così come sono e li innova al di sopra di essi :)
DXM

@aaronaught Penso di averlo coperto con "così fino a quando qualcuno non farà un salto concettuale di qualche tipo";) Se hai un modello alternativo migliore sentiti libero di suggerirlo ... se no ti senti un po 'ipocrita di cui lamentarti "alcune persone" quando sei uno di loro :)
Tim B,

1
@DXM: Quindi? Ho detto che dovremmo investire tutti il ​​nostro tempo nella ricerca di nuovi modelli di memoria? Stavo solo sottolineando il (significativo) difetto nell'affermazione che una persona può solo inventare cose che sono già state inventate.
Aaronaught il

Un'affermazione che non ho mai fatto ...
Tim B,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.