FHEM Hauptschleife (MAIN)

Begonnen von jw2013, 16 Januar 2024, 01:48:36

Vorheriges Thema - Nächstes Thema

jw2013

FHEM verwendet leider die select()-Anweisung, deren Performance wird bekanntermaßen mit jedem weiteren Datei-Handle schlechter.

Ab einer bestimmten Menge an Objekten verbrät das System fast die gesamte CPU-Zeit nur noch in den Schleifen vor und nach der select-Anweisung, statt mit 'echten' Aufgaben.

Deswegen gibt es für verschiedene Betriebssysteme schon ewig Alternativen, unter Linux z.B. epoll.
Diese haben ein Laufzeitverhalten von O(1) anstatt O(n).

M.Schulze

Ich glaube nicht das aktuell jemand auf ein anderes System wechselt weil FHEM 'Select' benutzt.

Auch war die Performance nie ein Problem.


Eine wirkliche Innovation  wäre es gewesen die "FHEM Hauptschleife" bzw. FHEM.pl in "C" zu konvertieren und auf die Clients zu bringen, analog ESPHome, halt FHEMHome.
Weitere Modulautoren hätten sich dann bestimmt gefunden.


EPoll wird z.B. im ESP-IDF nicht supported.

MfG
Muss ich hier das Licht aus machen?

jw2013

Zitat von: M.Schulze am 17 Januar 2024, 09:41:53Ich glaube nicht das aktuell jemand auf ein anderes System wechselt weil FHEM 'Select' benutzt.

Auch war die Performance nie ein Problem.

Diese pauschale Aussage ist so leider nicht richtig.
FHEM läuft i.d.R. als einzelner Prozess, und wenn dieser den CPU Kern zu 100% auslastet, ist Ende.

Mit 1-2 Familienhäusern hatte ich vorher keine Probleme, mit größeren Objekten werden auf einem RPi4 leider die 100% erreicht, und das System funktioniert nicht mehr korrekt.
Das war ja überhaupt erst der Grund für mich, da mal 'reinzuschauen'.


ZitatEine wirkliche Innovation  wäre es gewesen die "FHEM Hauptschleife" bzw. FHEM.pl in "C" zu konvertieren und auf die Clients zu bringen, analog ESPHome, halt FHEMHome.
Weitere Modulautoren hätten sich dann bestimmt gefunden.

Sehe ich etwas anders. FHEM funktioniert perfekt als HAL oder Backend zwischen der Hardware (Sensoren+Aktoren) und der Software für die Hausverwaltung und Bewohner. Und auch wenn die Web-Oberfläche nicht gerade die modernste ist, für die Administration der Hardware funktioniert sie recht gut.

Zumindest in meinem Anwendungsfall wäre es absolut kontraproduktiv, die Haupt-Schleife auf die Clients zu bringen.


ZitatEPoll wird z.B. im ESP-IDF nicht supported.

Was hat epoll mit dem ESP zu tun? Ich rede von dem epoll, das irgendwann in den 2.5er Linux-Kernel aufgenommen wurde, da der Mechanismus um 'select' performance-technisch eine Katastrophe darstellt. BSD und MacOS haben aus dem gleichen Grund die 'kqueue' erhalten, und auch Windows bietet eine entsprechende API.

Ich hab schon einige Software von 'select' nach 'epoll' portiert, auch in Perl. Das Beste wird sein, ich schreibe einen minimal-invasiven Code als Proof-of-Concept, dann kann @rudolfkoenig entscheiden, was er damit anstellt.


DasQ

Also hier laufen neben Fhem noch etliche andere Prozesse und den von dir geschilderten Effekt kenn ich nicht.

Selbst wenn ich wie ein hirni alle Logs ins Image laufen lass bekomm ich Fhem nicht klein. Macht man natürlich aber auch nicht.
Fhem on MacMini/Ubuntu.
Absoluter Befürworter der Konsequenten-Kleinschreibung https://de.wikipedia.org/wiki/Kleinschreibung
Infos zu Klimawandel http://www.globalcarbonatlas.org

jw2013

Andere Prozesse haben damit ebensowenig zu tun wie die Logs...
Es geht um die CPU-Nutzung des Kerns, auf dem fhem als Single-Thread Applikation läuft.

Das Problem tritt auf, wenn fhem auf sehr vielen Handles, die z.B. zu offenen USB-(Serial)-Geräten und TCP-Verbindungen gehören, operiert.
Vor und nach jedem Select muss das System für den 'select'-Call über Listen iterieren, deren Länge von der Anzahl ebendieser Handles abhängt, unabhängig von den tatsächlich eintreffenen Daten.

