Freigeben über


Behandeln von Problemen mit der Arbeitsspeicherleistung in Linux

Gilt für: ✔️ Linux-VMs

In diesem Artikel wird erläutert, wie Sie Speicherleistungsprobleme beheben, die auf virtuellen Linux-Computern (VMs) in Microsoft Azure auftreten.

Der erste Schritt bei der Arbeit an Speicherproblemen besteht darin, die folgenden Elemente auszuwerten:

  • Verwendung des Arbeitsspeichers durch die Anwendungen, die auf dem System gehostet werden
  • Die entsprechende Ebene des verfügbaren Arbeitsspeichers auf dem System

Sie können mit der Analyse von Workloadmustern beginnen, um festzustellen, ob das System ordnungsgemäß konfiguriert ist. Als Nächstes müssen Sie möglicherweise die Skalierung des virtuellen Computers in Betracht ziehen oder zwischen einer NUMA-Architektur (nicht uniform Memory Access) und UMA (Uniform Memory Access) wählen. Außerdem lohnt es sich zu überlegen, ob die Anwendungsleistung von Transparent HugePages (THP) profitieren würde. Der beste Ansatz besteht darin, mit dem Anwendungsanbieter zusammenzuarbeiten, um die empfohlenen Speicheranforderungen zu verstehen.

Wichtige Bereiche, die vom Arbeitsspeicher betroffen sind

  • Prozessspeicherzuweisung – Speicher ist eine erforderliche Ressource für jeden Prozess, einschließlich des Kernels. Die erforderliche Arbeitsspeichermenge hängt vom Prozessentwurf und -zweck ab. Der Speicher wird in der Regel entweder dem Stapel oder dem Heap zugewiesen. So verlassen sich z. B. Speicherdatenbanken wie SAP HANA stark auf Speicher, um Daten effizient zu speichern und zu verarbeiten.

  • Seitencachenutzung – Der Arbeitsspeicher kann auch indirekt durch eine Erhöhung des Seitencaches genutzt werden. Der Seitencache ist eine Speicherdarstellung einer Datei, die zuvor von einem Datenträger gelesen wurde. Dieser Cache hilft dabei, wiederholte Datenträgerlesevorgänge zu vermeiden. Das beste Beispiel für diesen Prozess ist ein Dateiserver, der von dieser zugrunde liegenden Kernelfunktionalität profitiert.

  • Speicherarchitektur – Es ist wichtig zu wissen, welche Anwendung oder Anwendungen auf demselben virtuellen Computer ausgeführt werden und ob sie für den verfügbaren Arbeitsspeicher konkurrieren könnten. Möglicherweise müssen Sie auch überprüfen, ob die VM für die Verwendung der NUMA- oder UMA-Architektur konfiguriert ist. Abhängig von den Speicheranforderungen eines Prozesses ist die UMA-Architektur möglicherweise vorzuziehen, damit der vollständige RAM ohne Strafe behoben werden kann. Andererseits können Sie für Hochleistungscomputing (HPC) mit vielen kleinen Prozessen oder Prozessen, die in einen der NUMA-Knoten passen, von der CPU-Cachelokalität profitieren.

  • Speicherüberbelegung – Es ist auch wichtig zu bestimmen, ob der Kernel Speicherüberbelegung zulässt. Je nach Konfiguration wird jede Speicheranforderung erfüllt, bis der angeforderte Betrag nicht mehr verfügbar ist.

  • Swap-Speicher Durch das Aktivieren des Swap-Speichers wird die Gesamtsystemstabilität verbessert, indem ein Puffer bei Arbeitsspeicher-Knappheit bereitgestellt wird. Dieser Puffer hilft dem System, unter Druck stabil zu bleiben. Weitere Informationen finden Sie in diesem Linux Kernel-Artikel.

Verstehen der Tools zur Fehlerbehebung beim Speicher

Sie können die folgenden Befehlszeilentools verwenden, um Probleme zu beheben.

kostenlos

Verwenden Sie den free Befehl, um den verfügbaren und verwendeten Arbeitsspeicher auf einem System anzuzeigen.

Screenshot der kostenlosen Beispielausgabe.

