Arbeitsspeicher sparend coden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Dav1d hat geschrieben:Ich persönlich würds mit supervisor machen, richtig gutes Tool, benutze ich für fast alles: Websites, andere Netzwerk-Services, Daemons etc.

Bei solchen sachen wirst du auf Deutsch nicht fündig: 'systemd service auto restart' -> http://www.freedesktop.org/software/sys ... rvice.html (und Ctrl+F restart), btw. man kann auch in der manpage auf dem RPI nachschauen ;).

Trotzdem würde ich dir empfehlen mal supervisord anzuschauen.
habe mir supervisor mal hier durchgelesen: https://www.digitalocean.com/community/ ... debian-vps
Hab ich das richtig verstanden, dass dies eine Alternative ist, zum Service? Also ich würde das Skript dann nicht so wie jetzt, als Service laufen lassen, sondern eben mit dem supervisor?

Mit der Restart Möglichkeit bei einem "unexpected" Fehler klingt das aufjedenfall gut. Danke :)

Mal schauen, wann ich dafür Zeit habe. Ich befürchte, dass das einige Stunden dauern wird, das einzurichten. In der Regel gibts bei sowas oft Probleme mit der directory :D Also wo ich das Skript und die dazugehörigen Dateien und Skripte hinpacken muss, damit der Zugriff einwandfrei funktioniert. Auch sehe ich im Tutorial noch keine Möglichkeit, die Größe der logs zu verringern... muss ich dann auch noch raussuchen ^^
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Habe einen Weg gefunden, bei dem der Service nie wegen zu wenig arbeitsspeicher gekilled wird.

Es scheint tatsächlich hieran zu liegen:

Code: Alles auswählen

with open('History.txt', 'a') as f :
                    f.write("%s" % text)
Denn wenn ich täglich die vom Vortag angelegte .txt Datei lösche, kann das Skript problemlos tagelang durchlaufen.
Lösche ich die .txt Datei allerdings nicht, sodass sie zu groß wird, wird der service irgendwann gekilled.

Vllt liegt das daran, dass bei jedem öffnen der datei der gesamte inhalt im arbeitspeicher geöffnet wird?
Falls ja, gibt es eine bessere Art der Öffnung einer txt Datei, um nur untendran etwas hinzuzufügen? Dafür muss ja der ganze kram der vorher geschrieben wurde nicht mit geöffnet werde.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Serpens66: nein, die Datei landet nicht im Arbeitsspeicher. Kann es sein, dass es gar nicht am Arbeitsspeicher liegt, sondern dass Deine Disk-Quota überschritten wird?
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Sirius3 hat geschrieben:@Serpens66: nein, die Datei landet nicht im Arbeitsspeicher. Kann es sein, dass es gar nicht am Arbeitsspeicher liegt, sondern dass Deine Disk-Quota überschritten wird?
Der digitalocean support meinte damals, ich solle "sudo cat /var/log/messages" ausführen und ihm das ergebnis schicken. Hatte ich gemacht und er schrieb daraufhin:
Dec 23 21:57:26 MeinServer kernel: [4790455.532401] python3.4 invoked oom-killer: gfp_mask=0x280da, order=0, oom_score_adj=0
This means that your Droplet is running out of memory which is causing processes to be killed. You will need to figure out what is using so much memory (it could be your python program) to prevent this from happening.
Ich nutze den 5 $/monat Plan https://www.digitalocean.com/pricing/ , also sollte ich doch 20GB freien Speicher haben. Und "memory" heißt doch arbeitsspeicher, oder?

Die textdateien werden schon recht groß. Aktuell lösche ich sie wenn sie ungefähr 500 MB groß sind. Weiß nicht was genau die Schwelle ist, bis der service gekilled wird... könnten 1 bis 2 GB sein. Aber 20 GB sind die txt dateien definitv nicht groß.

Aktuell wird mir folgendes angezeigt (die fragliche txt datei ist gerade nur 66 MB groß):

Code: Alles auswählen

root@MeinServer:~# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        20G  2.5G   17G  14% /
udev             10M     0   10M   0% /dev
tmpfs            99M   13M   87M  13% /run
tmpfs           248M     0  248M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           248M     0  248M   0% /sys/fs/cgroup
BlackJack