D.h. das System wird schon durch die pure Existenz weiterer offener Verbindungs-Handles langsamer, selbst wenn immer nur über ein einzelnes Handle Daten laufen. Das ist ein Grund-Problem des Designs des select-Calls, weswegen quasi auf allen Platformen alternative API eingeführt wurden.

Ich kann und will hier nicht alles im Forum erklären, das würde den Rahmen sprengen. Als Anregung ein paar Infos und Links:

https://devarea.com/linux-io-multiplexing-select-vs-poll-vs-epoll/

Gnome bzw. die darunter liegende glib hatte epoll vor über 10 Jahren eingeführt:

https://gitlab.gnome.org/GNOME/glib/-/issues/693

Auch Node.js bzw. libuv verwenden unter Linux epoll statt select:

http://docs.libuv.org/en/v1.x/design.html

Hoffe das hilft...

DasQ

Fhem on MacMini/Ubuntu.
Absoluter Befürworter der Konsequenten-Kleinschreibung https://de.wikipedia.org/wiki/Kleinschreibung
Infos zu Klimawandel http://www.globalcarbonatlas.org

jw2013

Das ist schwer zu pauschalisieren, da es auf den durchschnittlichen IO auf allen Handles ankommt.

Beispiele für die reine IO-Schleife (Daten-Event-Pumpe), unter der Annahme, daß der Traffic mit weiteren Handles linear ansteigt, und ohne Berücksichtigung weiterer Verarbeitung:

select:

10 offene Verbindungen => ca. 1% CPU
50 offene Verbindungen => ca. 25% CPU
100 offene Verbindungen => ca. 100% CPU

epoll:

10 offene Verbindungen => ca. 0,5% CPU
50 offene Verbindungen => ca. 2,5% CPU
100 offene Verbindungen => ca. 5% CPU

Bei 'select' wächst die CPU Last exponentiell an, bei 'epoll' nur linear.

xenos1984

Zitat von: jw2013 am 18 Januar 2024, 17:30:02Bei 'select' wächst die CPU Last exponentiell an, bei 'epoll' nur linear.

Das ist quadratisch, nicht exponentiell.

betateilchen

Zitat von: jw2013 am 17 Januar 2024, 17:50:46Mit 1-2 Familienhäusern hatte ich vorher keine Probleme, mit größeren Objekten werden auf einem RPi4 leider die 100% erreicht, und das System funktioniert nicht mehr korrekt.

Macht man sowas wirklich noch auf einer Hardwareplattform, die ursprünglich als Spielzeug für Schüler entwickelt wurde?
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

tpm88

Zitat von: betateilchen am 18 Januar 2024, 17:56:16Macht man sowas wirklich noch auf einer Hardwareplattform, die ursprünglich als Spielzeug für Schüler entwickelt wurde?

Das ist nicht der Punkt, den der TE versucht zu diskutieren. Es ist nicht wirklich sinnvoll, Performance-Probleme generell mit schnellerer Hardware zu erschlagen. Stichwort "Ressourcen"... Oder bekommt die Idee erst gar keine Chance, weil der TE erst ein paar Beiträge im Forum hat?

Eigentlich hat keiner von allen, die bisher geantwortet haben, sich überhaupt mit der Frage select vs epoll (oder Alternativen) beschäftigt.

ZitatIch hab schon einige Software von 'select' nach 'epoll' portiert, auch in Perl. Das Beste wird sein, ich schreibe einen minimal-invasiven Code als Proof-of-Concept, dann kann @rudolfkoenig entscheiden, was er damit anstellt.
Top!

Meine Vorlesung zum Thema Komplexitätstheorie liegt zwar schon eine Weile zurück, aber einen Widerspruch glaube ich auch gesehen zu haben:

ZitatDeswegen gibt es für verschiedene Betriebssysteme schon ewig Alternativen, unter Linux z.B. epoll.
Diese haben ein Laufzeitverhalten von O(1) anstatt O(n).

vs

ZitatBei 'select' wächst die CPU Last exponentiell an, bei 'epoll' nur linear.

Also was nun?





Test FHEM Server on RPi, CUL_HM
Prod FHEM Server on Odroid HC1, HM-USB, JeeLink
Devices: diverse HM, IT1500, 1wire, LaCrosse, MQTT

DasQ

Ähmm nein!

Also ich hab mir jetzt nochmals den Thread durchgelesen.
Die Geschichte mit epoll wurde zunächst ja nur als Beispiel genannt. Das es aber primär darum geht wurde erst durch die verschieden Fragen bzw. Postings klarer.
Also pauschal zu sagen das es sich nicht darum dreht ist einfach falsch.