Dieser Befehl generiert eine Zusammenfassung des reservierten und verfügbaren Arbeitsspeichers, einschließlich gesamter und verwendeter Swapspace.

pidstat und vmstat

Verwenden Sie den pidstat -r Befehl, um eine detailliertere Ansicht der Speicherauslastung durch einzelne Prozesse anzuzeigen.

Screenshot der Pidstat-Beispielausgabe -r.

Wenn Sie Berichte zur Speicherauslastung analysieren, sind zwei wichtige Spalten zu beobachten: VSZ und RSS.

  • VSZ (Virtual Set Size) zeigt die Gesamtmenge des virtuellen Speichers (in Kilobyte) an, die ein Prozess reserviert.
  • RSS (Resident Set Size) gibt an, wie viel virtueller Speicher derzeit im RAM (z. B. zugesicherten Arbeitsspeicher) gespeichert ist.

Eine weitere nützliche Metrik ist majflt/s (die Anzahl der Hauptseitenfehler pro Sekunde). Diese Zahl misst, wie oft eine Speicherseite von einem Swap-Gerät gelesen werden muss. Wenn Sie Bedenken hinsichtlich der hohen Nutzung des Swapspeichers haben, überprüfen Sie die Menge mithilfe des vmstat Tools, um die Seiten-In- und Auslagerungsstatistiken im Laufe der Zeit zu überwachen.

Vmstat-Ausgabebeispiel

In diesem Beispiel können Sie feststellen, dass viele Speicherseiten gelesen oder geschrieben werden, um zu tauschen. Diese hohen Werte deuten in der Regel darauf hin, dass das System nur noch über wenig verfügbaren Arbeitsspeicher verfügt. Diese Bedingung kann auftreten, weil mehrere Prozesse im Arbeitsspeicher konkurrieren oder weil die meisten Anwendungen keinen verfügbaren Arbeitsspeicher verwenden können.

Ein häufiger Grund für nicht verfügbaren Arbeitsspeicher ist die Verwendung von HugePages. HugePages sind reservierter Speicher. Nicht alle Anwendungen können reservierten Speicher verwenden. In einigen Situationen müssen Sie möglicherweise bewerten, ob Ihre Anwendungen HugePages benötigen oder effektiver mit Transparent HugePages (THP) arbeiten würden. THP ermöglicht es dem Kernel, große Speicherseiten dynamisch zu verwalten. Beispielsweise kann der virtuelle Java-Computer (JVM) THP nutzen, indem die folgende Kennzeichnung aktiviert wird:

-XX:+UseTransparentHugePages

Weitere Informationen zu THP finden Sie unter Transparent HugePage Support.

Weitere Informationen zu HugePages finden Sie unter HugeTLB Pages.

Testen der THP-Verwendung in einem Beispielprogramm

Um zu beobachten, wie THP vom System verwendet wird, können Sie ein kleines C-Programm ausführen, das ca. 256 MB RAM zuweist. Das Programm verwendet den madvise Systemaufruf, um dem Linux-Kernel mitzuteilen, dass diese Speicherregion große Seiten verwenden sollte, wenn das THP unterstützt wird.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>

#define LARGE_MEMORY_SIZE (256 * 1024 * 1024) // 256MB

int main() {
    char str[2];

    // Allocate a large memory area
    void *addr = mmap(NULL, LARGE_MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);


    if (addr == MAP_FAILED) {
        perror("mmap");
        return 1;
    }


    // Use madvise to give advice about the memory usage
    if (madvise(addr, LARGE_MEMORY_SIZE, MADV_HUGEPAGE) != 0) {
        perror("madvise");
        munmap(addr, LARGE_MEMORY_SIZE);
        return 1;
    }

    // Initialize the memory
    int *array = (int *)addr;
    for (int i = 0; i < LARGE_MEMORY_SIZE / sizeof(int); i++) {
        array[i] = i;
    }

    memset(addr, 0, LARGE_MEMORY_SIZE);

    printf("Press Enter to continue\n");
    fgets(str,2,stdin);

    // Clean up
    if (munmap(addr, LARGE_MEMORY_SIZE) == -1) {
        perror("munmap");
        return 1;
    }

    return 0;
}

