Linux-Speicherfragmentierung

20

Gibt es eine Möglichkeit, Speicherfragmentierung unter Linux zu erkennen? Dies liegt daran, dass ich auf einigen Servern mit langer Laufzeit einen Leistungsabfall festgestellt habe und erst nach einem Neustart eine bessere Leistung sehe. Ich bemerkte es mehr, wenn ich Linux-Unterstützung für große Seiten verwendete. Sind große Seiten in Linux anfälliger für Fragmentierung?

Ich habe mir insbesondere / proc / buddyinfo angesehen. Ich möchte wissen, ob es bessere Möglichkeiten gibt (nicht nur CLI-Befehle an sich, ein Programm oder ein theoretischer Hintergrund), um es zu betrachten.

Raghu
quelle
Ich sehe nicht nur schnelle Kommandozeilenlösungen, sondern auch einfache Programme / Theorien. Daher habe ich bei serverfault nicht nachgefragt.
Raghu
1
Ich verstehe hier keinen Punkt. Nach meinem Verständnis muss Speicherfragmentierung zu Speichermangel und damit zu Speicherzuordnungsfehlern führen. Sie fragen jedoch nach Leistungseinbußen. Liegt es daran, dass Sie viel Speicher auf die Festplatte ausgelagert haben? Und wenn ja was vmstatauf dem Gebiet geben so?
@skwllsp - Bearbeitet meine Antwort, um genauer zu sein.
Tim Post
@Raghu - ich würde nicht die meisten Systemadministratoren erwarten , dass Kernel - Code ändern , um die Speicherverwaltung verhalten sich anders zu machen, aber qualifizierte Linux - Administratoren mindestens eine Übersicht über wissen sollten , wie Linux - Speicher verwaltet. Diese Frage ist wirklich aktuell. Ich habe für die Migration gestimmt, weil ich (in meiner Antwort) keinen Code vorschlagen kann, der Ihre Frage beantwortet. Das Lesen von / proc oder das Verwenden von vmstatist eine übliche Benutzererfahrung. Wenn Sie ein Programm schreiben würden, um dasselbe zu tun, wäre es anders. Wenn Sie beabsichtigen, bash zu verwenden, um diese Informationen zu sammeln, bearbeiten Sie Ihre Frage, es wird nicht geschlossen :)
Tim Post
@Tim - Wie ich bereits angedeutet habe, wollte ich nicht nur die bash / cli-Befehle kennen, sondern benötigte auch die Informationen, die mir bei meinem Benchmarking-Verfahren helfen (um die Ergebnisse zu analysieren, nicht um sie auszuführen).
Raghu

Antworten:

12

Ich antworte auf den Tag. Meine Antwort bezieht sich nur auf Linux .

Ja, große Seiten sind anfälliger für Fragmentierung. Es gibt zwei Speicheransichten: die, die Ihr Prozess erhält (virtuell) und die, die der Kernel verwaltet (real). Je größer eine Seite ist, desto schwieriger wird es, ihre Nachbarn zu gruppieren (und bei ihnen zu bleiben), insbesondere wenn Ihr Dienst auf einem System ausgeführt wird, das auch andere unterstützen muss, die standardmäßig viel mehr Speicher zuweisen und schreiben als sie tatsächlich am Ende mit.

Die Zuordnung des Kernels zu (echten) zugewiesenen Adressen ist privat. Es gibt einen sehr guten Grund, warum Userspace sie so sieht, wie der Kernel sie präsentiert, weil der Kernel in der Lage sein muss, ein Overcommit durchzuführen, ohne Userspace zu verwirren. Ihr Prozess wird einen schönen, zusammenhängenden „Disneyfied“ Adressraum , in dem zu arbeiten, nicht bewusst, was der Kern tatsächlich tut hinter den Kulissen mit diesem Speicher.

Der Grund , warum Sie verminderte Leistung sehen auf lange laufenden Server ist sehr wahrscheinlich , weil zugeordnete Blöcke, die nicht explizit gesperrt (zB mlock()/ mlockall()oder posix_madvise()) und eine Zeit lang nicht verändert wurden ausgelagert , was bedeutet , dass Sie da Kufen auf der Festplatte , wenn es zum Lesen Sie. Wenn Sie dieses Verhalten ändern, wird Ihr Prozess zu einem schlechten Nachbarn . Aus diesem Grund stellen viele Benutzer ihr RDBMS auf einen völlig anderen Server als web / php / python / ruby ​​/ whatever. Die einzige Möglichkeit, dies zu beheben, besteht darin, die Konkurrenz um zusammenhängende Blöcke zu verringern.

Fragmentierung ist (in den meisten Fällen) nur dann wirklich bemerkbar, wenn sich Seite A im Speicher befindet und Seite B zum Auswechseln verschoben wurde. Ein Neustart Ihres Dienstes scheint dies natürlich zu "heilen", aber nur, weil der Kernel noch keine Gelegenheit hatte, den Prozess "(jetzt) ​​neu zugewiesene Blöcke im Rahmen seiner Überlastungsquote" auszublenden.