Das ist erst später raus gekommen.

Man muß doch auch erlauben, wenn ein Thread zunächst uneindeutig scheint, das man das eigentliche Problem rausarbeitet.
Das anfangsposting gibt das ja noch nicht her.


Ich war zunächst der Meinung es geht um ein Performance Problem bei ihm.
Ahnte aber schon das es ihm um viel mehr geht.

Naja und da ich da auch nicht wirklich weiterhelfen kann, dacht ich, man pusht den Thread in dem man antwortet. Rudi scheint ja noch nicht darauf aufmerksam geworden zu sein. Sei's wies is, ich kann hier nur noch Mäuschen spielen und andächtig mitlesen.
Fhem on MacMini/Ubuntu.
Absoluter Befürworter der Konsequenten-Kleinschreibung https://de.wikipedia.org/wiki/Kleinschreibung
Infos zu Klimawandel http://www.globalcarbonatlas.org

jw2013

Zitat von: xenos1984 am 18 Januar 2024, 17:48:16Das ist quadratisch, nicht exponentiell.

Good catch, Danke! Quadratisch.


Zitat von: betateilchen am 18 Januar 2024, 17:56:16Macht man sowas wirklich noch auf einer Hardwareplattform, die ursprünglich als Spielzeug für Schüler entwickelt wurde?

Absolut, und noch einiges mehr :-)


Zitat von: tpm88 am 18 Januar 2024, 19:44:58Es ist nicht wirklich sinnvoll, Performance-Probleme generell mit schnellerer Hardware zu erschlagen.

100% Zustimmung! Bin mit dem C64 und [34]86ern aufgewachsen, da nimmt man die Rechenleistung moderner RPis ganz anders wahr.


Zitat von: tpm88 am 18 Januar 2024, 19:44:58Meine Vorlesung zum Thema Komplexitätstheorie liegt zwar schon eine Weile zurück, aber einen Widerspruch glaube ich auch gesehen zu haben:

ZitatDeswegen gibt es für verschiedene Betriebssysteme schon ewig Alternativen, unter Linux z.B. epoll.
Diese haben ein Laufzeitverhalten von O(1) anstatt O(n).

vs

ZitatBei 'select' wächst die CPU Last exponentiell an, bei 'epoll' nur linear.

Also was nun?


Den Widerspruch kann ich aufklären: Das Laufzeitverhalten O(n) bzw. O(1) bezieht sich auf die Funktion selbst.

Wenn jetzt durch jedes der 'n' Verbindungs-Handles pro Sekunde z.B. 1 Event getriggert wird, wird die Funktion dann zusätzlich zu ihrem Laufzeit-Verhalten n-mal aufgerufen. Daher die quadratische bzw. lineare Last in der Praxis.


Zitat von: DasQ am 18 Januar 2024, 22:30:17Ich war zunächst der Meinung es geht um ein Performance Problem bei ihm.
Ahnte aber schon das es ihm um viel mehr geht.

Ich verstehe, was Du meinst, @DasQ!

Um hier nicht Eure Hilfsbereitschaft zeitlich zu stark mit meinem Thema zu blockieren, kurze Zusammenfassung und Vorschlag:

Es geht mir um ein Performance-Problem bei meinen Installationen.
Die Ursache des Problems besteht Plattform-übergreifend.
Ich kenne die Lösung für eine Plattform (Linux/epoll).
Die Behebung auf dieser Plattform wird für mich völlig ausreichen.
Ich gehe aufgrund der Antworten in diesem Thread nicht davon aus, daß das bekannt war, und ich meine Zeit mit redundanter Entwicklung verschwenden würde.
Die Implementierung ist aufgrund des bestehenden Codes nicht ganz trivial (keine API, sondern verschachtelte Perl Hashs), aber mit Perl tie und ein paar weiteren Kniffen machbar.
Ich bin schon soweit, dass ich es als Modul implementieren kann, ohne etwas an fhem.pl ändern zu müssen.

Das werde ich die nächsten Tage erledigen und hier hochladen. Dann kann das jeder testen, und ggf. 'Rudi' vorlegen.

jw2013

#12
Ich hätte ein erstes Modul fertig. Wie vermutet muss sich das System für die epoll-Strukturen alles aus verschachtelten Perl-Hashs extrahieren, und diese dazu über mehrerer tie's an Perl-Klassen binden, was kein sonderlich sauberes Design darstellt, aber vom Prinzip her funktioniert es.

Allerdings, mein eigentliches Problem ist leider noch nicht behoben. Mit dem EPOLL Modul komme ich auf dem Test-System von einer Grundlast zwischen 45-50% CPU runter auf 35-40%.
War dort also nicht die Haupt-Ursache, wird aber zukünftig hilfreich für die größeren Deployments.

