Cannot fork: Cannot allocate memory | BlockingInformParent

Begonnen von Burny4600, 14 Februar 2018, 10:33:06

Vorheriges Thema - Nächstes Thema

Hardlife

Zitat von: mumpitzstuff am 09 Oktober 2019, 00:42:00
Bei mir steigt mit dem HTTPMOD Device (habe das TV Device von oben importiert) der Speicherverbrauch ebenfalls an (Debian Buster). Der Anstieg selbst ist abhängig vom Intervall, je kürzer desto stärker ist der Anstieg. Setzt man das Device auf disable steigt der Verbrauch nicht weiter an. Die Readingsgroups habe ich rausgeschmissen und kann sie deshalb ebenfalls ausschließen.

Eine Sache ist mir bei deinen Regex Ausdrücken aufgefallen. Ersetz mal bitte alle:
</a>
durch
<\/a>

Meines Wissens muss ein / immer Escaped sein.

Danke schön, habe ich beherzigt und implementiert.
Hat zwar bisher funktioniert??? Und ändert nichts am Fehler... Aber auch ich schätzte möglichst korrekten Code  :)
Raspi 4B
nanoCUL-868 & 433,JeeLink,milight,Signalduino,GPIO-433er-Sender/Empfänger, GPIO-Infrarot,GSM-Stick für SMS
MAX!-Heizungssteuerung,Intertechno-V1-Steckdosen + V3-Dimmer,"Flamingo FA21RF"-Funk-Rauchmelder
433er-China-Bewegungsmelder,"Voltcraft CO20"-Stick,LaCrosse-Temperatur,Revolt-NC5462

Mave

Nachdem ich FREEZEMON entfernt habe, ist die Speicherauslastung meines RPi nun seit 3 Tagen konstant bei 260 MB +/- 20

Es scheint also nicht speziell an einem einzigen Modul zu liegen sondern abhängig von der Gesamtinstallation.

DS_Starter

@Rudi, vielen Dank für den Ansatz mit awk/VmSize. Dadurch gelingt die Analyse präziser als mit sysmon. Ich habe den Code auf DbLog zugeschnitten um die Werte in der DB zu speichern und auszuwerten. Anbei ein Vergleich zwischen sysmon und awk/pstat. Man sieht deutlich die Verzerrung der Werte durch den BlockingCall in der sysmon Ausgabe.
Dadurch ist es mir leichter gefallen eine weitere Speicheroptimierung bei der Verarbeitung von Cam-Aufnahmen vorzunehmen (ist eingecheckt) .

Zur Speicherverwaltung von Perl habe ich mich ein bisschen intensiver belesen und wenn ich alles richtig verstanden habe, stellt es sich folgendermaßen dar (bitte berichtigt mich wenn etwas nicht korrekt ist !).

Im Betrieb fordert Perl beim Betriebsystem Speicher an, sobald er für die Variablen, Hashes etc. benötigt wird. Sobald diese Variablen out of Scope gehen und keine Referenzen mehr darauf bestehen, wird der Speicher Perl-intern wieder freigegeben und kann wiederverwendet werden. 

Aber an das Betriebssystem wird dieser Speicher beim Abräumen (Garbage Collector) _nicht_ wieder zurück gegeben !

Das bedeutet, dass der User ein Ansteigen des Speichers solange beobachten wird, bis das System "eingeschwungen" ist. Das heißt wenn alle benötigten Variablen mindestens einmal verwendet wurden (Webinhalte abgerufen, Aufnahmen versendet, Caches gefüllt, etc), ist die High Water Mark des Speicherverbrauchs erreicht und stabilisiert sich.

Ausnahme ist der Fehlerfall, zum Beispiel weil zirkuläre Referenzen erstellt wurden, die nicht aufgelöst und abgeräumt werden können. Zum Beispiel verwendet das CPAN Modul HTML::TreeBuilder  solche Referenzen um seine Arbeit zu machen.
Diese müssen (in älteren Versionen von HTML::TreeBuilder) explizit aufgebrochen werden. HTTPMOD verwendet zum Beispiel dieses Modul.

CPAN sagt dazu:
Zitatprevious versions of HTML::TreeBuilder required you to call $tree->delete() to erase the contents of the tree from memory when you're done with the tree. This is not normally required anymore. See "Weak References" in HTML::Element for details.

Man muss es eigentlich aktuell nicht mehr tun, aber CPAN sagt auch "normalerweise".  Wäre ein Ansatz bzgl. HTTPMOD, aber _nur_ eine Vermutung !!

BlockingCalls gehen in die Betrachtung überhaupt nicht ein, weil die dort erstellten Variablen mit Beendigung des parallelen Prozesses zerstört werden und der Speicher an das Betriebssystem zurück gegeben wird.