@Serpens66: An der Programmzeile kann es aber nicht liegen. Ausser Du speicherst die Datei nicht auf dem Massenspeicher sondern in den Arbeitsspeicher. Speicherst Du die Datei unterhalb irgendeines Pfades der beim ``df`` mit dem Typ `tmpfs` aufgelistet wird? Unter `/run/` beispielsweise?
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

BlackJack hat geschrieben:@Serpens66: An der Programmzeile kann es aber nicht liegen.
merkwürdig. Ist die einzige Spur die ich zurzeit habe. Wenn die txt Datei zu groß wird, gibts probleme.
BlackJack hat geschrieben: Ausser Du speicherst die Datei nicht auf dem Massenspeicher sondern in den Arbeitsspeicher. Speicherst Du die Datei unterhalb irgendeines Pfades der beim ``df`` mit dem Typ `tmpfs` aufgelistet wird? Unter `/run/` beispielsweise?
ne, sie wird direkt im "/ <root>" gespeichert, dort liegt auch das skript. Also keine Unterordner (sehe gerade es gibt noch einen unterorder names "root", der ist nicht gemeint)
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Dav1d hat geschrieben: Kannst dir mit memory_profiler anschauen wo der memory herkommt. Wenn dir das nicht reicht gibts noch mehr Memory-Profiler, z.T. auch web basiert.
Habe jetzt mal die Zeit gefunden, mich mit dem memory_profiler zu beschäftigen :)

Habe es also mit
pip3 install -U memory_profiler
installiert und an den anfang des skripts:
from memory_profiler import profile
fp=open('memory_profiler.log','w+')

geschrieben und über die zu untersuchende funktion:
@profile(stream=fp)

Wenn ich das skript nun auf meinem Debian 8.1 x64 starte, dann bekomme ich allerdings folgende Warnung im milisekundentakt geprintet:
/usr/local/lib/python3.4/dist-packages/memory_profiler.py:88: UserWarning: psutil module not found. memory_profiler will be slow
Mar 13 15:12:34 Meinskript python3.4[21632]: warnings.warn("psutil module not found. memory_profiler will be slow")


In der Doku steht nur, dass man psutil bei windows braucht. Aber ich verwende doch kein windows?
https://pypi.python.org/pypi/memory_profiler
Habe dennoch mal mit
sudo apt-get install python-psutil
das packet installiert.
Aber die Warnung kommt immernoch?! Liegt das vllt an der Python 3.4 Problematik? Also dass ich Python 3.4 verwende, während im "Python" Ordner Python 2 installiert ist? Oder woran liegt das?

Die memory_profiler.log Datei bleibt leer.

edit:
Habe psutil jetzt nochmal mit:
apt-get install python3-psutil
installiert und nun kommt die Warnnung nicht mehr :)
Allerdings bleibt die memory_profiler.log Datei immernoch leer....
...
auch ohne stream wird nichts dazu geprintet. Liegt also nicht an der log Datei.

Laut Doko sollte es doch eig funktionieren, ohne extra befehl beim Ausführen, wenn ich es vorher importiere?! hmmm
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

kann meinen Post leider nicht mehr editieren, aber evlt ist es noch wichtig zu wissen, dass ich mein Skript als einen service laufen lasse.
Aber eigentlich sollte das keine auswirkung haben, außer dass ich den geprinteten output über das journal aufrufe.

edit:
vermutlich liegt es tatsächlich am service ? O.ô habe das skript mal normal mit "python3.4 Meinskript.py" aufgerufen und da gibt es eine Ausgabe vom memorey_profiler.
Also wie schaffe ich diese ausgabe auch für einen service?
(wobei ich die Tests zur Not auch durch den direkten aufruf des Skripts machen kann. Memory_profiler muss ja nicht ständig mit laufen ^^)

Wollte mal schauen, ob ich es unter windows zum laufen bekomme, aber da weiß ich nicht genau wie ich psutil installiere. Angeblich soll es mit pip funktionieren, aber da bekomme ich folgendes:

Code: Alles auswählen

PS C:\Users\Serpens66> pip install psutil
Downloading/unpacking psutil
  Running setup.py (path:C:\Users\SERPEN~1\AppData\Local\Temp\pip_build_Serpens66\psutil\setup.py) egg_info for package
psutil

    warning: no previously-included files matching '*' found under directory 'docs\_build'
Installing collected packages: psutil
  Running setup.py install for psutil
    building 'psutil._psutil_windows' extension
    error: Unable to find vcvarsall.bat
    Complete output from command C:\Python34\python.exe -c "import setuptools, tokenize;__file__='C:\\Users\\SERPEN~1\\A
ppData\\Local\\Temp\\pip_build_Serpens66\\psutil\\setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read(
).replace('\r\n', '\n'), __file__, 'exec'))" install --record C:\Users\SERPEN~1\AppData\Local\Temp\pip-8d2dcpra-record\i
nstall-record.txt --single-version-externally-managed --compile:
    running install

running build

running build_py

creating build

creating build\lib.win32-3.4

creating build\lib.win32-3.4\psutil

copying psutil\_common.py -> build\lib.win32-3.4\psutil

copying psutil\_compat.py -> build\lib.win32-3.4\psutil

copying psutil\_psbsd.py -> build\lib.win32-3.4\psutil

copying psutil\_pslinux.py -> build\lib.win32-3.4\psutil

copying psutil\_psosx.py -> build\lib.win32-3.4\psutil

copying psutil\_psposix.py -> build\lib.win32-3.4\psutil

copying psutil\_pssunos.py -> build\lib.win32-3.4\psutil

copying psutil\_pswindows.py -> build\lib.win32-3.4\psutil

copying psutil\__init__.py -> build\lib.win32-3.4\psutil

creating build\lib.win32-3.4\psutil\tests

copying psutil\tests\runner.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_bsd.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_linux.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_memory_leaks.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_misc.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_osx.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_posix.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_process.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_sunos.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_system.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\test_windows.py -> build\lib.win32-3.4\psutil\tests

copying psutil\tests\__init__.py -> build\lib.win32-3.4\psutil\tests

running build_ext

building 'psutil._psutil_windows' extension

error: Unable to find vcvarsall.bat

----------------------------------------
Cleaning up...
Command C:\Python34\python.exe -c "import setuptools, tokenize;__file__='C:\\Users\\SERPEN~1\\AppData\\Local\\Temp\\pip_
build_Serpens66\\psutil\\setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'),
__file__, 'exec'))" install --record C:\Users\SERPEN~1\AppData\Local\Temp\pip-8d2dcpra-record\install-record.txt --singl
e-version-externally-managed --compile failed with error code 1 in C:\Users\SERPEN~1\AppData\Local\Temp\pip_build_Serpen
s66\psutil
Storing debug log for failure in C:\Users\Serpens66\pip\pip.log
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

echt doof, dass man schon nach ein paar minuten den Post nicht mehr editieren kann. Vllt kann ja ein Mod die drei Posts in einen zusammenfassen oderso.

Habe das Problem nun jedenfalls gelöst:
Der memory_profiler schreibt erst den output, wenn das skript fertig durchgelaufen ist. Solange es noch läuft, schreibt er nichts.
Und da ich das skript mit sys.exit() beendet habe, wurde auch der memory_profiler beendet, bevor er seine gesammelten daten niedergeschrieben hat.
(weiß gerade garnicht mehr, warum ich sys.exit() überhaupt eingebaut habe.. werde es mal rausnehmen)
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

okay, nächstes Problem:

Die zu untersuchende Funktion läuft in einer Endlosschleife, also

Code: Alles auswählen

@profile
def myfunction():
    while True:
        # do some stuff
Nun ist das problem, dass der memory_profiler lediglich für einen der Durchläufe seinen Output generiert.
Ich möchte ja gerade wissen, ob der memory usage mit jedem neuen Durchlauf der Schleife größer wird, oder nicht.

Habt ihr eine Idee dazu?
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Serpens66 hat geschrieben:okay, nächstes Problem:

Die zu untersuchende Funktion läuft in einer Endlosschleife, also

Code: Alles auswählen

@profile
def myfunction():
    while True:
        # do some stuff
Nun ist das problem, dass der memory_profiler lediglich für einen der Durchläufe seinen Output generiert.
Ich möchte ja gerade wissen, ob der memory usage mit jedem neuen Durchlauf der Schleife größer wird, oder nicht.

Habt ihr eine Idee dazu?
keiner eine Idee wie ich vernünftig analysieren kann wo in meinem skript in der while schleife etwas mehr und mehr speicher verbraucht?

