Heim > Backend-Entwicklung > C++ > Hauptteil

Schreiben Sie Ihren eigenen Speicherpool-Allokator in C

Linda Hamilton
Freigeben: 2024-11-20 03:33:02
Original
802 Leute haben es durchsucht

Writing Your Own Memory Pool Allocator in C

Schreiben Sie Ihren eigenen Speicherpool-Allokator in C: Eine Schritt-für-Schritt-Anleitung

In C ist die dynamische Speicherverwaltung ein entscheidender Aspekt bei der Entwicklung effizienter Software, insbesondere bei leistungskritischen Anwendungen. Während Funktionen wie malloc() und free() in der Standardbibliothek häufig verwendet werden, bringen sie bei häufigem Aufruf Mehraufwand und Einschränkungen mit sich, wie z. B. Fragmentierung und langsamere Zuordnungszeiten. Eine Lösung für diese Probleme ist die Erstellung eines Speicherpool-Allokators.

In diesem Blog zeigen wir Ihnen, wie Sie einen einfachen Speicherpool-Zuordner von Grund auf in C schreiben. Durch die Verwendung eines Speicherpools können wir einen großen Speicherblock vorab zuweisen und ihn manuell verwalten, wodurch die Fragmentierung reduziert und der Speicher verbessert wird Allokationsleistung.

? Bleiben Sie auf Twitter(X) im Gespräch: @trish_07

Was ist ein Speicherpool-Allokator?

Ein Speicherpoolzuweiser ist eine benutzerdefinierte Speicherverwaltungsstrategie, bei der ein großer Speicherblock vorab zugewiesen wird und kleinere Teile davon nach Bedarf an das Programm übergeben werden. Wenn der Speicher nicht mehr benötigt wird, wird er zur Wiederverwendung an den Pool zurückgegeben. Dieser Ansatz ermöglicht eine schnellere Zuweisung und Freigabe als die direkte Verwendung von malloc() und free() sowie eine bessere Speichernutzung.

So funktioniert ein einfacher Speicherpool:

  • Reservieren Sie vorab einen großen Speicherblock.
  • Teilen Sie diesen Block in kleinere Stücke (Blöcke).
  • Verfolgen Sie die nicht verwendeten Blöcke in einer kostenlosen Liste.
  • Wenn ein Block angefordert wird, weisen Sie ihn aus dem Pool zu und geben Sie ihn an den Aufrufer zurück.
  • Wenn ein Block freigegeben wird, geben Sie ihn in den Pool zurück.

Schritt 1: Definieren Sie die Speicherpoolstruktur

Wir beginnen mit der Definition einer einfachen Struktur für den Speicherpool und die darin enthaltenen Blöcke. Jeder Block verfügt über einen Zeiger auf den nächsten Block in der freien Liste, wodurch wir schnell Speicher zuweisen und freigeben können.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

#define POOL_SIZE 1024  // Total memory pool size

// Define a block structure with a pointer to the next free block
typedef struct Block {
    struct Block *next;
} Block;

// Define the MemoryPool structure
typedef struct {
    Block *freeList;
    unsigned char pool[POOL_SIZE]; // Pre-allocated pool
} MemoryPool;
Nach dem Login kopieren
Nach dem Login kopieren

In diesem Code:

  • POOL_SIZE ist die Gesamtgröße des Speicherpools. Wir werden ein statisches Array zuweisen, um den Pool zu simulieren.
  • Die Blockstruktur stellt einen einzelnen Speicherblock dar und enthält einen Zeiger (next), der ihn mit dem nächsten Block in der freien Liste verknüpft.
  • Die MemoryPool-Struktur enthält den freeList-Zeiger (der freie Blöcke verfolgt) und ein Pool-Array, das den tatsächlichen vorab zugewiesenen Speicher enthält.

Schritt 2: Initialisieren Sie den Speicherpool

Um den Speicherpool zu initialisieren, müssen wir den Pool in Blöcke unterteilen und die freie Liste einrichten. Jeder Block sollte auf den nächsten freien Block verweisen.

void initMemoryPool(MemoryPool *pool) {
    pool->freeList = (Block *)pool->pool;
    Block *current = pool->freeList;

    // Create a free list of blocks
    for (int i = 0; i < (POOL_SIZE / sizeof(Block)) - 1; i++) {
        current->next = (Block *)((unsigned char *)current + sizeof(Block));
        current = current->next;
    }

    current->next = NULL; // Last block points to NULL
}
Nach dem Login kopieren
Nach dem Login kopieren

In dieser Funktion:

  • Wir initialisieren die freeList so, dass sie auf den Anfang des Pools zeigt.
  • Wir durchlaufen dann den Pool und setzen den nächsten Zeiger jedes Blocks auf den nächsten im Speicher.
  • Schließlich zeigt der letzte Block auf NULL, um das Ende der freien Liste anzuzeigen.

Schritt 3: Zuweisen von Speicher aus dem Pool