Wenn Sie das Programm ausführen, ist es nicht direkt zu beobachten, ob THP vom Programm verwendet wird.

Sie können die gesamte THP-Nutzung auf dem System überprüfen, indem Sie die /proc/meminfo Datei untersuchen. Überprüfen Sie das AnonHugePages Feld, um die Arbeitsspeichermenge zu ermitteln, die THP verwendet. Diese Datei enthält nur systemweite Statistiken.

Um zu erfahren, ob ein Prozess THP verwendet, müssen Sie die smaps Datei im /proc betreffenden Verzeichnis des betreffenden Prozesses prüfen. Suchen Sie z. B. in /proc/2275/smaps, nach einer Zeile, die das Wort heap enthält (hier ganz rechts dargestellt).

Screenshot der THP-Verwendung durch das C-Beispielprogramm.

Dieses Beispiel zeigt, dass ein großes Speichersegment zugewiesen und als gekennzeichnet THPeligiblewurde (THP wird verwendet). Durch die Verwendung madvice syscallist die Zuordnung dieses Speicherblocks wesentlich effizienter. Sie könnten die gleiche Effizienz erreichen, indem Sie riesige Seiten verwenden. Je nach Größe der Zuordnung kann der Kernel entweder standardmäßige 4 KB-Seiten oder größere zusammenhängende Blöcke zuweisen. Diese Optimierung kann die Leistung für speicherintensive Anwendungen verbessern.

Weitere Informationen finden Sie unter Transparent Hugepage Support.

NUMA

Wenn die Anwendungen auf einem NUMA-System mit mehreren Knoten ausgeführt werden, ist es wichtig, die Speicherkapazität der einzelnen Knoten zu kennen. Alle Knoten können auf den Gesamtspeicher des Systems zugreifen. Sie erhalten jedoch eine optimale Leistung, wenn die Prozesse, die auf einem bestimmten NUMA-Knoten ausgeführt werden, auf dem Speicher arbeiten, der unter direkter Kontrolle dieses Knotens liegt. Wenn der lokale Knoten keine Speicheranforderung erfüllen kann, weist das System Speicher von einem anderen Knoten zu. Der Zugriff auf den Speicher über Knoten hinweg führt jedoch zu Latenz und kann Leistungseinbußen verursachen. Daher sollten Sie die Speicherlokalität überwachen, um sicherzustellen, dass Workloads an den Speicherressourcen ihrer zugewiesenen NUMA-Knoten ausgerichtet sind.

Der folgende Screenshot zeigt ein Beispiel für die NUMA-Konfiguration des Systems.

Screenshot der Numactl-Ausgabe.

Diese Konfiguration zeigt, dass der Zugriff auf den Speicher innerhalb desselben Knotens eine Entfernungsstufe von 10 aufweist. Wenn Sie auf den Speicher von Node 1 auf Node 0 zugreifen möchten, hat dieser Vorgang einen hohen Distanzwert von 12, ist aber weiterhin überschaubar. Wenn Sie jedoch auf Speicher NODE 3 von NODE 0 zugreifen möchten, wird die Entfernungsstufe 32. Dieser Vorgang ist zwar noch möglich, aber auch dreimal langsamer. Es ist hilfreich, diese Unterschiede zu berücksichtigen, wenn Sie Leistungsprobleme diagnostizieren oder speichergebundene Workloads optimieren. Weitere Informationen finden Sie in diesem Linux Kernel-Artikel. Eine Beschreibung des numactl Tools finden Sie unter numactl(8).

Um festzustellen, ob eine Neuausrichtung von Prozessen vorhanden ist und ein anderer Knoten erforderlich wäre, verwenden Sie das numastat Tool. Die Dokumentation für dieses Tool ist unter numastat(8)verfügbar. Das migratepages Tool migratepages(8) kann Ihnen helfen, die Speicherseiten auf den richtigen Knoten zu verschieben.

Overcommitment und OOM Killer

