Speicherauslastung Java bei eigenem Programm

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo Leute,

    ich habe hier schon viel gelesen, aber zu meinem Problem noch keine Lösung gefunden.

    Kurz zu mir:
    Meine Java Kenntnisse sind noch recht einfach. Kenne mich aber ganz pasabel mit C# (für ab und zu mal Hobbyprogrammieren) und C (für Mikroprozessor) aus. Linux ist für mich auch neu. Bisher nur DOS und Windows.
    Auf dem PI läuft Rasbian (aktuelles NOOBS Image 1.3.4). Da ist Java 1.7.0_40 enthalten.

    Mein Projekt: (noch nicht alles drin!)
    Ich habe einen PI mit 512MB Ram. Dort lese ich per RS232 einen Datenstring aus, den ich von einem µC bekommen. Da sind Temperaturen, Feuchtigkeit, Druck und so weiter drin. Ist so ne Art Wetterstation. Empfangen werden zwei Strings mit jeweils ca. 250 Zeichen. Dafür nutze ich pi4j. Die Daten sollen auf der SD Card oder nem externen USB Stick gespeichert werden. Ich will aller 10-30s einen Datenstring speichern. Eventuell auch auf einem Web Server anzeigen. Das ist aber erstmal nur "nice to have".
    Geschrieben wird das ganze in Eclipse Indigo und compillliert auf dem PI.Erstellt habe ich ein Standard Java Projekt wo ich pi4j als Libs eingebunden habe.

    Mein Problem:
    Ich habe ein Programm geschrieben wo ich aktuell die akt. Datum, akt. Uhrzeit, Mem Used, Mem Free, SD Card used und SD Card free speichere. Das läuft im Sekundentakt. Das Programm läuft auch recht gut,
    ABER!:

    wenn ich das Java Programm starte hat es laut "ps au" bereits 233156 VSZ (ist doch virtueller Ram, oder? und RSS von 12068 (habe ich noch nicht herrausgefunden was das ist). Das VSZ bleibt die ganze Zeit gleich. RSS erhöht sich langsam. Nach 2h ist es dann 13876. Bleibt dann aber relativ gleich. Das große Problem ist eher, dass der Ram halt mehr ausgelastet wird. Also beim Start habe ich z.B. 100Mb Ram ausgelastet. 10Mb nimmt er sofort und dann nach 2h sind es schon 115Mb. Nach drei Tagen sind es 270Mb. Länger habe ich es noch nicht laufen lassen. Ich bin auf dem PI nur mittels Putty drauf und PI läuft nur auf Konsole. Also ohne startx.

    Es wird aber auch nie Ram freigemacht. Als würde der GC nicht laufen. Wenn ich das Programm anhalte, gibt er ungefähr 10Mb Ram frei. Der Rest bleibt in Nutzung. Bei ps au verschwindet der Prozess aber komplett. Wenn ich es dan wieder neu starte geht das gleich spiel wieder los. Er nimmt 10Mb sofort und den Rest dann Stück für Stück.
    Wenn ich das Programm am PC laufen lasse, startet er laut Task Manager bei z.B. 12Mb, läuft dann bis ca. 13,8Mb voll und verringert sich auch ca. 1Mb und dann wieder bis 13,8Mb. So geht das den ganzen Tag. Auf dem PI geht es nur nach oben.

    Mache ich irgendwo ein Fehler oder habe ich etwas übersehen.


    Als Vorlage für meine Routinen nutze ich die Programmschnipsel hier: http://www.mkyong.com/tutorials/java-io-tutorials/ Die Erfassung der Zeit habe ich aus nem Java Buch. Ich gehe mal davon aus, das das daran nicht liegen kann.

    Aber hier mal der Schnipsel:

    Code
    // actual Date of the PI
        public String aktDate() {
            
            String DateText = new SimpleDateFormat("dd.MM.YYYY").format(new Date());
            
            return DateText;
        }


    Er erzeugt damit zwar immer ne neue SimpleDateFormat, aber wen er das neu erzeugt, kann das alte ja vom GC weggelöscht werden, oder? Man soll ja den GC nicht einfach in nem Loop aufrufen. Das macht der doch selber, oder?

    So erzeuge ich die Messdatei:


    Ich habe auch mal das Programm in Java mittels *** -Xmx15m gestartet. Hat auch keine Änderung gebracht. Habe auch mal Java 8 probiert. Da isses das selbe. Also muss es ja an mir liegen.

    Habt ihr evetuell ne Idee warum der immer mehr Ram frisst?

    Danke euch.
    Arno


  • ... warum der immer mehr Ram frisst?

    Schau mal wie viel RAM sich frei machen lässt. Z. B. mit:

    Code
    free -m
    Code
    sync
    Zitat
    Code
    sudo sysctl -w vm.drop_caches=3
    Code
    free -m

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

    Einmal editiert, zuletzt von rpi444 (17. Januar 2014 um 15:41)

  • Hallo rpi444,

    wow, danke für dein Beitrag. Jetzt sind wieder über 230Mb mehr Ram frei. :bravo2:


    Aber jetzt ist die Frage, habe ich was falsch Programmiert, oder muss ich einfach einmal am Tag mittels Cron Job diesen Befehl ausführen? Also Fehler bei mir oder "Fehler" im Linux. Ich gehe davon aus, dass andere das auch haben würden, also Fehler bei mir, oder? :blush:

    Weil laut "ps au" ist das Programm immer noch gleich groß im Speicher vertreten. So konstant ist das schon seit fast 2 Tagen.

    Code
    root      2530  0.0  0.3   4824  1460 tty1     S+   Jan14   0:00 sudo java -clas
    root      2531  1.8  3.1 233408 14276 tty1     Sl+  Jan14  73:44 java -classpath

    Und in den paar Minuten die ich das hier getippt habe, ist der Speicher bereits wieder gesunken :s

    Code
    pi@raspberrypi ~ $ free -m
                 total       used       free     shared    buffers     cached
    Mem:           437         44        393          0          2         11
    -/+ buffers/cache:         30        407
    Swap:           99          0         99

    Also ist irgendwo noch was nicht ganz in Ordnung, nehme ich jedenfalls mal an.:huh:

    :danke_ATDE:für den super Tip
    Arno


  • Aber jetzt ist die Frage, habe ich was falsch Programmiert, oder muss ich einfach einmal am Tag mittels Cron Job diesen Befehl ausführen? Also Fehler bei mir oder "Fehler" im Linux. Ich gehe davon aus, dass andere das auch haben würden, also Fehler bei mir, oder? :blush:

    Nein, diesen Befehl musst Du nicht einmal am Tag ausführen. Einen Fehler kann man hier auch nicht erkennen. Linux kann mit dem RAM effizient umgehen und Du bist bestrebt Programme zu schreiben, die möglichst mit wenig RAM auskommen. Aber der RAM ist doch auch dafür da, dass er benutzt wird. Dein Programm veranlasst den Pi noch nicht, SWAP zu benutzen. Wenn Du feststellen willst wie viel Speicher einzelne Prozesse (+ libraries/module/etc.) benutzen, dann kannst Du z. B. auch "pmap" (pmap - report memory map of a process) benutzen. Siehe die Ausgaben für:

    Code
    which pmap
    Code
    man pmap


    Beispiel:

    Zitat


    ~ $ sudo pmap -d $(pidof ngircd) | grep mapped
    mapped: 4568K writeable/private: 596K shared: 0K

    Ein anderes tool ist nmon.

    Code
    sudo apt-get install nmon
    Code
    which nmon
    Code
    man nmon


    Für memory anzeigen: nach dem Start mit "nmon", interaktiv m.

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

  • Ich könnte vermuten, dass du in deinem Programm Speicher anforderst, den der GC nicht frei machen kann. Deine Codeschnipsel sind aber OK. Initialisiert du irgendwo ein Array oder eine Collection? Beim Auslesen der Hardware vielleicht?
    Etwas mehr Quellcode wäre gut.

  • Ok, dann mal hier der Rest vom PRogramm. Wie bereits geschrieben. Bin noch icht so weit gekommen. ISt mir halt gleich aufgefallen, dass der Ram so voll wird.


    Main_Loop:


    Filehandling:


    System_Info:

    Mehr isses leider noch nicht. Deswegen isses ja so "nervig" das ich mit dem bissel Code schon solche "Probleme" habe :)

    Vielleicht findet ihr ja nochwas. Wie schon geschrieben, bin noch Anfänger. Also wenn ihr verbesserungsverschläge habt, immer her damit :)

    :danke_ATDE:
    Arno

  • Hallo Arno,

    kann es sein, daß Du die Ausgabe von "free" falsch interpretierst?

    Beispiel:

    Code
    > free -m
            total       used       free     shared    buffers     cached
    Mem:      460        264        195          1          0        238
    -/+ buffers/cache:    25        435

    Wichtig für Dich ist nur die 2.te Zeile: aktuell sind hier 25 MB belegt und 435 MB frei.

    Der Kernel ist intelligent genug, bereits beendete Programme und Daten einstweilen im Cache zu behalten, sie könnten ja evtl. nochmal benötigt werden - das zeigt die 1. Zeile.

    Gruß, mmi

  • Guten morgen,

    Zitat


    Wichtig für Dich ist nur die 2.te Zeile: aktuell sind hier 25 MB belegt und 435 MB frei.

    Ich habe nach der obersten Zeile geschaut. Was bedeutet dann die oberste Zeile?
    Da ist ja jetzt natürlich peinlich :wallbash: :angel:

    :danke_ATDE:
    Arno


  • Was bedeutet dann die oberste Zeile?

    Mach mal die Summe aus: "shared" + "buffers" + "cached" + "used aus der 2. Zeile".

    The most popular websites without IPv6 in Germany.  IPv6-Ausreden

    Meine PIs

    PI4B/8GB (border device) OpenBSD 7.4 (64bit): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server

    PI3B+ FreeBSD 14.0-R-p3 (arm64): SSH-Serv., WireGuard-Serv., ircd-hybrid-Serv., stunnel-Proxy, Mumble-Serv., ddclient

    PI4B/4GB Bullseye-lite (64bit; modifiziert): SSH-Server, WireGuard-Server, ircd-hybrid-Server, stunnel-Proxy, Mumble-Server, botamusique, ample

  • Siehe dazu auch: http://wiki.debianforum.de/Linux_Speichermanagement

    Zitat

    Da ungenutzter Speicher bekanntlich verschwendeter Speicher ist, behält Linux einmal vorhandene Daten im Hauptspeicher, solange dieser nicht für laufende oder neu gestartete Programme benötigt wird.

    Werden nun bereits zu einem früheren Zeitpunkt benötigte Daten erneut angefordert, so besteht eine gute Chance, dass sich diese noch immer im Cache befinden. Von dort lassen sie sich um ein Vielfaches schneller auslesen als von der Festplatte und selbst wenn die gewünschten Daten sich im Cache nicht mehr vorfinden und doch auf die Platte zugegriffen werden muss, verzeichnet man unterm Strich keinerlei Einbußen.

    In diesem Zusammenhang belegter Speicher ist im Grunde genommen also freier Speicher, er wird lediglich einer sinnvollen Verwendung zugeführt, bis er anderweitig benötigt wird.

  • Dein Programm hat keine groben Fehler - ich denke mal ncht, dass es Probleme machen wird. Was nicht ganz sauber ist, ist das Dateihandling. Im Try/Catch/Block ist auch das Schließen der Datei. Wenn es dort zu einen Fehler kommt, wird das Betriebssystem ist Datei nicht schließen. Daher gehört die Methode in einen finally-Block, der immer durchlaufen wird. Das nur am Rande und hat weniger mit deinem Problem zu tun.

    Die Antwort ergibt sich eher aus den Anworten weiter oben. Linux hat ein Motto: nicht genutzter Speicher ist schlechter Speicher. Daher ist ein RAM-Verbrauch erst mal nichts schlechtes.

  • Die Berechnung wieviel RAM tatsächlich verwendet wird, müsste glaub ich so aussehen:

    Vorraussetzung: apt-get install bc

    in bash:

    Ausgabe wäre:

    Code
    53.85MB/485.30MB (11.00%)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!