Compattazione heap memory

di il
13 risposte

Compattazione heap memory

Negli ultimi mesi mi sono cimentato nelle basi della programmazione in c++, e in particolare in questo momento mi sto dedicando all'approfondimento di alcuni concetti legati alla gestione dell'heap.

In particolare però mi sono posto come quesito su come il compilatore scegliesse la posizione di memoria nel quale allocare il blocco in questione, dopo alcune letture mi sembra di aver capito che semplicemente esso lo posizioni nella prima zona di memoria libera sufficientemente grande.
A questo punto ho deciso di analizzare come il compilatore eliminasse i blocchi di memoria dall'heap, che per quello che penso di aver capito semplicemente li toglie, senza tante operazioni di spostamento degli altri blocchi, creando così dei "buchi" (perdonatemi il termine ma non saprei come spiegarmi altrimenti) nella memoria.

Il mio quesito è se ci sia un modo per compattare (chiedo perdono anche qui per il termine) questi buchi in quanto ho provato a scrivere qualche riga di codice ma non trovo un modo per riconoscere le zone vuote (a meno che io non utilizzi una funzione differente rispetto a delete, richiedendo come argomenti la dimensione e un puntatore identificativi del blocco ed eseguendo al momento la compattazione).

Spero non sia una richiesta troppo stupida e vi ringrazio per l'aiuto in anticipo.