Um Speicher zuzuweisen, müssen wir den ersten verfügbaren Block aus der freien Liste abrufen. Sobald wir einen Block zugewiesen haben, entfernen wir ihn aus der freien Liste.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

#define POOL_SIZE 1024  // Total memory pool size

// Define a block structure with a pointer to the next free block
typedef struct Block {
    struct Block *next;
} Block;

// Define the MemoryPool structure
typedef struct {
    Block *freeList;
    unsigned char pool[POOL_SIZE]; // Pre-allocated pool
} MemoryPool;
Nach dem Login kopieren
Nach dem Login kopieren

Diese Funktion prüft, ob die freie Liste leer ist. Wenn nicht, nimmt es den ersten freien Block, entfernt ihn aus der freien Liste und gibt ihn an den Aufrufer zurück.

Schritt 4: Speicher freigeben und wieder zum Pool hinzufügen

Wenn Speicher freigegeben wird, geben wir den Block in die Liste der freien Speicher zurück. Dadurch kann es für zukünftige Zuweisungen wiederverwendet werden.

void initMemoryPool(MemoryPool *pool) {
    pool->freeList = (Block *)pool->pool;
    Block *current = pool->freeList;

    // Create a free list of blocks
    for (int i = 0; i < (POOL_SIZE / sizeof(Block)) - 1; i++) {
        current->next = (Block *)((unsigned char *)current + sizeof(Block));
        current = current->next;
    }

    current->next = NULL; // Last block points to NULL
}
Nach dem Login kopieren
Nach dem Login kopieren

Hier fügen wir den freigegebenen Block an den Anfang der freien Liste hinzu, indem wir seinen nächsten Zeiger auf den aktuellen ersten Block in der freien Liste setzen. Dadurch kann der Block in Zukunft wiederverwendet werden.

Schritt 5: Beispielverwendung

Da wir nun alle notwendigen Funktionen haben, lasst uns alles zusammenfügen und unseren Speicherpool-Allokator testen.

void *allocateMemory(MemoryPool *pool) {
    if (pool->freeList == NULL) {
        printf("Memory pool exhausted!\n");
        return NULL;
    }

    // Get the first free block
    Block *block = pool->freeList;
    pool->freeList = block->next; // Move the free list pointer

    return (void *)block;
}
Nach dem Login kopieren

In diesem Beispiel:

  • Wir initialisieren den Speicherpool mit initMemoryPool().
  • Wir weisen dann zwei Blöcke mit allocateMemory() zu.
  • Zuletzt geben wir die Blöcke mit freeMemory() frei.

Wenn Sie dieses Programm ausführen, sollten Sie eine Ausgabe ähnlich dieser sehen:

void freeMemory(MemoryPool *pool, void *ptr) {
    Block *block = (Block *)ptr;
    block->next = pool->freeList; // Add the block to the free list
    pool->freeList = block;
}
Nach dem Login kopieren

Warum einen Speicherpool verwenden?

  1. Leistung: Speicherpools sind in der Regel schneller als der wiederholte Aufruf von malloc() und free(), da der Overhead der Speicherverwaltung auf Systemebene minimiert wird.
  2. Fragmentierung vermeiden: Speicherpools helfen, Fragmentierung zu vermeiden, indem sie Speicherblöcke mit fester Größe zuweisen.
  3. Vorhersagbarkeit: Die Speicherzuweisung wird vorhersehbar, da das Programm die Zuweisung und Freigabe steuert.

Speicherpools sind besonders nützlich in Echtzeitsystemen, eingebetteten Systemen und Spielen, bei denen niedrige Latenz und Speichereffizienz von entscheidender Bedeutung sind.

Abschluss

Das Schreiben eines eigenen Speicherpool-Allokators kann die Speicherverwaltung für leistungskritische Anwendungen erheblich optimieren. Durch die direkte Speicherverwaltung können Sie die Zuweisungsgeschwindigkeit verbessern, die Fragmentierung reduzieren und mehr Kontrolle darüber erlangen, wie der Speicher in Ihrem Programm verwendet wird. Dieses Beispiel ist zwar grundlegend, Sie können es jedoch um zusätzliche Funktionen erweitern, z. B. unterschiedliche Blockgrößen oder threadsichere Speicherzuweisung.

Wenn Sie an einem Projekt arbeiten, das eine effiziente Speicherverwaltung erfordert, sollten Sie die Implementierung eines eigenen Speicherpools in Betracht ziehen. Dies ist eine großartige Möglichkeit, tiefer in die Speicherverwaltung einzutauchen und die Leistung Ihrer Anwendung zu verbessern.


Wenn Sie Fragen haben oder weitere Erläuterungen benötigen, können Sie sich jederzeit an uns wenden. Viel Spaß beim Codieren! ?

Das obige ist der detaillierte Inhalt vonSchreiben Sie Ihren eigenen Speicherpool-Allokator in C. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage