Wie Funktioniert die Speicherverwaltung Funktionieren in der C#?

0
849

Im Vergleich zu C++, C#’s garbage collector scheint wie Magie, und Sie können sehr leicht code schreiben, ohne sich Gedanken über den zugrunde liegenden Speicher. Aber wenn Sie sich sorgen über die Leistung, das wissen, wie die .NET-runtime verwaltet seinen RAM kann Ihnen helfen, besseren code zu schreiben.

Value Types vs. Reference Types

Es gibt zwei Arten von Typen .NET, die Sie unmittelbar betreffen, wie der zugrunde liegende Speicher behandelt.

Wertetypen werden primitive Typen mit fester Größe wie int, bool, float, double, etc. Sie sind als Wert übergeben, das heißt, wenn Sie rufen someFunction(int arg) das argument ist kopiert und geschickt, wie eine neue Position im Speicher.

Unter der Haube, Wert-Typen sind (in der Regel) auf dem stack gespeichert werden. Dies gilt zumeist um lokale Variablen, und es gibt viele Ausnahmen, wo Sie stattdessen gespeichert werden auf dem heap. Aber in allen Fällen, die Position im Speicher, wo Sie den Wert Typ wohnt, hält den aktuellen Wert der variable.

Der stack ist nur eine Besondere Position im Speicher, initialisiert mit dem Standardwert, aber in der Lage, sich zu erweitern. Der stack ist ein Last-in, First-out (LIFO) Datenstruktur. Man kann sich das wie einen Eimer—Variablen Hinzugefügt werden, die oben auf dem Eimer, und wenn Sie gehen out-of-scope .NET greift in den Eimer und entfernt Sie ein zu einer Zeit, bis es unten angekommen ist.

Der stack ist viel schneller, aber es ist nur noch eine Position im RAM, nicht auf einen speziellen Speicherort im cache der CPU (obwohl es kleiner ist als die Haufen, und als solche ist sehr wahrscheinlich zu heiß sein in den cache, das hilft bei der performance).

Der Stapel erhält die meisten seiner performance von seiner LIFO-Struktur. Wenn Sie eine Funktion aufrufen, werden alle Variablen definiert, die der Funktion Hinzugefügt werden auf den Stapel. Wenn die Funktion zurückgibt und die Variablen außerhalb des Bereichs, den stack löscht off alles, die Funktion auf ihn. Die Laufzeitumgebung verwaltet diese mit stack-frames definieren von Blöcken von Speicher für verschiedene Funktionen. Stack Zuweisungen sind extrem schnell, weil es einfach schreiben eines einzelnen Wertes auf das Ende des stack-Frames.

Dies ist auch wo der Begriff “StackOverflow” kommt, die sich ergibt, wenn eine Funktion enthält zu viele verschachtelte Methodenaufrufe und füllt den gesamten stack.

Referenz-Typen, jedoch sind entweder zu groß, haben keine festen Größen, oder zu lange Leben werden auf den stack. In der Regel nehmen die form von Objekten und Klassen, die instanziiert wurde, aber Sie enthält auch arrays und strings, die in der Größe variieren.

Referenz-Typen wie Instanzen von Klassen sind oft Initialisierung mit dem Schlüsselwort new erzeugt eine neue Instanz der Klasse und gibt eine Referenz darauf. Sie können diese Einstellung auf eine lokale variable, die tatsächlich verwendet der stack zum speichern der Referenz auf den Speicherort auf dem heap.

Der heap erweitern können und füllen Sie, bis der computer aus der Erinnerung, die macht es ideal für die Speicherung einer Menge von Daten. Jedoch, es ist unorganisiert, und in C# es muss verwaltet werden, mit einem garbage-collector, um richtig zu arbeiten. Heap-Zuweisungen sind auch langsamer als stack Zuweisungen, obwohl Sie immer noch Recht schnell.

Es gibt jedoch eine Reihe von Ausnahmen zu diesen Regeln, sonst Wert-und Referenztypen genannt werden würde “stack-Typen” und “heap-Typen”.

  • Äußere Variablen des lambda-Funktionen, lokale Variablen von IEnumerator-Blöcke und lokale Variablen von async-Methoden sind alle gespeichert auf dem heap.
  • Wert-Typ-Felder von Klassen werden langfristig Variablen und sind immer auf dem heap gespeichert. Sie sind auch verpackt in einem Referenz-Typ, und gespeichert werden, dass neben den Typ der Referenz.
  • Statische klassenfelder sind auch immer gespeichert auf dem heap.
  • Benutzerdefinierte structs sind value-Typen, aber Sie enthalten Referenz-Typen wie Listen und strings, die gespeichert werden auf dem heap als normal. Erstellen Sie eine Kopie der Struktur erstellt eine neue Kopie und Zuweisung aller Referenztypen auf dem heap.

Die wichtigste Ausnahme von der Regel des “Referenztypen werden auf dem heap” ist die Verwendung von stackalloc mit Span<T>, die manuell reserviert einen Speicherblock auf dem stack für eine temporäre array, wird gereinigt aus dem stack als normal, wenn es den Bereich verlässt. Dieses Verfahren relativ teuer heap und legt weniger Druck auf den garbage collector in den Prozess. Es kann sein, viel mehr Leistung bietet, aber es ist ein bisschen eine erweiterte Funktion, so dass, wenn Sie möchten, um mehr darüber zu erfahren Lesen Sie diese Anleitung, um es richtig zu nutzen, ohne dass eine StackOverflow-exception.

Was Ist Garbage Collection?

Der stack ist sehr gut organisiert, aber der heap ist chaotisch. Ohne etwas zu verwalten, die Dinge auf dem heap nicht bereinigt werden automatisch, die dazu führt, die Anwendung aus dem Speicher durch, um es nie freigegeben wird.

Natürlich, das ist ein problem, das ist der Grund, warum der garbage collector vorhanden ist. Es läuft auf einem hintergrund-thread und scannt in regelmäßigen Abständen Ihre Anwendung für Bezüge, die nicht mehr existieren auf dem Stapel, die darauf hindeuten, dass das Programm beendet wurde die Sorge um die Daten referenziert werden. Die .NET-runtime können kommen und Aufräumen, und-shift-Speicher um in den Prozess zu machen heap mehr organisiert.

Aber diese Magie kommt zu einem Preis—garbage collection ist langsam und teuer. Es läuft auf einem hintergrund-thread, aber gibt es einen Zeitraum, wo die Ausführung des Programms muss gestoppt werden, die zum ausführen der garbage collection. Dies ist der Kompromiss, dass kommt mit der Programmierung in C#, alles, was Sie tun können, ist zu versuchen, zu minimieren, den Müll, die Sie erstellen.

In Sprachen ohne garbage-collector, müssen Sie manuell bereinigen nach sich selbst, das ist schneller, in vielen Fällen aber mehr ärgerlich für die Programmierer. Also, in einem Sinne, ein garbage collector ist wie ein Roomba, das reinigt Ihre Böden automatisch, aber langsamer ist, als nur aufstehen und Staubsaugen.