FHEM Forum

FHEM - Entwicklung => FHEM Development => Thema gestartet von: KölnSolar am 08 Januar 2020, 09:16:29

Titel: Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: KölnSolar am 08 Januar 2020, 09:16:29
Hallo Ihr Lieben,
ich bräuchte mal wieder etwas Nachhilfe.

Ich hab ein verwaistes Modul unter meine Fittiche genommen. Dort werden Reads auf System-Files in /sys/.... gemacht. Die Files sind Mini. Ich habe keine Ahnung wie die Files vom Kernel verwaltet werden. Der Zugriff dauert(bei mir: RPi3, produktives FHEM, pi-hole für das gesamte lokale Netzwerk, npm, alexa, python3, bumper) IMMER eine knappe Sek. Tests mit Reads von eigenen kleinen Files sind absolut unkritisch(< 1ms)

Wegen des blockierenden Verhaltens, hatte ich auf BlockingCall umgestellt, was blockingtechnisch den gewünschten Erfolg brachte. Nun lese ich immer wieder, dass das auch nicht so dolle ist wegen dem Speicherverbrauch(das ist aber ein Thema, wozu ich gleich einen weiteren Faden eröffne).

Hat jemand eine Idee warum der Zugriff so langsam sein könnte bzw. ob ich durch irgendwelche Maßnahmen etwas beschleunigen kann ?

Danke&Grüße
Markus
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: CoolTux am 08 Januar 2020, 09:21:46
/sys ist ein virtuelles Filesystem des Kernels. Es beinhaltet virtuelle Dateien welche Informationen über verschiedene Kernel-Subsysteme, Hardware und assoziierte Geräte-Treiber.
Je nach Informationsgehalt und menge der Auswahl an Dateien die Du ab fragst kann das schon mal etwas mehr sein.
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: rudolfkoenig am 08 Januar 2020, 09:44:02
Wenn ein FileDescriptor im Spiel ist, dann kann man per select pruefen, ob sysread blockieren wuerde.
Und damit das ganz normale FHEM "ReadFn-Verfahren" verwenden.
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: KölnSolar am 08 Januar 2020, 11:10:02
Danke Euch.
Ich glaube ich habe
ZitatUnd damit das ganz normale FHEM "ReadFn-Verfahren" verwenden.
verstanden. Ich weiß aber nicht, wie und wann das File einen Update erfährt. Bevor ich in einen Test Zeit verschwende, bisheriger Ablauf

open
1. read mit diamond descriptor
2. read mit diamond descriptor
close

Das  read entspricht nach meinem Verständnis dem readline. Auch ein Test mit sysread brachte keine wesentliche Beschleunigung. Die Sekunde wird immer verbraten, wenn das 1. read erfolgt. (Man "spürt" das auch, wenn man sich per WinSCP das file öffnet).
Würde sich das Problem mit einem dauerhaft per FileDescriptor geöffnetem File lösen ?(Unabhängig davon, in welchem Zyklus ReadFn aufgerufen würde).

Grüße Markus
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: yoda_gh am 08 Januar 2020, 11:21:03
Sicherheitshalber noch eine kleine Ergänzung zu der Erklärung von CoolTux: Dateien in;/sys sind ein direktes Interface in den Kernel - wenn Du die liest, wird also direkt ein Kernel-Funktion aufgerufen, deren Ausgabe Du dann siehst. Diese Funktion kann was auch immer tun, vermutlich besorgt sie in Deinem Fall direkt Informationen von der Hardware,  deswegen siehst Du Verzögerungen. Oder der zu Grunde liegende Kernel-Treiber ist schlicht kaputt....
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: rudolfkoenig am 08 Januar 2020, 11:37:30
ZitatIch glaube ich habe ... verstanden.
Ich bin nach deinen Fragen unsicher.

Ich versuche es detaillierter:

Beim erwaehnten Verfahren ist nicht das Verwenden von sysread der Knackpunkt, sondern dass sysread _nur dann_ aufgerufen werden darf, wenn der Kernel per select signalisiert, dass was zu Lesen gibt.
D.h. das Ganze wird mit select nicht schneller, nur FHEM wird nicht blockiert, weil sysread erst dann aufgerufen wird, wenn man sicher ohne Warten Daten kriegt.
In ReadFn darf man sysread auch nur ein einziges mal aufrufen (sinnvollerweise mit einem ausreichend grossen Buffer).
Wenn mehr als diese Buffer-Laenge zu Lesen gibt, dann muss man wieder auf den naechsten ReadFn Aufruf warten.