Vielleicht hilft es das Speicherverhalten besser einordnen zu können und ich hoffe alles richtig dargestellt zu haben. Wie gesagt, berichtigt mich bitte wenn nötig.

Grüße,
Heiko

ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

rudolfkoenig

"Garbage Collector" wuerde ich fuer das bei Java verwendete Verfahren reservieren: grob geht es um ein Thread, was parallel zum Rest laeuft, den Speicher untersucht, und freigegebene Speicherbereiche einsammelt. Ein Speicherstueck kann nach Freigabe nicht sofort wieder benutzt werden, erst wenn der Garbage-Collector es gefunden hat. Diese Methode hat kein Problem mit zirkulaeren Referenzen, kann aber den Prozess laenger blockieren, insb. wenn sehr viel Speicher alloziert ist.

Perl hat keinen separaten Thread, wenn der Referenzcounter eines Speicherstuecks auf 0 faelt, kann es sofort wiederverwendet werden. Diese Methode hat Probleme mit zirkulaeren Referenzen, bremst aber weniger. Dass der Speicher bei Freigabe nicht ans OS zurueckgegeben wird, liegt an dem verwendeten Malloc-Library (eine weitere Abstraktionsschicht, bekannt aus C), obwohl sie bemueht sich: https://stackoverflow.com/questions/2215259/will-malloc-implementations-return-free-ed-memory-back-to-the-system

nuccleon

Zitat von: DS_Starter am 10 Oktober 2019, 23:12:42
@Rudi, vielen Dank für den Ansatz mit awk/VmSize. Dadurch gelingt die Analyse präziser als mit sysmon. Ich habe den Code auf DbLog zugeschnitten um die Werte in der DB zu speichern und auszuwerten.
Top!
Würdest du den Code dazu hier teilen?

DS_Starter

#665
ZitatWürdest du den Code dazu hier teilen?

Natürlich, gerne.

In die 99_myUtils kommt dieses kleine Stückchen:


############################################################################################################
#       RAM Verbrauch von Perl ermitteln und mit "<DbLog-Device>" speichern
#       Aufruf mit: { psize("<DbLog-Device>") }
############################################################################################################
sub psize($) {
    my ($name) = @_;
   
my $ts  = FmtDateTime(time);
my $ret = $ts."|psize|manual|manual|size|";
my $v   = `awk '/VmSize/{print \$2}' /proc/$$/status`;
$ret   .= sprintf("%.2f",(rtrim($v)/1024));
$ret   .= "|MB";

fhem ("set $name addCacheLine $ret");

return;
}


EDIT: DbLog muss im asynchronen Mode laufen wegen "addCacheLine".
Der Aufruf erfolgt dann mit "{ psize("<DbLog-Device>") }". Dazu habe ich ein at erstellt, was den Aufruf regelmäßig durchführt:


defmod AT.pSize at +*00:01 { psize("LogDBShort") }
attr AT.pSize icon clock
attr AT.pSize room Dienste->Monitoring


Hinweis: weil doch sehr viele gleiche Werte geloggt werden, kann man dann mit DbRep eine sehr einfache  Datenreduzierung vornehmen mit:


set <DbRep-Device> delSeqDoublets delete


Das habe ich dann auch regelmäßig über ein at eingeplant um nur die Pegeländerungen in der DB zu halten.

Grüße,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

StefanStrobel

Hallo,

Treebuilder wird von HTTPMOD nur verwendet, wenn in der Konfiguration mit XPath gearbeitet wird.

        } elsif ($aName eq "enableXPath"
                || $aName =~ /(get|reading)[0-9]+XPath$/
                || $aName =~ /[Rr]eAuthXPath$/
                || $aName =~ /[Ii]dXPath$/) {
            eval "use HTML::TreeBuilder::XPath";
            if($@) {
                return "Please install HTML::TreeBuilder::XPath to use the xpath-Option (apt-get install libxml-TreeBuilder-perl libhtml-treebuilder-xpath-perl) - error was $@";
            }
            $hash->{XPathEnabled} = ($aVal ? 1 : 0);
        }

In dem von Hardlife beschriebenen Problem ist aber alles mit Regexes umgesetzt.
Ich habe seine (abgespeckte) Konfiguration über Nacht und eine Weile sogar mit 10-Sekunden-Intervall auf meinem Raspberry laufen lassen, aber keinen Speicheranstieg nachvollziehen können.

Es muss also tatsächlich an weiteren Parametern liegen.

Gruss
   Stefan

mumpitzstuff

Was für ein Raspbian verwendest du denn? Unabhängig von Hardlife konnte ich (ich habe buster installiert) und noch ein weiterer User das sofort nachvollziehen. Bei mir läuft auf dieser fhem Installation auch kaum mehr als ein paar Sensoren, die per FHEM2FHEM von der Hauptinstallation abgefragt werden.

StefanStrobel

Hallo,