Tatsächlich wird ein Neustart (sagen wir mal) von 'Apache' unter hoher Last wahrscheinlich Blöcke, die anderen Diensten gehören, direkt auf die Festplatte senden. Also ja, 'Apache' würde sich für kurze Zeit verbessern, aber 'MySQL' könnte darunter leiden. Zumindest bis der Kernel sie gleichermaßen leiden lässt, wenn es einfach an genügend physischem Speicher mangelt.

Fügen Sie mehr Speicher hinzu oder teilen Sie anspruchsvolle malloc()Verbraucher auf :) Es ist nicht nur eine Fragmentierung, die Sie sich ansehen müssen.

Versuchen Sie vmstatsich einen Überblick darüber zu verschaffen, was wo tatsächlich gespeichert wird.

Tim Post
quelle
Danke für die Antwort. Ich habe riesige Seiten (Größe = jeweils 2048 KB) für mysql - innodb buffer pool verwendet, um zu sehen, wie gut die Preise sind (mithilfe von sysbench). Anfangs, als die Prozessverfügbarkeit (und sogar die Systemverfügbarkeit) gering war, wurden sehr gute Ergebnisse erzielt. Die Leistung verschlechterte sich jedoch über mehrere Läufe hinweg. In Bezug auf die von Ihnen erwähnte Seite habe ich sicherlich eine hohe VM-Aktivität bemerkt, aber ich nahm an, dass dies an Benchmark- und Innodb-Log-Leerung lag (VM-Aktivität bei großen Seiten höher als ohne). Ich habe auch vm.swappiness auf 1 gesetzt. Ich konnte keine drastische Änderung feststellen.
Raghu
"Riesige Seiten können nicht unter Speicherdruck ausgetauscht werden", heißt es in dem guten Handbuch . Ich denke, dies ist eine gute Antwort in W / R / T-Standardspeicher, aber nicht für sehr große Seiten.
Dan Pritts
5

Kernel

Um den aktuellen Fragmentierungsindex zu erhalten, verwenden Sie:

sudo cat /sys/kernel/debug/extfrag/extfrag_index

Führen Sie zum Defragmentieren des Kernelspeichers Folgendes aus:

sysctl vm.compact_memory=1  

Außerdem versuchen Sie, Transparent Huge Pages (auch bekannt als THP) zu deaktivieren und / oder Swap zu deaktivieren (oder zu verringern swappiness).

Benutzerraum

Um die Fragmentierung des Benutzerbereichs zu verringern, sollten Sie beispielsweise einen anderen Allokator ausprobieren jemalloc(er verfügt über hervorragende Funktionen zur Selbstüberwachung , die Ihnen einen Einblick in die interne Fragmentierung des Allokators geben).

Sie können zu benutzerdefiniertem malloc wechseln, indem Sie Ihr Programm damit neu kompilieren oder indem Sie Ihr Programm mit den LD_PRELOADfolgenden LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app Befehlen ausführen : (Achten Sie auf die Interaktionen zwischen THP und Speicherzuordnern. )

Sie möchten wahrscheinlich mehrere Instanzen Ihres Dienstes ausführen, eine für jeden NUMA-Knoten, und diese mithilfe von binden numactl.

SaveTheRbtz
quelle
1
Warum sollten Sie glauben, dass das Deaktivieren von Swap helfen könnte? Mir scheint es wahrscheinlicher, dass das Deaktivieren von Swap noch mehr schaden wird.
Kasperd
1
Da der ursprüngliche Beitrag nicht genügend Informationen enthält, leckt der Prozess möglicherweise nur und beginnt zu tauschen. Auch sehe ich keine legitimen Gründe für die Verwendung von Swap auf so ziemlich jedem Produktionssystem (mb nur für gemeinsam genutzte Workstations für Studenten).
SaveTheRbtz
2
Durch ausreichend Swap-Speicher wird die Leistung verbessert. Die Leistungsprobleme, die bei unzureichendem Swap-Speicher auftreten, sind Grund genug, Swap zu aktivieren.
Kasperd
1
@SaveTheRbtz Ein guter Grund für die Verwendung von Swap in einem Produktionssystem ist, dass es dem System mehr Optionen bietet, die es nur dann verwendet, wenn es dies für vorteilhaft hält. Außerdem können geänderte Seiten, auf die seit Stunden nicht mehr zugegriffen wurde (und auf die möglicherweise nie mehr zugegriffen wird), aus dem wertvollen physischen Speicher entfernt werden. Schließlich ermöglicht es dem System, Fälle zu behandeln, in denen viel mehr Speicher reserviert ist als verwendet wird.
David Schwartz
2
"Nur wenn es denkt, dass sie von Vorteil sind" - das fügt zusätzliche Heuristik hinzu und macht das System weniger vorhersehbar. Auch Seitenersetzungsalgorithmen (die in Swap und Anonym verwendet werden mmap) sind auf verschiedenen Kerneln (z. B. Linux vs FreeBSD) oder sogar verschiedenen Versionen desselben Betriebssystems (2.6.32 vs 3.2 vs 3.10) unterschiedlich implementiert. "Es erlaubt modifizierte Seiten [. ..] aus dem physischen [...] Speicher entfernt werden "- das wird Speicherlecks verbergen. "Behandeln Sie Fälle, in denen viel mehr Speicher reserviert ist als verwendet wird" - langsames System ist viel schlimmer als ausgefallenes System, daher ist "vernünftig" fraglich.
SaveTheRbtz
4