readline ist Tabu, da diese Funktion solange wiederholt sysread aufruft, bis in den Daten ein newline ist, und das hat der kernel/select nie zugesichert.
Es wird nur zugesichert, dass mindestens ein Byte ohne blockieren zu lesen ist.

Nachtrag:
Mit ReadFn meine ich sowas wie
$hash->{ReadFn}  = "MQTT2_SERVER_Read";und $hash->{FD} wird vorher in %selectlist eingetragen.
Das passiert bei MQTT2_SERVER etwas versteckt in TcpServer_Accept

Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: KölnSolar am 08 Januar 2020, 14:28:42
ZitatIch bin nach deinen Fragen unsicher.
Da mag ich Dir zustimmen.  ;D

Nun glaub ich aber noch mehr, dass ein Versuch nicht lohnt.(oder doch, ich kann dann die Updatehäufigkeit ermitteln  :) ) Denn
Zitatweil sysread erst dann aufgerufen wird, wenn man sicher ohne Warten Daten kriegt.
das ist ja nicht das Problem. Ich warte nicht bis Daten da sind, sondern der Zugriff auf /sys.... dauert einfach so lange. :'( Das file ist IMMER mit genau 3 Zeilen gefüllt. Der "Anstoß", dass neue Daten vorhanden sind, hilft also nicht. Wenn müsste über den Weg die Daten systemtechnisch woanders gepuffert sein, so dass nicht der "übliche" Leseweg stattfindet, sondern eben ein schnellerer. Dem ist aber dann ja nicht so.

Danke&Grüße
Markus

Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: rudolfkoenig am 08 Januar 2020, 14:50:10
Ich habe (vmtl. faelschlicherweise) angenommen, dass dein Hauptproblem das Blockieren von FHEM ist, dabei wollte ich mit meiner Beschreibung helfen.
Jetzt gehe ich davon aus, dass du "nur" nicht lange warten willst, bis die Daten da sind. Leider kann ich dabei nicht helfen, und sehe es genauso wie @yoda_gh
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache, Optimierung ?
Beitrag von: KölnSolar am 08 Januar 2020, 17:49:57
Zitatsehe es genauso wie @yoda_gh
Und die Nachricht hatte ich glatt übersehen.

Ihr drei habt letztendlich meine Vermutung bestätigt. Es sind tatsächlich Kernelprogramme, die die files schreiben.
Und meine Hoffnung zerstört, ich könne per Programm das Problem lösen. :'(
Nicht umsonst wird Hexenmeister bei Sysmon mit BlockingCall arbeiten.  :)
Er liest aber nicht über Perl-read, sondern per Systembefehl "cat". (Habe ich mir gerade angeguckt) Bei Aufruf in der Konsole merkt man aber, dass es zumindest keinen signifikanten Unterschied macht.  :'(

Aber eine Lösung gibt es immer.  ;D Deshalb ja mein anderer Faden, zu dem sich niemand zu antworten traut. Zu heißes Eisen ?

Grüße & Dank an Euch 3
Markus

Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: herrmannj am 08 Januar 2020, 18:49:25
Vielleicht zum strukturieren: welches Problem genau möchtest Du lösen? Der Kernel benötigt etwas Zeit die Daten zu liefern. Daran lässt sich nichts ändern.

Normalerweise fragt man den Kernel, macht mit anderen Sachen weiter bis die Antwort bereitsteht. Das abholen dauert dann nur Millisekunden.
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: KölnSolar am 08 Januar 2020, 22:08:19
Wie gesagt: Der Kernel beschreibt Dateien in /sys... und ich hole mir nur die Informationen per readline internaltimer-gesteuert ab, kein request. Da dauert aber das 1. readline(von 2) immer eine Sek. In meinem System 27-mal/min.

Da es scheinbar keine Lösung zur Beschleunigung des reads gibt, ist die seit 2 Jahren laufende Lösung, das lesen per BlockingCall aus dem Hauptprozess auszulagern. Das funktioniert perfekt und ist für das Modul die Lösung.

Fazit: Ich weiß jetzt, dass es nicht an meinen amateurhaften Perl-Kenntnissen liegt und dass die alte Lösung die richtige ist.