Habe schon versucht die while schleife wegzunehmen und stattdessen denselben Code mehrmals hintendran kopiert. Dann funktioniert memory_profiler, also ich sehe wieviel speicher nach zb. 10 durchläufen gebraucht wird. Problem ist nur, dass es grob geschätzt 100 bis 1000 durchläufe dauert, bis man wirklich eindeutig sichtbare resultate hat.
Klar kann ich den memory_profiler auch für eine Zeitfunktion nutzen. Aber dass der verbrauchte memory groeßer und groeßer wird weiß ich ja schon. Die Frage ist nur wo genau. Und der Code ist halt einfach zu lang, um einfach mal ein paar variablen drauflos zu raten.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Serpens66: wahrscheinlich liegt genau da Dein Problem, dass Dein Code zu lange ist, um ihn vernünftig zu testen. Speicher wird ja nicht einfach so verbraucht. Wenn jede Funktion eine definierte Aufgabe hat, dann ist der Speicherverbrauch genau das, was die Funktion zurückgibt. Fang also an, kleine testbare Funktionen zu schreiben und diese auch mit entsprechenden Tests auszustatten. Dann sollte eigentlich klar werden, wo Speicher verbraucht wird.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Sirius3 hat geschrieben:@Serpens66: wahrscheinlich liegt genau da Dein Problem, dass Dein Code zu lange ist, um ihn vernünftig zu testen. Speicher wird ja nicht einfach so verbraucht. Wenn jede Funktion eine definierte Aufgabe hat, dann ist der Speicherverbrauch genau das, was die Funktion zurückgibt. Fang also an, kleine testbare Funktionen zu schreiben und diese auch mit entsprechenden Tests auszustatten. Dann sollte eigentlich klar werden, wo Speicher verbraucht wird.
danke für deine antwort.
und womit teste ich dann wenn ich das getan habe? Um die while schleife komme ich schließlich nicht drumherum, selbst wenn ich für jede kleine Aufgabe an eine andere Funktion verweise.

Habe mittlerweile schon die while schleife umgeschrieben, sodass vereinfacht gesagt:

Code: Alles auswählen

def whilefunction(self):
    while True:
        self.myfunction()
gemacht wird. Auf die Weise sollte sichergestellt sein, dass jede in myfunction eingeführte "nicht-self" Variable nach jedem while durchlauf gelöscht wird, richtig? Allerdings theoretisch sollte es keine Veränderung bringen, denn vorher wurden die Variablen schlicht immer wieder überschrieben.

Eigentlich ist das einzige, was nun noch immer groeßer werden kann, meine self. Variablen, welche ich Funktionsübergreifend verwende (denn ich habe schon sehr viele einzelfunktionen, die teilaufgaben übernehmen. Und damit ich leichter damit umgehen kann, gibt es auch einige self. Variablen ... alles ständig in parametern und argumenten hin und her zu schieben ist schlicht zu krass, es sind jetzt schon bis zu 10 parameter die an jede funktion übergeben werden.)

gibt es denn etwas, wie ich, ohne jede einzelne Variable aufzuschreiben, mir die größe aller self. Variablen anzuzeigen lassen kann? Das wäre zumindest schonmal ein Anfang.
Ansonsten muss ich dann halt doch mal jede einzelne Variable mit sys.getsizeof() aufschreiben... Ist sys.getsizeof() am Besten dafür geeignet?
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

so...

1) Durch den Aufbau der funktionen sollte sichergestellt sein, dass jede normale Variable regelmäßig gelöscht wird.
2) Für die self Variablen gebe ich jede stunde nun über sys.getsizeof(self.variable) die Groeße aus. Aber wie erwartet (da sich nie die anzahl der einträge, sondern nur der Wert der Einträge ändert), bleiben alle self Variablen absolut konstant groß und das jetzt schon seit 4 Stunden Laufzeit.

Doch während der 4 stunden laufzeit hat sich die top Info verändert in:
top kurz nach dem Start des skripts (self dictionaries und listen wurden bereits eingefuehrt) als Service:

Code: Alles auswählen