Die Verwendung großer Seiten sollte unter Linux keine zusätzliche Speicherfragmentierung verursachen. Die Linux-Unterstützung für große Seiten gilt nur für gemeinsam genutzten Speicher (über shmget oder mmap), und alle verwendeten großen Seiten müssen von einem Systemadministrator speziell angefordert und vorab zugewiesen werden. Sobald sie sich im Speicher befinden, werden sie dort festgehalten und nicht mehr ausgetauscht. Die Herausforderung beim Auslagern großer Seiten angesichts der Speicherfragmentierung besteht genau darin, warum sie im Speicher festgehalten werden (bei der Zuweisung einer 2-MB-großen Seite muss der Kernel 512 zusammenhängende freie 4-KB-Seiten finden, die möglicherweise gar nicht vorhanden sind).

Linux-Dokumentation auf riesigen Seiten: http://lwn.net/Articles/375098/

Es gibt einen Umstand, in dem die Speicherfragmentierung zu einer langsamen Zuweisung großer Seiten führen kann (nicht jedoch, wenn große Seiten eine Speicherfragmentierung verursachen ). Dies ist der Fall , wenn Ihr System so konfiguriert ist, dass der Pool großer Seiten vergrößert wird, wenn eine Anwendung dies anfordert. Wenn / proc / sys / vm / nr_overcommit_hugepages größer als / proc / sys / vm / nr_hugepages ist, kann dies passieren.

jstultz
quelle
In der Tat - und es sollte im Allgemeinen die Leistung verbessern, da es TLB-Ausfälle verhindert (eine Erklärung finden Sie im verlinkten Artikel).
Dan Pritts
0

Es gibt /proc/buddyinfowas sehr nützlich ist. Es ist nützlicher mit einem schönen Ausgabeformat, wie dieses Python-Skript tun kann:

https://gist.github.com/labeneator/9574294

Für große Seiten möchten Sie einige freie Fragmente in der Größe 2097152 (2 MB) oder größer. Bei transparenten großen Seiten wird sie automatisch komprimiert, wenn der Kernel nach einer bestimmten Anzahl von Seiten gefragt wird. Wenn Sie jedoch sehen möchten, wie viele Sie erhalten können, führen Sie als Root Folgendes aus:

echo 1 | sudo tee /proc/sys/vm/compact_memory

Ja, große Seiten verursachen große Probleme bei der Fragmentierung. Entweder können Sie keine großen Seiten abrufen, oder der Kernel verbringt viel zusätzliche Zeit mit dem Abrufen von Seiten.

Ich habe eine Lösung, die für mich funktioniert. Ich benutze es auf ein paar Servern und meinem Laptop. Es funktioniert hervorragend für virtuelle Maschinen.

Fügen Sie die kernelcore=4GOption Ihrer Linux-Kernel-Befehlszeile hinzu. Auf meinem Server verwende ich 8G. Gehen Sie mit der Nummer vorsichtig um, da Ihr Kernel sonst nichts außerhalb dieses Speichers zuordnen kann. Server, die viele Socket-Puffer benötigen oder Festplattenschreibvorgänge auf Hunderte von Laufwerken streamen, werden diese Einschränkung nicht mögen. Jegliche Speicherzuordnung, die für eine Platte oder einen DMA "fixiert" werden muss, fällt in diese Kategorie.

Der gesamte andere Speicher wird dann "verschiebbar", was bedeutet, dass er für eine enorme Seitenzuordnung zu netten Stücken komprimiert werden kann. Jetzt können transparente, große Seiten wirklich abheben und so arbeiten, wie sie sollen. Wann immer der Kernel mehr 2M Seiten benötigt, kann er 4K Seiten einfach woanders neu zuordnen.

Und ich bin mir nicht ganz sicher, wie dies mit Zero-Copy Direct IO zusammenwirkt. Der Speicher in der "beweglichen Zone" sollte nicht fixiert werden, aber eine direkte E / A-Anforderung würde genau das für DMA tun. Es könnte es kopieren. Es könnte sowieso in der beweglichen Zone stecken. In beiden Fällen ist es wahrscheinlich nicht genau das, was Sie wollten.

Zan Lynx
quelle