Hallo, ich habe auf einem Raspberry Pi Speicher für einen mehrseitigen Text allokiert und deallokiert. Das Ergebnis habe ich mit /proc/mem in der Erwartung überprüft, dass der zur Verfügung stehende Speicherplatz beim Allokieren um einen gewissen Betrag weniger und beim Deallokieren wieder mehr geworden ist. Nach einem kompletten Zyklus von Allokieren und Deallokieren habe ich eigentlich erwartet, wieder auf demselben Betrag an freiem Speicher rauskommen, mit dem ich angefangen habe. Leider ist dem nicht so. Das von /proc/mem angezeigte scheint eher zufällig zu sein und in keinem Kausalzusammenhang mit meinem Allokieren / Deallokieren zu stehen. Was mache ich falsch?
:
Bearbeitet durch User
Michael schrieb: > dem nicht so. Das von /proc/mem angezeigte scheint eher zufällig zu sein /proc/mem ist wohl daselbe wie /proc/meminfo auf einem Ubuntu-System. Und damit vermisst Du leider global das Gesamtsystem, und nicht nur das, was Dein Programm macht. Da spuckt Dir also alles mögliche in die Suppe, was auf dem Ding läuft ... Du musst also /proc/<pid>/mem auslesen, damit Du nur Deinen Prozess siehst ... Edit: /proc/<pid>/mem scheint bei mir nix auszugeben. Naja, muss man wohl doch anders abfragen. Z.B. "ps aux" -> VSZ ...
:
Bearbeitet durch User
man 5 proc_pid_statm man 5 proc_pid_status könnten helfen. Edit: Man darf auch direkt im Programm ausgeben, ohne externe tools.
1 | #!/usr/bin/python3
|
2 | # vim: fileencoding=utf-8: ts=4: sw=4: expandtab:
|
3 | import os |
4 | with open(f'/proc/{os.getpid()}/status') as fr: |
5 | for line in fr.readlines(): |
6 | print(line,end='') |
:
Bearbeitet durch User
Norbert schrieb: > Man darf auch direkt im Programm ausgeben, ohne externe > tools.#!/usr/bin/python3 > # vim: fileencoding=utf-8: ts=4: sw=4: expandtab: > import os > with open(f'/proc/{os.getpid()}/status') as fr: > for line in fr.readlines(): > print(line,end='') Wenn der Prozess das für sich selbst macht, muss er nicht mal die PID angeben. Einfach /proc/self nehmen. Das ist ein Symlink auf die aktuelle PID.
Rolf M. schrieb: > Wenn der Prozess das für sich selbst macht, Stimmt. Wäre dann noch einmal kürzer:
1 | #!/usr/bin/python3
|
2 | # vim: fileencoding=utf-8: ts=4: sw=4: expandtab:
|
3 | with open(f'/proc/self/status') as fr: |
4 | print(*fr.readlines()) |
Michael schrieb: > Was mache ich falsch? Du glaubst, Linux' Speicherverwaltung sei einfach und linear. Das ist jedoch nicht der Fall. In der Realität macht der Kernel dabei ein paar sehr schlaue Dinge, und nicht einmal ein malloc(3) tut genau das was wir gerne glauben -- Stichwort "Overcommit". Einen Überblick über die meisten Konzepte findest Du hier [1], mehr Details hier [2], und eine noch ausführlichere Darstellung im Verzeichnis Documentation/mm/ des Linux Kernel Sourcecode sowie hier [3]. [1] https://docs.kernel.org/admin-guide/mm/concepts.html [2] https://tldp.org/LDP/tlk/mm/memory.html [3] https://docs.kernel.org/mm/index.html
Hallo, ich habe "man 5 proc_pid_statm" und "man 5 proc_pid_status" gelesen. Dort steht was von ungenau. Wenn man es genauer wissen möchte, soll man in "/proc/pid/smaps" nachschauen. Das habe ich (ohne system () zu benutzen) getan und die mit heap überschriebenen Abschnitte herauskopiert, siehe beigefügte Datei. Kann ich dieser entnehmen, dass meine Deallokation nicht stattfindet? Abgesehen davon: Hinter meiner Frage nach dem Heap-Verbrauch meines Programmes steht eigentlich die Frage, ob meine Funktionen zum Allokieren und Deallokieren meines Stringarrays funktionieren. Tun sie das? Was brk () betrifft, so steht in "man 2 brk" in den Notizen: "Avoid using brk() and sbrk(): the malloc(3) memory allocation package is the portable and comfortable way of allocating memory." Da ich von brk () noch nie etwas gehört habe und momentan mit malloc und free eh schon alle Hände voll zu tun habe, würde ich gerne zumindest vorübergehend auf den Einsatz von brk () verzichten.
Ein T. schrieb: > Du glaubst, Linux' Speicherverwaltung sei einfach und linear. Das ist > jedoch nicht der Fall. Im Vergleich zu den 8 Bit-Microcontrollern, die ich üblicherweise ohne Betriebssystem nutze, gerne auch mal in Assembler, scheint Linux teilweise doch ein bischen komplizierter... ;-)
:
Bearbeitet durch User
Due Einführung einer neuen Programmiersprache war bei uns der Anlass, etwas genauer auf den Speicherbedarf unserer PODs zu achten. Es stellte sich heraus, dass er bei jeder Lastspitze etwas größer wurde und erst nach etwa 6 Wochen Laufzeit ein stabiles Niveau erreicht. Wir hatten damals sehr viel Arbeitszeit und auch Geld für Tools aufgebracht, um das befürchtete Memory Leck zu finden. Aber da war keins. Das Zusammenspiel zwischen Garbage Collector, Kubernetes und Linux ist kaum noch zu durchschauen.
Michael schrieb: > Was brk () betrifft, so steht in "man 2 brk" in den Notizen: "Avoid > using brk() and sbrk(): the malloc(3) memory allocation package is the > portable and comfortable way of allocating memory." malloc() nutzt intern selbst brk()/sbrk(), um Speicher vom System zu bekommen (oder alternativ bei großen Blöcken auch mmap()). Daher ist das Verhalten dieser Funktionen in dem Fall auch bei Nutzung von malloc() relevant. Bedenke, dass Speicher vom System nicht byteweise, sondern nur in ganzen Speicherseiten verwaltet wird. malloc() kümmert sich dann innerhalb deines Prozesses um die feingranulare Allokation. Das heißt, dass Speicher nur dann überhaupt an das System zurückgegeben werden kann, wenn eine Speicherseite komplett frei wird. Dazu kommt, dass man mit brk()/sbrk() ja das Ende des Heap verschiebt. Damit kann natürlich prinzipbedingt nur Speicher zurückgegeben werden, der auch ganz am Ende des Heap liegt und nicht irgendwo mitten drin. Deshalb wird in der Regel Speicher, der per brk()/sbrk() allokiert wird, beim Freigeben zwar intern für das Programm wieder für neue Allokationen verfügbar gemacht, aber nicht komplett an das Betriebssytem zurückgegeben.
Nemopuk schrieb: > Wir hatten damals sehr viel Arbeitszeit und auch Geld für Tools > aufgebracht, um das befürchtete Memory Leck zu finden. Aber da war > keins. Das Zusammenspiel zwischen Garbage Collector, Kubernetes und > Linux ist kaum noch zu durchschauen. Schau nicht auf verfügbaren memory sondern auf commited memory.
:
Bearbeitet durch User
Michael schrieb: > Was brk () betrifft, so steht in "man 2 brk" in den Notizen: "Avoid > using brk() and sbrk(): the malloc(3) memory allocation package is the > portable and comfortable way of allocating memory." Da ich von brk () > noch nie etwas gehört habe und momentan mit malloc und free eh schon > alle Hände voll zu tun habe, würde ich gerne zumindest vorübergehend auf > den Einsatz von brk () verzichten.
1 | Calling sbrk() with an increment of 0 can be used to find the |
2 | current location of the program break. |
Und bedenke das Pages die noch nicht angefasst wurden lediglich reserviert sind. Direkt nach einem malloc(100GB) ist fast noch genauso viel Speicher verfügbar wie direkt vor dem malloc.
:
Bearbeitet durch User
Jens G. schrieb: > Edit: /proc/<pid>/mem scheint bei mir nix auszugeben. Naja, muss man > wohl doch anders abfragen. Z.B. "ps aux" -> VSZ ... RSS kommt dem "tatsächlichen" Speicherverbrauch eines Prozesses näher als VSZ.
Michael schrieb: > Hinter meiner Frage nach dem Heap-Verbrauch meines Programmes steht > eigentlich die Frage, ob meine Funktionen zum Allokieren und > Deallokieren meines Stringarrays funktionieren. Tun sie das? Zur Beantwortung gibt es ein großartiges Programm namens valgrind [1], das bereits in den Paketrepositories von Raspbian enthalten ist und deswegen nur von Dir installiert und benutzt werden muß. Hinweis: für eine ausführliche Ausgabe empfiehlt sich der Parameter "--leak-check=full", viel Erfolg! [1] https://valgrind.org/
Michael schrieb: > Im Vergleich zu den 8 Bit-Microcontrollern, die ich üblicherweise ohne > Betriebssystem nutze, gerne auch mal in Assembler, scheint Linux > teilweise doch ein bischen komplizierter... ;-) Nur gaaanz geringfügig. :-)
G. K. schrieb: > Direkt nach einem malloc(100GB) ist fast noch genauso > viel Speicher verfügbar wie direkt vor dem malloc. Ganz genau so ist das bei virtueller Speicherverwaltung. Angefordert wird nicht etwa physischer Speicher, sondern nur Adressraum. Ob und wann der mit physischem Speicher "hinterlegt" wird, entscheidet das OS, jedenfalls wenn der Programmierer nichts anderes vorgibt. Für bestimmte Zwecke ist es nämlich durchaus möglich, einen "commit" (also das Hinterlegen mit physischem Speicher) unmittelbar bei der Speicheranforderung zu erzwingen. Für "normalen" Speicherbedarf ist das aber absolut nicht sinnvoll, jedenfall nicht, wenn das Ziel ist, das Gesamtsystem möglichst effizient zu betreiben.
G. K. schrieb: >> Edit: /proc/<pid>/mem scheint bei mir nix auszugeben. Naja, muss man >> wohl doch anders abfragen. Z.B. "ps aux" -> VSZ ... > > RSS kommt dem "tatsächlichen" Speicherverbrauch eines Prozesses näher > als VSZ. Kommt drauf an, ob man den Speicher wissen will, der tatsächlich im RAM liegt, oder den Speicher, der im virtuellen Adressraum belegt wird, bzw. das Programm glaubt zu belegen. Da der TO den Effekt von malloc() wissen will, was erstmal nur virtuellen Speicher vorreserviert, macht eigentlich nur VSZ Sinn zu beobachten, und nicht RSS, was aus Anwendersicht eher zufälligen Charakter hat.
:
Bearbeitet durch User
Ein T. schrieb: > Zur Beantwortung gibt es ein großartiges Programm namens valgrind [1], mike@PC6:~/Privat/geany/work$ valgrind --leak-check=full ./stringarray_2 ==6007== Memcheck, a memory error detector ==6007== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward et al. ==6007== Using Valgrind-3.24.0 and LibVEX; rerun with -h for copyright info ==6007== Command: ./stringarray_2 ==6007== Hello, world ==6007== ==6007== HEAP SUMMARY: ==6007== in use at exit: 0 bytes in 0 blocks ==6007== total heap usage: 1,012 allocs, 1,012 frees, 109,104 bytes allocated ==6007== ==6007== All heap blocks were freed -- no leaks are possible ==6007== ==6007== For lists of detected and suppressed errors, rerun with: -s ==6007== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) :-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.