top - 16:13:34 up 69 days, 15:26,  1 user,  load average: 0.14, 0.08, 0.06
Tasks:  63 total,   1 running,  62 sleeping,   0 stopped,   0 zombie
%Cpu(s):  6.3 us,  0.3 sy,  0.0 ni, 92.4 id,  0.0 wa,  0.0 hi,  0.3 si,  0.7 st
KiB Mem:    506340 total,   221992 used,   284348 free,     8404 buffers
KiB Swap:        0 total,        0 used,        0 free.    43600 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
23015 root      20   0  736180 133204   9148 S  7.3 26.3   0:32.76 python3.4
    1 root      20   0   28556   3900   2308 S  0.0  0.8   1:48.58 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0  11:44.14 ksoftirqd/0
    5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
    7 root      20   0       0      0      0 S  0.0  0.0  56:55.05 rcu_sched
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
    9 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
   10 root      rt   0       0      0      0 S  0.0  0.0   1:19.23 watchdog/0
   11 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 khelper
   12 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kdevtmpfs
   13 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 netns
   14 root      20   0       0      0      0 S  0.0  0.0   0:03.37 khungtaskd
   15 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 writeback
   16 root      25   5       0      0      0 S  0.0  0.0   0:00.00 ksmd
   17 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 crypto
   18 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kintegrityd
   19 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 bioset
   20 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kblockd
   22 root      20   0       0      0      0 S  0.0  0.0   0:53.53 kswapd0
   23 root      20   0       0      0      0 S  0.0  0.0   0:00.00 fsnotify_mark
   29 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kthrotld
   30 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 ipv6_addrconf
   31 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 deferwq
   65 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 ata_sff
   66 root      20   0       0      0      0 S  0.0  0.0   0:00.00 khubd
   67 root      20   0       0      0      0 S  0.0  0.0   0:00.00 scsi_eh_0
   68 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 scsi_tmf_0
   70 root      20   0       0      0      0 S  0.0  0.0   0:00.00 scsi_eh_1
   72 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 scsi_tmf_1
   93 root      20   0       0      0      0 S  0.0  0.0   3:15.70 jbd2/vda1-8
   94 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 ext4-rsv-conver
  137 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kauditd
  157 root      20   0   37424   5052   2648 S  0.0  1.0 188:31.06 systemd-journal
  161 root      20   0   40792    476      4 S  0.0  0.1   0:00.07 systemd-udevd
  194 root      20   0       0      0      0 S  0.0  0.0   0:00.00 vballoon
  196 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kpsmoused
  271 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kvm-irqfd-clean
  448 root      20   0   37068    420      0 S  0.0  0.1   0:21.22 rpcbind
  460 statd     20   0   37268    596      8 S  0.0  0.1   0:00.00 rpc.statd
  476 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 rpciod
  478 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 nfsiod
  487 root      20   0   23348    200      0 S  0.0  0.0   0:00.00 rpc.idmapd
top nach ca. 4 Stunden Laufzeit. Die self. Variablen haben noch immer dieselbe Groeße: (nicht derselbe Tag)

Code: Alles auswählen

top - 19:48:26 up 70 days, 19:01,  1 user,  load average: 0.48, 0.73, 0.72
Tasks:  63 total,   2 running,  61 sleeping,   0 stopped,   0 zombie
%Cpu(s): 17.4 us,  0.3 sy,  0.0 ni, 81.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.3 st
KiB Mem:    506340 total,   450848 used,    55492 free,    53904 buffers
KiB Swap:        0 total,        0 used,        0 free.   184152 cached Mem

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND
 3287 root      20   0  752816 166400   8888 R 18.6 32.9  94:52.60 python3.4
    1 root      20   0   28556   3848   2256 S  0.0  0.8   1:50.87 systemd
    2 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kthreadd
    3 root      20   0       0      0      0 S  0.0  0.0  11:54.21 ksoftirqd/0
    5 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kworker/0:0H
    7 root      20   0       0      0      0 S  0.0  0.0  57:44.45 rcu_sched
    8 root      20   0       0      0      0 S  0.0  0.0   0:00.00 rcu_bh
    9 root      rt   0       0      0      0 S  0.0  0.0   0:00.00 migration/0
   10 root      rt   0       0      0      0 S  0.0  0.0   1:20.44 watchdog/0
   11 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 khelper
   12 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kdevtmpfs
   13 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 netns
   14 root      20   0       0      0      0 S  0.0  0.0   0:03.43 khungtaskd
   15 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 writeback
   16 root      25   5       0      0      0 S  0.0  0.0   0:00.00 ksmd
   17 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 crypto
   18 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kintegrityd
   19 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 bioset
   20 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kblockd
   22 root      20   0       0      0      0 S  0.0  0.0   0:53.73 kswapd0
   23 root      20   0       0      0      0 S  0.0  0.0   0:00.00 fsnotify_mark
   29 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kthrotld
   30 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 ipv6_addrconf
   31 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 deferwq
   65 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 ata_sff
   66 root      20   0       0      0      0 S  0.0  0.0   0:00.00 khubd
   67 root      20   0       0      0      0 S  0.0  0.0   0:00.00 scsi_eh_0
   68 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 scsi_tmf_0
   70 root      20   0       0      0      0 S  0.0  0.0   0:00.00 scsi_eh_1
   72 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 scsi_tmf_1
   93 root      20   0       0      0      0 S  0.0  0.0   3:18.52 jbd2/vda1-8
   94 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 ext4-rsv-conver
  137 root      20   0       0      0      0 S  0.0  0.0   0:00.00 kauditd
  157 root      20   0   37424   6104   3700 S  0.0  1.2 191:51.68 systemd-journal
  161 root      20   0   40792    476      4 S  0.0  0.1   0:00.07 systemd-udevd
  194 root      20   0       0      0      0 S  0.0  0.0   0:00.00 vballoon
  196 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kpsmoused
  271 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 kvm-irqfd-clean
  448 root      20   0   37068   1588   1168 S  0.0  0.3   0:21.55 rpcbind
  460 statd     20   0   37268    596      8 S  0.0  0.1   0:00.00 rpc.statd
  476 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 rpciod
  478 root       0 -20       0      0      0 S  0.0  0.0   0:00.00 nfsiod
  487 root      20   0   23348    200      0 S  0.0  0.0   0:00.00 rpc.idmapd