Überprovisionierung ist eine wichtige Designentscheidung, die die Systemleistung und Stabilität ernsthaft beeinträchtigen kann. Der Linux-Kernel unterstützt drei Modi:

  • "Heuristik"
  • Sich immer übermäßig engagieren
  • Nicht überlasten

Standardmäßig verwendet das System das Heuristic Schema. Dieser Modus bietet einen ausgewogenen Kompromiss zwischen der ständigen Zulassung der Speicherüberbelegung und der strikten Ablehnung. Weitere Informationen finden Sie in der Kerneldokumentation.

Eine falsche Einstellung für die Überbelegung kann verhindern, dass Speicherseiten Arbeitsspeicher zugewiesen bekommen. Möglicherweise kann diese Bedingung die Erstellung neuer Prozesse behindern oder verhindern, dass interne Kernelstrukturen genügend Arbeitsspeicher erhalten.

Wenn Sie überprüfen, ob das Problem mit der Speicherzuweisung verbunden ist, ist die wahrscheinlichste Ursache für dieses Problem unzureichende Ressourcen für den Kernel. In dieser Art von Situation könnte der OOM (Out-Of-Memory) Killer aufgerufen werden. Der Auftrag besteht darin, einige Speicherseiten für die Verwendung durch Kernelaufgaben oder andere Anwendungen freizugeben. Durch Aufrufen des OOM-Killers warnt Sie das System, dass es seine Ressourcengrenzwerte erreicht hat. Wenn Sie die Möglichkeit eines Speicherverlusts beseitigen können, kann die Ursache für diese Bedingung sein, dass zu viele Prozesse ausgeführt werden oder dass Prozesse, die viel Arbeitsspeicher verbrauchen. Um das Problem zu beheben, sollten Sie die VM-Größe erhöhen oder einige Anwendungen auf einen anderen Server verschieben.

Systemprotokolle, die während OOM-Ereignissen generiert wurden

In diesem Abschnitt wird eine Technik zum Identifizieren des Moments vorgestellt, in dem der OOM Killer ausgelöst wird, und um zu erfahren, welche Informationen vom System protokolliert werden.

Das folgende einfache C-Programm testet, wie viel Arbeitsspeicher dynamisch auf einem System zugeordnet werden kann, bevor es fehlschlägt.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ONEGB (1 << 30)
int main() {
        int count = 0;
        while (1) {
                int *p = malloc(ONEGB);
              if (p == NULL) {
                printf("malloc refused after %d GB\n", count);
                return 0;
               }
        memset(p,1,ONEGB);
        printf("got %d GB\n", ++count);
     }
}

Dieses Programm gibt an, dass die Speicherzuweisung nach ca. 3 GB fehlschlägt.

Screenshot des Speicherzuweisungsfehlers.

Wenn das System nicht mehr genügend Arbeitsspeicher hat, wird der OOM-Killer aufgerufen. Sie können die zugehörigen Protokolle mithilfe des dmesg Befehls anzeigen. Die Protokolleinträge beginnen in der Regel wie im folgenden Screenshot dargestellt.

Screenshot des aufgerufenen OOM-Killerprotokolls.

Die Einträge enden in der Regel in einer Zusammenfassung des Arbeitsspeicherzustands.

Screenshot des Zustands

Zwischen diesen Einträgen finden Sie detaillierte Informationen zur Speicherauslastung und zum prozess, der für die Beendigung ausgewählt wurde.

Screenshot der vollständigen Details von OOM Nr. 1. Screenshot der vollständigen Details von OOM Nr. 2.

Anhand dieser Informationen können Sie die folgenden Erkenntnisse extrahieren:

4194160 kBytes physical memory 
No swap space
3829648 kBytes are in use

Im folgenden Protokollbeispiel hat der Malloc-Prozess eine einzelne 4 KB-Seite angefordert (Reihenfolge=0). Obwohl 4 KB-Seite klein ist, war das System bereits unter Druck. Das Protokoll zeigt, dass der Speicher aus der "Normalzone" zugewiesen wurde.

Screenshot des Protokollbeispiels zu Malloc.