13 Risposte

  • Re: Compattazione heap memory

    Scusa, ma stai parlando di una struttura heap simulata dal tuo programma o della reale area heap del sistema? Vorresti "compattare" da un programma C/C++ l'area heap del sistema operativo?
  • Re: Compattazione heap memory

    È il sistema operativo che gestisce lo heap, non il compilatore.

    Se è per scopi didattici puoi vedere i sorgenti di freeRTOS, che ha 5 modelli di gestione heap tutti abbastanza semplici
    https://www.freertos.org/a00111.htm

    Se vuoi far da solo, allo startup chiedi tipo 500 MB al sistema operativo e poi te la vedi tu...
  • Re: Compattazione heap memory

    La richiesta non è stupida, si chiama frammentazione interna della memoria. Però è molto meno sensibile di una volta, poiché il pool di indirizzi è virtualizzato e paginato praticamente in ogni caso.
    Quando poi si hanno processi a 64 bit il range di indirizzi è talmente grande da non dare problemi particolari.

    Comunque l'osservazione è giusta e la conclusione pure: non esiste in C e C++ un qualcosa in grado di deframmentare lo help (in certi casi sì ma non appesantisco).

    D'altronde la memoria 'non esiste'
  • Re: Compattazione heap memory

    La richiesta di compattazione dell'heap di sistema da parte di un programma utente è peregrina.

    La questione è sicuramente un problema (con sistemi a 32 bit) dato che è possibile che vengano esauriti indirizzi contigui sufficienti assegnabili ad un processo per problemi di frammentazione. Mi è capitato in un mio (gruppo) di programmi che facevano largo uso di memoria in quantità e momenti non facilmente prevedibili.
  • Re: Compattazione heap memory

    Weierstrass ha scritto:


    È il sistema operativo che gestisce lo heap, non il compilatore.

    Se è per scopi didattici puoi vedere i sorgenti di freeRTOS, che ha 5 modelli di gestione heap tutti abbastanza semplici
    https://www.freertos.org/a00111.htm

    Se vuoi far da solo, allo startup chiedi tipo 500 MB al sistema operativo e poi te la vedi tu...
    Prima di tutto grazie mille per il chiarimento riguardo cosa si occupasse di queste allocazioni.
    Io in un primo momento avevo intenzione di fare da solo, ma dopo aver fatto qualche tentativo ho capito di non avere idea di come individuare questi "buchi" di memoria (ah se riusciste a suggerirmi un termine migliore ne sarei grato) utilizzando le librerie standard, per cui penso darò un occhiata ai codici sorgenti a cui si riferisce il sito (anche se mi sembrano un po' troppo avanzati per quello che so in questo momento, anzi penso proprio di essermi imbarcato in una ricerca più grande di me).

    Comunque ti ringrazio di nuovo per l'aiuto
  • Re: Compattazione heap memory

    Ma forse non ti è chiaro che non lo puoi fare con un programma che non sia parte integrante del sistema operativo con i diritti dello stesso.
  • Re: Compattazione heap memory

    oregon ha scritto:


    Ma forse non ti è chiaro che non lo puoi fare con un programma che non sia parte integrante del sistema operativo con i diritti dello stesso.
    Ecco infatti, ne ero convinto perchè pensavo fosse una parte gestita dal compilatore, ma essendo gestita dal sistema operativo stesso ciò naturalmente non vale;
    chiedo venia
  • Re: Compattazione heap memory

    +m2+ ha scritto:


    La richiesta non è stupida, si chiama frammentazione interna della memoria. Però è molto meno sensibile di una volta, poiché il pool di indirizzi è virtualizzato e paginato praticamente in ogni caso.
    Quando poi si hanno processi a 64 bit il range di indirizzi è talmente grande da non dare problemi particolari.

    Comunque l'osservazione è giusta e la conclusione pure: non esiste in C e C++ un qualcosa in grado di deframmentare lo help (in certi casi sì ma non appesantisco).

    D'altronde la memoria 'non esiste'
    Penso di non aver capito il concetto finale
  • Re: Compattazione heap memory

    oregon ha scritto:


    La richiesta di compattazione dell'heap di sistema da parte di un programma utente è peregrina.

    La questione è sicuramente un problema (con sistemi a 32 bit) dato che è possibile che vengano esauriti indirizzi contigui sufficienti assegnabili ad un processo per problemi di frammentazione. Mi è capitato in un mio (gruppo) di programmi che facevano largo uso di memoria in quantità e momenti non facilmente prevedibili.
    infatti non ne ho bisogno effettivamente, perchè come dicevate anche voi prima con il genere di programmi che scrivo (in genere molto didattici e legati al mio apprendimento)è pressochè impossibile esaurire lo spazio, però diciamo che mi è venuto il dubbio e volevo approfondirlo visto che mi ha abbastanza stimolato.
  • Re: Compattazione heap memory

    I processi hanno una loro memoria,che però non esiste, nel senso che in un sistema operativo moderno non c'è una mappa 1:1 tra un blocco di memoria del programma e una parte della ram del computer.
    I processi "vedono" una memoria lineare (in realtà è segmenta comunque su architettura intel ma lasciamo stare) che viene divisa in un certo numero di pagine (spesso ma non sempre di 4KB) le quali possono essere in RAM oppure no (tipicamente swap file).
    Non posso fare uno spiegone sul funzionamento di un sistema operativo moderno, è però un argomento affascinante e fonte spesso di sorprese.

    Se poi si conosce lo sviluppo dalla modalità reale, i salti nell' iperspazio (win 95) , il modello i386, poi IA64 e così via ancora meglio.
    Magari completando con la tipologia di motorola, poi PowerPC e magari Alpha e poi ARM.

    Versione breve: è molto, ma molto più complesso di come si possa pensare
  • Re: Compattazione heap memory

    Hai quindi due frammentazioni.
    Quella interna, dovuta al fatto che la memoria è allocata in blocchi (pagine di solito)
    Quella esterna, dovuta ai buchi creati da allocazione e deallocazione.
    Nel secondo caso ci sono vari algoritmi per scegliere dove allocare la memoria richiesta, ma il problema permane (dal punto di vista logico) ma potrebbe non esserlo in concreto, proprio perché è il sistema operativo che fa 'pensare' al programma di dargli qualcosa (una sequenza monotona di indirizzi) che potrebbe non esserci in realtà.
    Per ragioni di prestazioni (località caricamento cache) e anche di spazio (dimensioni tabelle) tutto può accadere, lato SO

    Tutto chiaro? Non credo ma troverai millemila spiegoni su internet
  • Re: Compattazione heap memory

    La gestione della memoria e' forse l'aspetto PIU' COMPLESSO nella realizzazione di un programma poiche' l'efficienza/inefficienza della sua gestione ha un impatto DIRETTO sulle performance dell'applicazione stessa.

    Invece di andare a casaccio, ci sono almeno 2 fonti autorevoli a cui fare riferimento:

    1) The Art of Computer Programming, Volume 1, Capitoro 2: Dinamyc Storage Allocation
    2) Garbage Collection: Algorithms for Automatic Dynamic Memory Management

    per non parlare del gestore della memoria a livello hardware, usato dal sistema operativo (memoria segmentata, virtuale, paginazione, ...)
    e del gestore della memoria del sistema operativo che la deve distribuire tra i vari processi, perche' COMUNQUE la memoria fisica e' quella installata e basta.

    Per il C/C++ esiste una buona implementazione di un garbage collector:

    https://en.wikipedia.org/wiki/Boehm_garbage_collecto
    https://www.hboehm.info/gc

    La possibilita' di ""compattare"" la memoria richiede un'infrastruttura abbastanza complicata.
    Il problema e' questo:

    -- non c'e' modo di sapere dove sono i puntatori che puntato ad una certa area di memoria.

    Quindi, se questa viene spostata, non c'e' modo di aggiornare tutti i puntatori.

    Una soluzione e' questa:

    1) esiste un ""INDICE"" di TUTTI i blocchi di memoria allocati
    2) i puntatori NON PUNTATO DIRETTAMENTE al blocco di memoria, MA tengono traccia SOLO dello SLOT all'interno dell'indice che contiene il puntatore al bocco di memoria a cui si e' interessati
    3) l'accesso ad un'area di memoria richiede DUE accessi: p:puntatore -> slots[p] -> area allocata
    4) la memoria puo' essere compattata perche' TUTTI i blocchi di memoria sono registrarti nell'INDICE (e SOLO QUI) e questo e' l'UNICO ad essere aggiornato quando i blocchi vengono mossi da una locazione di memoria all'altra
    5) quando un blocco si libera, e' sufficiente indicare nell'indice che il corrispondente slot e' libero, oltre al fatto che anche il blocco e' libero
    6) quando si alloca un nuovo blocco di memoria, si puo' fare una ricerca del primo slot libero ed usarlo per registrare la posizione del blocco di memoria
    7) l'indice contiene le informazioni sui blocchi allocati e liberi, e quindi e' l'operazione di compattazione risulta molto semplice.

    Dopo un po', OVVIAMENTE, sara' l'indice diventare come un gruviera, MA

    1) l'indice NON PUO' ESSERE compattato per lo stesso problema iniziale
    2) l'indice e' una struttura dati di dimensioni limitate e quindi la quantita' di memoria persa e' accettabile
    3) ci sono strategie inteligenti per mantenere traccia degli slot liberi

    C'e' un'altro BANALE problema:tempi di esecuzione, che NON SONO certamente dell'ordine dei millisecondi.

    Comunque, l'approccio e' praticamente lo stesso della deframmentazione del disco.

    -------------------------

    L'accesso alle strutture dati interne del gestore della memoria del C/C++ non sono pubblicamente accessibili.
    Comunque esistono librerie di terze parti in sorgente e i sorgenti del runtime a cui puo fare riferimento.

    https://en.wikipedia.org/wiki/Dmallo
    https://dmalloc.com

    https://en.wikipedia.org/wiki/C_dynamic_memory_allocation

    -------------------------

    Per quanto riguarda Windows & C++ ci sono DUE tipi di heap:
    1) l'heap gestito dal sistema operativo, che puo' essere manipolat mediante le API di windows, ma che DEVE essere usato per allocare GRANDI blocchi di memoria (qualche megabyte, NON CERTAMENTE bytes)
    2) l'heap gestito dal GESTORE DELLA MEMORIA del linguaggio di programmazione usato il quale ha il compito di fare l'allocazione fine, cioe' soddisfare la singola richiesta dell'applicazione.

    Quando l'heap del gestore della memoria e' terminato, l'applicazione richiede un nuovo blocco al sistema (qualche centinaio di kilobyte/megabyte) operativo.
  • Re: Compattazione heap memory

    Vi ringrazio tutti per le esaustive risposte, evidentemente mi sono imbarcato in una ricerca che è superiore alle mie capacità attuali, in ogni caso penso di avere capito il concetto di fondo e passerò senz'altro un po' di tempo ad arrovellarmi sulle fonti che mi avete condiviso...

    grazie di nuovo
Devi accedere o registrarti per scrivere nel forum
13 risposte