Dauer Read eines files 1 Sek.; Ursache[geklärt], Optimierung[unmöglich] ?

Begonnen von KölnSolar, 08 Januar 2020, 09:16:29

Vorheriges Thema - Nächstes Thema

KölnSolar

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
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

CoolTux

/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.
Du musst nicht wissen wie es geht! Du musst nur wissen wo es steht, wie es geht.
Support me to buy new test hardware for development: https://www.paypal.com/paypalme/MOldenburg
My FHEM Git: https://git.cooltux.net/FHEM/
Das TuxNet Wiki:
https://www.cooltux.net

rudolfkoenig

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.

KölnSolar

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
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

yoda_gh

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....

rudolfkoenig

#5
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


KölnSolar

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

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

rudolfkoenig

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

KölnSolar

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

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

herrmannj

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.

KölnSolar

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
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

rudolfkoenig

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.



Wuppi68

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?
Jetzt auf nem I3 und primär Homematic - kein Support für cfg Editierer

Support heißt nicht wenn die Frau zu Ihrem Mann sagt: Geh mal bitte zum Frauenarzt, ich habe Bauchschmerzen

herrmannj

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

KölnSolar

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.



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