Wo Du einmal mitliest:
Weil ich per freezemon manchmal freezes zu dem Modul angezeigt bekomme, BlockingCall als Blackbox nutze und auch das "Speicherproblem" bei BlockingCall immer wieder angesprochen wird, hatte ich mir Gedanken gemacht, ob BlockingCall die Ursache ist und ich darauf verzichten kann. Nun bin ich noch mehr bestärkt, dass wir Mechanismen wie BlockingCall ohne Nebenwirkungen brauchen. In meinem anderen Thread von heute hab ich das ja zum Thema gemacht. Ich würde mich freuen, wenn Du dort mal rein schaust und Deine Meinung äußerst. Ich gehe da noch einen Schritt weiter. Du hast ja nicht unerheblich an meinem Nina-Modul mitgewirkt. Bisher habe ich zwar nirgendwo vernommen, dass es Laufzeitprobleme gäbe, aber die Datensammlung und die von Dir dankenswerterweise zur Verfügung gestellte Berechnungsfunktion benötigen schon ordentlich Rechenzeit. Und warum soll das im Hauptprozess sein ?

Grüße Markus
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: rudolfkoenig am 08 Januar 2020, 22:45:44
Zitat[...] das lesen per BlockingCall aus dem Hauptprozess auszulagern. Das funktioniert perfekt und ist für das Modul die Lösung.
Das ist sicher eine _moegliche_ Loesung, aber es geht auch mit weniger Ressourcenverbrauch, z.Bsp. per select.

ZitatNun bin ich noch mehr bestärkt, dass wir Mechanismen wie BlockingCall ohne Nebenwirkungen brauchen.
Das ist ein netter Wunsch, aber mW gibt es keine Loesung ohne Nebenwirkungen.

Ich kenne 4, alle nicht unproblematisch:
- select. Keine Loesung fuer CPU-Intensive Aufgaben, kann den Rest blockieren durch Bibliotheksfunktionen.
- fork (z.Bsp. BlockingCall): braucht viel Speicher, Starten und Datenaustausch zwischen den Prozessen aufwendig.
- multithreading. Erfordert eine spezielle perl Version, und ist nichts fuer unerfahrene Programmierer.
- alles was blockieren kann, kriegt das Ergebnis per Callback (z.Bsp. HttpUtils_NonblockingGet). Nachteile siehe select.


Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: Wuppi68 am 08 Januar 2020, 22:51:35
mal ne ganz andere Frage zu diesem Problem:

Was macht denn time dd if=/sys/<dein Device> of=/dev/null bs=<die Größe der Daten die normaler weise gelesen werden> count=<1|10|100|1000>
skalieren dann die Werte?

und was wie Werte werden überhaupt gelesen?
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: herrmannj am 09 Januar 2020, 16:34:13
Zitat von: KölnSolar am 08 Januar 2020, 22:08:19
Berechnungsfunktion benötigen schon ordentlich Rechenzeit. Und warum soll das im Hauptprozess sein ?
Moin Markus,

jetzt speziell zu den Zeiten, da hatte ich zumindest ansatzweise die Laufzeit gemessen und erinnere mich nicht an an grobe Auffälligkeiten. War irgendwo im dreistelligen ms Bereich und der Teil läuft ja nur sporadisch. Wenn das jetzt pro Sekunde einmal oder mehrfach anfallen würde dann würde das anders ins Gewicht fallen.

Man muss das immer abwägen. Thread oder fork hat auch "Kosten". Bei fork muss das OS eine Kopie des gesamten Prozesses erstellen, man muss die Daten in den Hauptprozess zurückholen und die Fehleranfälligkeit steigt. Siehe blockingcall und Speicher.

Für das Lesen aus /sys ist vermutlich das von Rudi vorgeschlagene Select der richtige Weg. Mach mal das was Wuppi68 sagt. Egal ob die Daten wirklich langsam kommen oder (wahrscheinlicher) der Kernel nur eine Zeit benötigt bis die Daten bereit stehen, die dann aber schnell übertragen werden - in beiden Fällen wäre Select (bei non blocking FD, und non-blocking read) das richtige. Die "Infrastruktur" (die select loop) hat fhem ganz zentral eingebaut.

Plus (Zitat Wuppi): was steht für x bei "Deinem" /sys/x ? Welche device ist es denn?

