Betrachten wir ein Speichersegment (dessen Größe bei Bedarf wie eine Datei wachsen oder schrumpfen kann), für das Sie zwei grundlegende Speicherzuweisungsoperationen mit Blöcken fester Größe ausführen können:
- Zuweisung eines Blocks
- Freigeben eines zuvor zugewiesenen Blocks, der nicht mehr verwendet wird.
Außerdem darf sich das Speicherverwaltungssystem nicht in aktuell zugewiesenen Blöcken bewegen: Ihr Index / ihre Adresse müssen unverändert bleiben.
Der einfachste Speicherverwaltungsalgorithmus würde einen globalen Zähler (mit dem Anfangswert 0) inkrementieren und seinen neuen Wert als Adresse für die nächste Zuordnung verwenden. Dies wird es jedoch niemals ermöglichen, das Segment zu verkürzen, wenn nur wenige zugewiesene Blöcke übrig bleiben.
Besserer Ansatz: Behalten Sie den Zähler bei, aber führen Sie eine Liste von freigegebenen Blöcken (die in konstanter Zeit ausgeführt werden können) und verwenden Sie ihn als Quelle für neue Zuweisungen, solange er nicht leer ist.
Was nun? Gibt es etwas Kluges, das trotz konstanter Zeitzuweisung und Freigabe der Zuweisung getan werden kann, um das Speichersegment so kurz wie möglich zu halten?
(Ein Ziel könnte sein, den momentan nicht zugewiesenen Block mit der kleinsten Adresse zu verfolgen, aber es scheint nicht in konstanter Zeit machbar zu sein ...)
quelle
Antworten:
Bei Blöcken mit fester Größe ist das, was Sie beschrieben haben, eine freie Liste . Dies ist eine sehr verbreitete Technik mit der folgenden Wendung: Die Liste der freien Blöcke wird in den freien Blöcken selbst gespeichert. In C-Code würde das so aussehen:
Dies funktioniert gut, solange alle zugewiesenen Blöcke dieselbe Größe haben und diese Größe ein Vielfaches der Größe eines Zeigers ist, sodass die Ausrichtung erhalten bleibt. Zuweisung und Freigabe erfolgen in konstanter Zeit (dh so konstant wie Speicherzugriffe und elementare Ergänzungen). In einem modernen Computer kann ein Speicherzugriff Cachefehler und sogar virtuellen Speicher, also Festplattenzugriffe, zur Folge haben. kann ziemlich groß sein). Es gibt keinen Speicheraufwand (keine zusätzlichen Zeiger pro Block oder ähnliches; die zugewiesenen Blöcke sind zusammenhängend). Außerdem erreicht der Zuweisungszeiger nur dann einen bestimmten Punkt, wenn zu einem Zeitpunkt so viele Blöcke zugewiesen werden mussten: Da die Zuweisung die freie Liste bevorzugt, wird der Zuweisungszeiger nur erhöht, wenn der Raum unter dem aktuellen Zeiger taktvoll ist. In diesem Sinne, Technik.
AbnehmendDer Zuweisungszeiger nach einer Freigabe kann komplexer sein, da freie Blöcke nur durch Befolgen der freien Liste, die sie in unvorhersehbarer Reihenfolge durchläuft, zuverlässig identifiziert werden können. Wenn es für Sie wichtig ist, die Größe des großen Segments nach Möglichkeit zu verringern, können Sie eine alternative Technik mit mehr Overhead verwenden: Zwischen zwei zugewiesenen Blöcken wird ein "Loch" eingefügt. Die Löcher werden mit einer doppelt verknüpften Liste in der Speicherreihenfolge miteinander verknüpft. Sie benötigen ein Datenformat für eine Bohrung, damit Sie die Bohrungsstartadresse ermitteln können, indem Sie wissen, wo sie endet, und auch die Bohrungsgröße, wenn Sie wissen, wo die Bohrung im Speicher beginnt. Wenn Sie dann einen Block freigeben, erstellen Sie eine Bohrung, die Sie mit der nächsten und der vorherigen Bohrung zusammenführen. Dabei wird (noch in konstanter Zeit) die geordnete Liste aller Bohrungen neu erstellt. Der Overhead beträgt dann ungefähr zwei Wörter in Zeigergröße pro zugewiesenem Block; Zu diesem Preis können Sie jedoch zuverlässig das Auftreten eines "endgültigen Lochs" erkennen, dh eine Gelegenheit, die Größe des großen Segments zu verringern.
Es gibt viele mögliche Variationen. Ein gutes Einführungspapier ist Dynamic Storage Allocation: Eine Umfrage und eine kritische Überprüfung von Wilson et al.
quelle
In dieser Antwort geht es um allgemeine Speicherverwaltungstechniken. Ich vermisste, dass die Frage nach dem Fall fragt, in dem alle Blöcke die gleiche Größe haben (und ausgerichtet sind).
Die grundlegenden Strategien, die Sie kennen sollten, sind First-Fit, Next-Fit, Best-Fit und das Buddy-System . Ich habe einmal eine kurze Zusammenfassung für einen Kurs geschrieben, ich hoffe, er ist lesbar. Ich weise dort auf eine ziemlich ausführliche Umfrage hin .
In der Praxis sehen Sie verschiedene Modifikationen dieser Grundstrategien. Aber keine davon ist wirklich konstante Zeit! Ich denke nicht, dass dies im schlimmsten Fall möglich ist, wenn nur wenig Speicherplatz zur Verfügung steht.
quelle
Möglicherweise möchten Sie sich die amortisierte Analyse und insbesondere dynamische Arrays ansehen . Auch wenn die Operationen nicht bei jedem Schritt wirklich in konstanter Zeit ausgeführt werden, sieht es auf lange Sicht so aus, als ob dies der Fall wäre.
quelle