Ich habe dann noch weiter analysiert, und einzelne Defs entfernt.
Ohne die OBIS und EnOcean (TCM ESP2) Instanzen komme ich unter 1%, d.h. dort gehe ich als nächstes dran...

Wer das EPOLL Modul testen möchte (bitte noch nicht in produktiven Systemen einsetzen, auch wenn es bei mir stabil läuft):

- das Modul kommt einfach ins FHEM/ Verzeichnis
- benötigt das IO::Epoll Modul, bei Raspberry OS / Debian: apt-get install libio-epoll-perl
- eine Instanz anlegen, z.B. define myEpoll EPOLL
- shutdown restart

(Update: kleinen Debug-Code entfernt, der per die ausgestiegen war)

KölnSolar

#13
ZitatOhne die OBIS ... Instanzen komme ich unter 1%
Ein seit Jahren bekanntes aber auch gelöstes Problem.
Setzt Du die polling-Attribute alignTime, interval, pollingMode ein ?

Grüße Markus
Edit: freezemon hätte Dir wahrscheinlich schnell Deine individuellen Performanceprobleme verraten.
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

jw2013

Danke für den Tipp, @KölnSolar!

Sämtliche eHZ Zähler der umliegenden Stadtwerke senden 1x pro Sekunde ohne Aufforderung, deswegen steht pollingMode bei allen auf "off", interval und alignTime sollten also keine Anwendung finden.

'event-min-interval' funktioniert, senkt aber die Last nicht merklich ab. Ich tippe eher darauf, dass der Parsing-Code in 47_OBIS.pm noch optimiert werden könnte.

Ich hatte vor Wochen übrigens schon einen Patch für OBIS eingestellt, aber noch nie eine Antwort erhalten:
https://forum.fhem.de/index.php?topic=135459
War das so nicht richtig?

jw2013

#15
Kleines Update für das 00_EPOLL.pm Modul: Ich habe den Code so angepasst, dass er sich im Falle von verbleibenden Daten in SSL Lese-Puffern so verhält wie das Original.

KölnSolar

ZitatSämtliche eHZ Zähler der umliegenden Stadtwerke senden 1x pro Sekunde ohne Aufforderung,
richtig
Zitatdeswegen steht pollingMode bei allen auf "off", interval und alignTime sollten also keine Anwendung finden.
falsch. Ich hab damals an der Entwicklung mitgewirkt. Mit den Attributen werden die Daten nur zum entsprechenden Zeitpunkt verarbeitet. Die Verarbeitung ist die "Bremse". Ist also nicht wirklich das, was man sonst unter polling versteht. Ich lese mit interval=60 2 "pushende" Zähler problemlos aus.
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

jw2013

Ich bekomme da einen seltsamen Effekt:
Das Attribut 'interval' kann ich im laufenden Betrieb setzen, es hat aber keine Auswirkung.
Wenn ich dann zusätzlich noch "alignTime" setzen will, bekomme ich eine Fehlermeldung, dass 'interval' nicht gesetzt wäre?!
Laut Source-Code prüft der auf $init_done. Also beide Parameter in die Config => FHEM bleibt beim Start hängen  :o

KölnSolar

pollingMode=on gesetzt ?

commandref
Zitatinterval
The polling-interval in seconds. (Only useful in Polling-Mode)
alignTime
Aligns the intervals to a given time. Each interval is repeatedly calculated. So if alignTime=00:00 and interval=600 aligns the interval to xx:00:00, xx:10:00, xx:20:00 etc....
pollingMode
Changes from direct-read to polling-mode. Useful with meters, that send a continous datastream. Reduces CPU-load.
RPi3/2 buster/stretch-SamsungAV_E/N-RFXTRX-IT-RSL-NC5462-Oregon-CUL433-GT-TMBBQ-01e-CUL868-FS20-EMGZ-1W(GPIO)-DS18B20-CO2-USBRS232-USBRS422-Betty_Boop-EchoDot-OBIS(Easymeter-Q3/EMH-KW8)-PCA301(S'duino)-Deebot(mqtt2)-zigbee2mqtt

jw2013

Funktioniert, Danke @KölnSolar ;D

Ich hatte pollingMode=off, da ich vermutete, dass das für selbsttätig sendende eHZ vorgesehen ist.
Im Grunde könnte man das interval-Attribut sogar im Modus off analog verwendbar machen. D.h. nach jedem erfolgreichen Parse sperren, also Read ins Leere laufen lassen, bis das Interval das nächste Mal auslöst.