zwei Links zum ersten einlesen zu non-blocking
https://docstore.mik.ua/orelly/perl4/cook/ch07_21.htm
https://www.cs.ait.ac.th/~on/O/oreilly/perl/cookbook/ch07_14.htm
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: KölnSolar am 09 Januar 2020, 22:53:24
Zitatjetzt speziell zu den Zeiten, da hatte ich zumindest ansatzweise die Laufzeit gemessen und erinnere mich nicht an an grobe Auffälligkeiten. War irgendwo im dreistelligen ms Bereich
Genau. Du hattest getestet, als ich nur den ersten Teil implementiert hatte. Da gab es 2,3 Polygone. Später kam dwd dazu. Da ist dann die Hölle los, wenns mal in Deutschland stürmt. Polygone ohne Ende. Wie gesagt, auffällig war es bisher nicht.
Zitatund der Teil läuft ja nur sporadisch. Wenn das jetzt pro Sekunde einmal oder mehrfach anfallen würde dann würde das anders ins Gewicht fallen.
Das ist für mich die falsche Argumentation. Wenns genau im Augenblick läuft, wenn es an der Tür klingelt(Taster) und ich gerade in den Garten gehe, verpasse ich das, weil Alexa nicht rechtzeitig mit mir gesprochen hat. ;) Da hilft dann nicht die Diskussion über Eintrittswahrscheinlichkeit, sondern es gilt es von vorneherein auszuschließen(sofern machbar).
ZitatMan muss das immer abwägen. Thread oder fork hat auch "Kosten". Bei fork muss das OS eine Kopie des gesamten Prozesses erstellen, man muss die Daten in den Hauptprozess zurückholen und die Fehleranfälligkeit steigt.
Im Grundsatz ist mir das klar. Im Detail kann ich es mangels Kenntnissen nicht beurteilen. :'(
ZitatSiehe blockingcall und Speicher.
Und hier scheiden sich die Geister. WZUT "behauptet" im anderen Thread, das wäre gelöst.  ??? Und schon frage ich mich, was stimmt denn nun und was bedeutet das konkret. Was sind die do's u. dont's beim Einsatz ?
ZitatWelche device ist es denn?
/sys/devices/w1_bus_master1/4711/w1_slave
Habe ich bewusst nicht erwähnt, sonst wär ich von den GPIO4-Gegnern wieder gesteinigt worden.  :'(
Zitatzwei Links zum ersten einlesen zu non-blocking
Die werde ich mir bestimmt zu  Gemüte führen. Allerdings hoffte ich mehr darauf, dass wir bereits irgendwo etwas haben, es nur nicht genutzt wird. Ich wette BlockingCall kennt weniger als die Hälfte der Entwickler. nonblockingget auch nicht alle. Und von CoProcess u. SubProcess hatte ich bis vor ein paar Tagen auch noch nichts gehört.



Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: herrmannj am 09 Januar 2020, 23:04:39
ZitatDas ist für mich die falsche Argumentation. Wenns genau im Augenblick läuft, wenn es an der Tür klingelt(Taster) und ich gerade in den Garten gehe, verpasse ich das, weil Alexa nicht rechtzeitig mit mir gesprochen hat. ;) Da hilft dann nicht die Diskussion über Eintrittswahrscheinlichkeit, sondern es gilt es von vorneherein auszuschließen(sofern machbar).
Ja klar. Ich persönlich halte das so: bis 500ms geht klar, 1000ms wenn es nur alle Stunden mal zum tragen kommt, aber da wirds schon eng.
ZitatUnd hier scheiden sich die Geister. WZUT "behauptet" im anderen Thread, das wäre gelöst.  ??? Und schon frage ich mich, was stimmt denn nun und was bedeutet das konkret. Was sind die do's u. dont's beim Einsatz ?
Blocking Call benutzt fork. Es gibt keine simple rule. Ist halt wie immer: je komplexer die verwendete Technik ist, desto höher das Risiko das es zu Problemen kommt. Und thread und fork sind komplex.
ZitatAllerdings hoffte ich mehr darauf, dass wir bereits irgendwo etwas haben, es nur nicht genutzt wird.
Ja. Genau. die Select loop  :) ;)
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: rudolfkoenig am 10 Januar 2020, 11:09:23
Was hier noch nicht erwaehnt wurde, aber den Widerstand der "Select-Neulinge" verstaendlich macht:

Bei der select Methode muss der Programmierer, wem diese Methode neu ist, umdenken: die gewuenschte Zeile steht nicht nach dem Aufruf der readline Funktion, "in der naechsten Zele" zur Verfuegung, sondern irgendwannmal spaeter:

Blockierend:line = readline("filename");
process(line);
Mt select:
select_readline("filename", sub(line) { process(line) });
[... hier ist line nicht bekannt...]