ich habe es auf Stretch mit Perl 5.24.1.

seit heute morgen habe ich auch noch einen Test mit der vollen Konfiguration von Hardlife am Laufen.
Mal sehen was da passiert.
Eventuell ist da ja etwas drin, was den Fehler auslöst, aber bei seiner reduzierten Konfiguration (auch ohne Readingsgroup) fehlt.
Auf den ersten Blick sah es jedoch so aus, als ob es einfach nur mehr Readings mit mehr Regexes wären ...
Ich bleibe dran.

Gruss
   Stefan

fhemxperte

Eventuell kann ich noch etwas beitragen? Ich nutze seit mindestens einem Jahr perl 5, version 20, subversion 3 (v5.20.3) built for x86_64-linux-thread-multi. Alle darüberliegenden Perl-versionen haben bei mir generell zu einem Speicheranstieg geführt, welches ich nicht eingrenzen konnte.


Erklärung zum Dateianhang:
(1) Bis zum 19.10.2019 hatte ich das KODI Modul mit IP Adressen als Ziel im internen Netzwerk laufen.
(2) Seitdem ich die Einstellung auf DNS (z.B. htpc-pi2.fritz.box) umgestellt habe, ist ein deutlich linearer Speicheranstieg zu beobachten (4 eingerichtete Module im 60 Sekunden polling Takt) mit mehreren Neustarts
(3) Hier habe ich auf einem Snapshot meiner Produktions-VM herumgetestet ... daher keine Daten
(4) Hier bin ich wieder zurückgeswitched auf IP-Adresse und es sieht (zumindest in dem kurzen Zeitraum) wieder besser aus


Womöglich hat Perl, das KODI Modul oder FHEM ein DNS Namensauflösungsproblem? Eventuell können andere das Problem hiermit auch eingrenzen?

Frank_Huber



Zitat von: fhemxperte am 14 Oktober 2019, 18:44:42
Womöglich hat Perl, das KODI Modul oder FHEM ein DNS Namensauflösungsproblem? Eventuell können andere das Problem hiermit auch eingrenzen?

Ich glaube hierfür wäre es noch wichtig zu wissen ob Du im global das dns Server Attribut gesetzt hast.

Gesendet von meinem S60 mit Tapatalk


fhemxperte

ZitatIch glaube hierfür wäre es noch wichtig zu wissen ob Du im global das dns Server Attribut gesetzt hast.

Korrekt, danke für den Gedankenanstoß. Den hatte ich nicht mehr im Kopf...

Meine Einstellung ist dnsServer=127.0.0.1, da ich lokal den Pi-Hole betreibe, somit sollte die Namensauflösung über den "FHEM specific nonblocking code" gehen anstatt über das OS.

rudolfkoenig

Wenn HttpUtils die interne Namensaufloesung verwendet (d.h. dnsServer ist gesetzt), dann wird das Ergebnis jeder Namensaufloesung gespeichert.
Das fuehrt zum Speicherloch, wenn man staendig andere Rechnernamen aufloesen will. Ich gehe davon aus, dass das nie der Fall ist.

Man kann aber pruefen, ob sie die Ursache ist, indem man dnsServer entfernt.

herrmannj

#673
Für alle die perl downgraden möchten (Linux)

* https://perlbrew.pl/


\curl -L https://install.perlbrew.pl | bash
echo source ~/perl5/perlbrew/etc/bashrc >> $HOME/.bashrc
perlbrew install perl-5.20.2
perlbrew switch perl-5.20.2


edit fhem.service

sudo nano /etc/systemd/system/fhem.service


richtigen Pfad eintragen. Im Zweifel echo $PATH

ExecStart=/home/pi/perl5/perlbrew/perls/perl-5.20.2/bin/perl fhem.pl fhem.cfg
#ExecStart=/usr/bin/perl fhem.pl fhem.cfg



sudo systemctl daemon-reload
sudo service fhem restart


Prüfen ob fhem läuft. Dann in der Eingabezeile von fhem die richtige perl version prüfen: (hier dann 5.20.2)
{$^V}

cpanm (https://perlbrew.pl/Perlbrew-and-Friends.html)
perlbrew install-cpanm

rudolfkoenig

Ab sofort kann man den HttpUtils internen Cache (d.h. wenn dnsServer gesetzt ist ) ausgeben mit:

fhem> { HttpUtils_dumpDnsCache() }
amazon.de    TS: 2019-10-14 21:15:14   TTL:   171   ADDR: 54.239.39.102
fhem.de      TS: 2019-10-14 21:13:54   TTL: 49166   ADDR: 88.99.31.202
google.com   TS: 2019-10-14 21:13:49   TTL:    11   ADDR: 172.217.16.78
heise.de     TS: 2019-10-14 21:13:51   TTL: 44493   ADDR: 193.99.144.80