Der verfügbare Arbeitsspeicher (free) beträgt 29.500 KB. Das Mindestwasserzeichen (min) beträgt jedoch 34.628 KB. Da das System unter diesem Schwellenwert liegt, kann nur der Kernel den verbleibenden Arbeitsspeicher verwenden, und Benutzerspeicheranwendungen werden verweigert. Der OOM-Killer wird an diesem Punkt aufgerufen. Es wählt den Prozess mit der höchsten oom_score- und Speicherauslastung („RSS“) aus. In diesem Beispiel hatte der Malloc-Prozess eine oom_score von 0, aber auch die höchste RSS (917760). Daher wird sie als Ziel für die Beendigung ausgewählt.

Überwachen des graduellen Speicherwachstums

OOM-Ereignisse können leicht erkannt werden, da verwandte Nachrichten in der Konsole und in den Systemprotokollen protokolliert werden. Eine graduelle Zunahme der Speicherauslastung, die kein OOM-Ereignis verursacht, kann jedoch schwieriger zu erkennen sein.

Verwenden Sie das sar-Tool aus dem sysstat-Paket, um die Speichernutzung im Laufe der Zeit zu überwachen. Um sich auf die Speicherdetails zu konzentrieren, verwenden Sie die Option "r" (z. B. "sar-r").

Beispielausgabe

Screenshot der Sar-Speicherinformationen.

In diesem Fall wächst die Speicherauslastung um etwa zwei Stunden. Dann fällt sie auf vier Prozent zurück. Dieses Verhalten kann erwartet werden, z. B. während der Spitzenanmeldungszeit oder ressourcenintensiver Berichterstellungsaufgaben. Um festzustellen, ob dieses Verhalten normal ist, müssen Sie die Nutzung möglicherweise über mehrere Tage überwachen und dann mit der Anwendungsaktivität korrelieren. Eine hohe Speicherauslastung ist nicht unbedingt ein Problem. Dies hängt von der Arbeitsauslastung und davon ab, wie die Anwendungen gestaltet sind, um den Arbeitsspeicher zu nutzen.

Um zu ermitteln, welche Prozesse den meisten Arbeitsspeicher verbrauchen, verwenden Sie pidstat.

Beispielausgabe

Screenshot der Pidstat-Ausgabe.

Diese Ausgabe zeigt alle ausgeführten Prozesse und deren Statistiken an. Ein weiterer Ansatz besteht darin, das Tool "ps" zu verwenden, um ähnliche Ergebnisse zu erzielen: ps aux --sort=-rss | head -n 10

Beispielausgabe

Screenshot der ps aux-Ausgabe.

Warum nach RSS sortieren?

Resident Set Size (RSS) ist der Teil des Prozessspeichers, der im RAM (nicht getauschter physischer Speicher) gespeichert ist. Im Gegensatz dazu stellt Virtual Set Size(VSZ) die Gesamtmenge des Arbeitsspeichers dar, den der Prozess reserviert, einschließlich des Arbeitsspeichers, der nicht zugesichert wird. Committed memory bezieht sich auf Seiten, die tatsächlich in den physischen Speicher geschrieben werden. Wenn Sie versuchen, zu ermitteln, welche Prozesse den physischen Speicher (einschließlich Swap) verwenden, konzentrieren Sie sich auf die RSS Spalte. In der Beispielausgabe scheint der snapd Prozess viel Arbeitsspeicher zu verwenden, aber sein RSS Wert ist niedrig. Der malloc Prozess weist ähnliche VSZ Werte auf RSS , die darauf hinweisen, dass er mehr als 1,3 GB Arbeitsspeicher aktiv verwendet.

Haftungsausschluss für Drittanbieterkontakte

Microsoft stellt Kontaktinformationen von Drittanbietern bereit, um Ihnen bei der Suche nach zusätzlichen Informationen zu diesem Thema zu helfen. Diese Kontaktinformationen können ohne vorherige Ankündigung geändert werden. Microsoft gibt keine Garantie für die Genauigkeit von Kontaktinformationen Dritter.

Kontaktieren Sie uns für Hilfe

Wenn Sie Fragen haben oder Hilfe benötigen, erstellen Sie eine Support-Anfrage oder wenden Sie sich an den Azure Community-Support. Sie können auch Produktfeedback an die Azure Feedback Community senden.