Wie bereits in vorherigen Posts erwähnt:
Das skript läuft als Service im Hintergrund. Die letzten prints (ungefähr der letzten stunde), sind vermutlich im systemd-journal gespeichert. Zusätzlich werden txt Dateien erstellt um über die Vorgänge informiert zu sein.

Wenn es nicht an der größe der Variablen liegt, woran kann es dann liegen?
Wir sehen also, über die variablen komme ich nicht weiter. Daher wäre sowas wie memory_profiler, welches den zusätzlich gebrauchten Memory pro Zeile angibt, schon sehr gut. Aber es muss halt auch mit einer while schleife mit mehreren Stunden Betrieb klappen, sonst ist es leider ziemlich nutzlos...
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Serpens: Am top kann man nicht erkennen, wieviel Speicher im Moment durch Pythonobjekte verbraucht werden, sondern nur einen Peak-Wert, also dass irgend wann einmal 33MB mehr an Speicher verbraucht wurden, was jetzt nicht sonderlich viel ist. Und wie schon mehrfach betont hilft es nicht, von außen nach irgendwelchem Speicherverbrauch zu suchen. Außer wenn irgendwo Werte gecached werden sollte es also nicht zu unnötigem Speicherverbrauch kommen, der nicht auch wieder aufgeräumt wird.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Sirius3 hat geschrieben:@Serpens: Am top kann man nicht erkennen, wieviel Speicher im Moment durch Pythonobjekte verbraucht werden, sondern nur einen Peak-Wert, also dass irgend wann einmal 33MB mehr an Speicher verbraucht wurden, was jetzt nicht sonderlich viel ist. Und wie schon mehrfach betont hilft es nicht, von außen nach irgendwelchem Speicherverbrauch zu suchen. Außer wenn irgendwo Werte gecached werden sollte es also nicht zu unnötigem Speicherverbrauch kommen, der nicht auch wieder aufgeräumt wird.
und trotzdem wird mein service nach 1-3 Tagen Laufzeit gekilled.
Also was kann ich tun?

Also sagst du, dass es wohl an gecacheden Werten liegt? Was heißt gecachede werte? Es gibt ja den pychache. Ich glaube das bedeutet, dass dort eine Kopie der Python scripte zwischengespeichert wird, um schnell drauf zuzugreifen, richtig? Aber das ist ja ebenfalls einmalig und sollte nicht immer mehr werden.
Wann werden noch Dinge gecached? das einzige was da für mich plausible klingt, ist das schreiben der txt Datei, aber das hattest du ja schon ausgeschlossen.
BlackJack

@Serpens66: Ich denke mal Sirius3 meint ausser wenn in Deinem Programm irgendwo Werte gecached werden. Entweder von Dir explizit oder von irgendeiner Bibliothek die Du verwendest. Da kann man aber jetzt wieder nicht viel sagen wenn man das Programm nicht kennt.