Wenn man unterschiedliche Daten benoetigt, die blockierend besorgt werden muessen, dann wird das Ganze etwas unschoen: entweder verwendet man eine Reihe von ineinander geschachtelten Funktionen (sog. "Calback Hell"), oder die Funktion wird als Status-Maschine gebaut.
Im "ueblichen" FHEM physikalischen/IO-Modul (wie 00_CUL.pm oder 00_MQTT2_SERVER.pm) entspricht das sub von oben der $hash->{ReadFn}. Diese implementiert eine Status-Maschine: sysread fuegt die gelesenen Daten zum bisherigen $hash->{BUF} hinzu, und wenn BUF danach kein komplettes Hardware-Telegramm ergibt (z.Bsp. NL fehlt noch), dann hoert ReadFn auf, und wartet auf dem naechsten Aufruf.

Bei existierenden, blockierenden Code kann der Umbau in die "select Methode" aufwendig sein, und der Umbau zu fork oder thread einfacher.
Auf der anderen Seite verursacht die select Methode weniger Probleme als fork, und ist einfacher zu beherrschen als thread.
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: herrmannj am 10 Januar 2020, 12:05:51
ehrlich, ich glaube das fork oder thread nur oberflächlich betrachtet "einfacher" sind. Wenn man das "richtig" machen möchte dann muss man so viele Spezialfälle beachten (offene handles, zombies). _Plus_ man muss unterschiedliche OS Versionen(2), Perl Versionen und perl Module (json?)(1)(3) testen. Und am Ende kommt doch jemand (user) mit irgendeinem exotischen Symptom um die Ecke um man muss den kram aufwendig versuchen zu debuggen.

Gerade in der "Phase" des Lernens ist der fork/thread Code dann meistens von stack overflow "inspiriert". Man freut sich dass das läuft ohne exakt zu verstehen warum - und dann soll man da plötzlich noch debuggen. Schwierig

Select erfordert es (Zustimmung) _anders_ den Programm Ablauf zu denken. Aber: nach 2-3 Tagen Kopfschmerzen ;) läuft das plötzlich.

(1): es gibt einige Perl module bei denen es entscheidend ist ob die vor oder nach dem fork geladen werden. Bei einem fork wird der ganze (perl/fhem) Prozess im Speicher ge-cloned. Json war früher berüchtigt dafür, sowohl threads als auch fork, unvorhersagbare Effekte auszulösen. (2) Windows zb kann nämlich gar keinen fork. Dort wird das als thread emuliert. (3)https://stackoverflow.com/questions/46793885/perl-json-fails-if-a-thread-is-started
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: KölnSolar am 15 Januar 2020, 21:30:46
ich hab Eure Beiträge mit "allgemeinem" Inhalt in den anderen Thread kopiert.

ZitatWiderstand der "Select-Neulinge"
kein Widerstand. Probiert, getestet, keine Daten  :'(

Grund
ZitatThe kernel module starts a 12-bit temperature conversation whenever you read the w1_slave file (which is specified to take no more than 750 ms). Not sure about the polling intervals at which it searches the bus for new devices, though
(und vor ein paar Jahren hatte ich das schonmal gelesen.....nur vergessen)
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: rudolfkoenig am 16 Januar 2020, 20:18:46
Zitatkein Widerstand. Probiert, getestet, keine Daten
Das liegt aber dann an der Implementierung.
Da hier offensichtlich viel Herzblut vergossen wird: ich biete es das Modul in dieser Hinsicht zu fixen, wenn du es mir zusendest.
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: KölnSolar am 16 Januar 2020, 21:06:22
Dank Dir fürs Angebot.
ZitatDas liegt aber dann an der Implementierung.
Ich befürchte.
Zitatoffensichtlich viel Herzblut vergossen wird
Och es geht. Mir reicht schon, dass ich verstanden habe, dass das ein Sonderfall ist u. es mir das Select-Thema näher gebracht hat.
Zitatich biete es das Modul in dieser Hinsicht zu fixen
Viel lieber hätte ich Deine knappen Ressourcen verschwendet, um zu verstehen, warum trotz global dnsServer bei hohem Netzwerktraffic ein blockierendes Verhalten auftreten könnte. Einstieg hier (https://forum.fhem.de/index.php/topic,83909.msg1013803.html#msg1013803) müsste zum Verständnis der Situation reichen.
Grüße Markus
Titel: Antw:Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?
Beitrag von: rudolfkoenig am 17 Januar 2020, 13:51:19
Na gut :)