Hattest Du eigentlich den Speicherverbrauch mal kontinuierlich protokolliert? Steigt der innerhalb der drei Tage gleichmässig immer mehr an, oder kann es auch sein das nur kurz vorm Abschuss etwas passiert was ganz schnell den ganzen Speicher verbraucht? Also zum Beispiel Eingabedaten kommen bei denen das ausgelöst wird, entweder ”normal”, oder aber auch vielleicht durch einen Fehler in Deinem Programm‽
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

BlackJack hat geschrieben:@Serpens66: Ich denke mal Sirius3 meint ausser wenn in Deinem Programm irgendwo Werte gecached werden. Entweder von Dir explizit oder von irgendeiner Bibliothek die Du verwendest. Da kann man aber jetzt wieder nicht viel sagen wenn man das Programm nicht kennt.

Hattest Du eigentlich den Speicherverbrauch mal kontinuierlich protokolliert? Steigt der innerhalb der drei Tage gleichmässig immer mehr an, oder kann es auch sein das nur kurz vorm Abschuss etwas passiert was ganz schnell den ganzen Speicher verbraucht? Also zum Beispiel Eingabedaten kommen bei denen das ausgelöst wird, entweder ”normal”, oder aber auch vielleicht durch einen Fehler in Deinem Programm‽
Danke für die weiteren Ratschläge :)

Ich dachte eig , dass ich mit dem top befehl den aktuellen verbrauch sehen könnte. Wusste nicht, dass das nur ein peak ist.

Wie protokolliere ich denn den speicherverbrauch am besten? Vermutlich direkt im Skript, also stündlich den speicherverbrauch mit in der txt Datei speichern. Was ist dafür am besten geeignet? Ich gehe aber stark davon aus, dass es ein kontinuirlicher Prozess ist. Denn bei unter einem Tag Laufzeit ist noch nie ein Kill passiert.

bezüglich cache:
Könnt ihr denn Beispiele oderso nennen, wonach ich ausschau halten muss, um chache zu entdecken? Oder einen anderen weg, wie ich feststellen kann, ob eine von mir verwendete bibliothek cached? Da es ja keine meiner Variablen ist, die so groß wird, wäre das wohl die nächste Vermutung, dass es an einer bibliothek liegen könnte.
Abgesehen von Skripten für die API Anbindung, welche in der Regel requests verwenden, importiere ich noch:

Code: Alles auswählen

import requests
import json
from time import sleep
import time
import threading
import sys
import traceback
from random import randint
import math
from copy import deepcopy  ## sollte nicht zuoft verwendet werden, da ausführung lange dauert !! 
from decimal import *
edit:
die Klassen der api skripte werden nach dem import direkt geöffnet und offen gehalten, also
Api1 = apiskript.Apiklasse()
Ist es dann sinvoll, diese auch noch in die stündliche memory kontrolle reinzupacken, also sys.getsizeof(Api1) zu prüfen? Oder kann da eig nichts passieren? (sind eigentlich alles nur funktionen ohne self. variablen, also eig sollte da nach jeder Verwednung alles gelöscht werden)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Serpens66: was sollen denn API-Klassen sein? Funktionen in Klassen zu packen, wenn es kein self gibt ist ziemlich sinnfrei.
Serpens66
User
Beiträge: 259
Registriert: Montag 15. Dezember 2014, 00:31

Sirius3 hat geschrieben:@Serpens66: was sollen denn API-Klassen sein? Funktionen in Klassen zu packen, wenn es kein self gibt ist ziemlich sinnfrei.
keine ahnung. Die skripte die ich fertig gefunden habe hatten das alle. In der Regel gibt es self.secret und self.apikey. (also diese self Variablen gibt es schon) Für Skripte die ich dann geschrieben habe, hab ich das so übernommen.
Ich glaube ohne klasse könnte ich das skript im hauptskript eben nicht einmal mit apikey übergabe öffnen, sondern müsste dann überall immer wieder den key usw wiederholen.

Aber wie dem auch sei, das ist ja nicht das Thema...
Also wie überwache ich automatisch am sinnvollsten den Speicherverbrauch? Welcher Befehl gibt den aktuell genutzten Speicher des ganzen Skripts aus? Klar gibt es beim memory_profiler einen zeitlichen check und darstellung, aber memory_profiler scheint sehr ungeeignet für große skripte die über längere Zeit laufen sollen und es auf schnelligkeit ankommt.
Antworten