Hauptmenü

FHEM Performance tunen?

Begonnen von sn0000py, 23 Dezember 2022, 07:43:38

Vorheriges Thema - Nächstes Thema

sn0000py

Hallo stelle das mal hier unter Anfängerfragen rein :)
Wie gehe ich es an FHEM zu tunen?
Welche Möglichkeiten habe ich rauszufinden wo meine Leichen in FHEM begraben sind?

Habe zwei "Probleme" Das starten von FHEM dauert richtig lange, da werkelt der schon mal 3 Minuten (ist ein Docker Image, das normalerweise in vermutlich paar sekunden da sein müsste - wenn ich es mit anderen Images wie Grafana, MariaDB, TVHeadEnd und co vergeliche)

Und während dem Betrieb sind auch immer wieder mal oft einige Delays/Hänger drinnen, merkt man dann oft, wenn ich die FHEM Seite reloade dann dauerts paar sekunden bis der reagiert.

bartman121

Also, die echten hänger, wenn das System blockiert solltest du Mal damit angehen

https://fhem.de/commandref_DE.html#freezemon

Ansonsten schau doch Mal dem Event-Monitor zu. Brauchst du wirklich alle Events die dort durchrattern?



sn0000py

Nein die Event werde ich sicher nicht alle brauchen, die werden zwar alles auf der SSD gespeichert aber vermute einfach das laufen an sich wird schon zeit brauchen oder?

Habe eben auch einige Timer die im sekunden intervall irgendwelche Sachen lesen/prüfe und dann schreiben.
Die dann teils auch weils eben schnell gehen musste auch Logs einfach so schreiben ;) - die werde ich mal eliminieren und das Freezmon mal installieren.

Gibt es auch einen Ansatz wie ich drauf kommen kann warum das starten so lange dauert? 

bartman121

ich tippe mal ins blaue ..

attr initialUsbCheck disable 1

ansonsten schau dir mal die Größe der Datei fhem.save an (in letzter Zeit werden immer wieder Schwierigkeiten bei Verwendung des MQTT2-Servers in Verbindung mit retain gemeldet

Wernieman

Auf die fhem.save hätte ich jetzt auch getippt.

Brauchst Du wirklich Trikker im Sekundentakt? Das sehe ich dann eher als "schlechtes Design". Wenn man so schnell reagieren muß, ist eine Umstellung auf Eventbasiert besser ....
- Bitte um Input für Output
- When there is a Shell, there is a Way
- Wann war Dein letztes Backup?

Wie man Fragen stellt: https://tty1.net/smart-questions_de.html

sn0000py

Zitat von: Wernieman am 23 Dezember 2022, 09:03:35
Auf die fhem.save hätte ich jetzt auch getippt.

Brauchst Du wirklich Trikker im Sekundentakt? Das sehe ich dann eher als "schlechtes Design". Wenn man so schnell reagieren muß, ist eine Umstellung auf Eventbasiert besser ....
Ja das mit dem Sekundenticker wirst schon recht haben, nur in dem einen Fall ist das halt schneller als Event basiert, da ich da auf die Daten (MQTT) vom PV wechslerichter/Akku und co schaue, um im sekunden intervall den AC Output berechne, wenn ich da auf Eventbasiert umstelle, dann habe ich da mehr Events als 1 pro Sekunde.

Auf was muss ich in der fhem.save achten? Die hat 17647 Zeilen. Wie bekomme ich da sachen raus wenn das zuviel ist?
Zb Homematic Thermostat hat da teilweise sehr viele Einträge.
Oder ein Dummy Device von mir (PV Forecast) hat auch sehr viele Einträge
UniFi Geräte sehr viele alte Einträge.

Das
attr initialUsbCheck disable 1
brauche ich nur wenn ich neue USB Geräte angehängt habe oder?
Die bestehenden USB Sache ignoriert mir das teil?

bartman121

Nein das Initialusbcheck kannst du getrost deaktivieren, das ist idR unnötig,auch wenn die Funktion sicher Mal einen Sinn hatte, aktuell hab ich noch keine Installation gesehen die das benötigt hatte. Versuch macht kluch...

Zur fhem.save ... Wie groß ist die Datei? Setzt du mqtt2-server ein?

Wie und warum zum Teufel benötigst du sekündlich den Output vom Wechselrichter? Genau durch solchen Unfug erzeugst du doch unnötig Last , die Berechnung wird dann vermutlich auch noch blockierend ablaufen, weil du das im notify machst und damit im Hauptprozess?

sn0000py

Ok das initusb ist mal raus.

die fhem.save hat eben ca 18000 zeilen und ist 1306kB groß.

MQTT2 Server verwende ich zwei einmal einen externen mosquitto server der eigenständig im docker läuft, und einem der Wechselrichter hat selber einen MQTT2 Server der seine daten schickt.

Berechnen muss ich es so schnell, weil ich im sekundentakt die Daten von der PV Speicher und Verbrauch bekomme und ich dann den ACOutput schreiben muss an den MQTT2 Server.
Leider geht da es nicht anders. Wenn ich zb will, das der Speicher nur mit 4000 Watt gladen wird, und der Rest der PV soll ins Netz gehen, dann muss ich eben sekündlich rechnen wieviel überschuss da ist (PV Produktion - Verbrauch) da dann die 4000 Watt weg und alles an Rest geht ins Netz. - das geht leider nicht anders.

Bzw im Moment entleere ich den Speicher über den Tag, da will ich auch das der Speicher nur mit 4000 Watt entleert wird, dazu eben auch die Rechnung ACOutput (ins Netz) = PV+4000 - Verbrauch

Beta-User

M.E. ein guter Thread, um sich einzulesen: https://forum.fhem.de/index.php/topic,117075.0/all.html

Zitat von: sn0000py am 23 Dezember 2022, 09:39:25
Ja das mit dem Sekundenticker wirst schon recht haben, nur in dem einen Fall ist das halt schneller als Event basiert, da ich da auf die Daten (MQTT) vom PV wechslerichter/Akku und co schaue, um im sekunden intervall den AC Output berechne, wenn ich da auf Eventbasiert umstelle, dann habe ich da mehr Events als 1 pro Sekunde.
Das ist auch ziemlich sicher eine Folge von einem Wust an nicht komplett durchdachten Event-Filtern. Es würde vermutlich reichen, passende "thresholds" bei event-on-change-reading" zu setzen. Dann noch schauen, ob das "event-loops" sind, oder Einzelevents...

ZitatAuf was muss ich in der fhem.save achten? Die hat 17647 Zeilen. Wie bekomme ich da sachen raus wenn das zuviel ist?
Zb Homematic Thermostat hat da teilweise sehr viele Einträge.
Da na, die Zahl der Zeilen ist vermutlich weniger interessant wie die Länge einzelner Zeilen. Einfach mal mit etwas kritischem Blick drübergehen. Die Thermostate sind vermutlich (!) nicht das Problem, eher (einmal mehr) die "Kommunikationsstatus im Sub-Device"-Thematik (aber an einer anderen Stelle!).

ZitatOder ein Dummy Device von mir (PV Forecast) hat auch sehr viele Einträge
Auch da kommt es eben darauf an, ob das überhaupt in der Form gebraucht wird. Aber ohne Details kann man schlecht helfen. "dummy" ist aber immer verdächtig und vermutlich (!) nicht die beste mögliche Läösung.

Zitatattr initialUsbCheck disable 1
brauche ich nur wenn ich neue USB Geräte angehängt habe oder?
Die bestehenden USB Sache ignoriert mir das teil?
Lösche (!!!!) es einfach... (völlig unnötige Diskussion)

Und du nutz offenbar NICHT (!) MQTT2_SERVER, sondern MQTT2_CLIENT! Wenn wir als Helfer Unschärfen dieser Qualtität ausfiltern müssen, ist es echt schwierig!
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

sn0000py

Ok danke für den Thread werde ich mir nun in den Feiertagen mal durchlesen

Aber nein diesen einen Timer muss ich jede Sekunde durchlaufen lassen, weil sich eben die PV und der Verbrauch oft sehr schnell ändern, und ich auf diese schnellen Änderungen auch schnell reagieren muss - eventuell wäre hier ein zweiter fhem vielleicht hilfreich für diese Regelaufgabe - oder ganz was anderes?

fhem.save
wie bekomme ich die einträge da raus?
Ich habe zb ein dummy Device, das eben einige readings hat, die ich nur zum berechnen und nachschauen brauche, sprich die daten werden nur zur Laufzeit benötigt und brauchen niemals gespeichert werden.

mqtt2-server
ja da hast recht verwende nur mqtt2-client, ich dachte die frage war ob ich generell einen mqtt2 server verwende

bartman121

Zitat von: sn0000py am 23 Dezember 2022, 10:38:36

Aber nein diesen einen Timer muss ich jede Sekunde durchlaufen lassen, weil sich eben die PV und der Verbrauch oft sehr schnell ändern, und ich auf diese schnellen Änderungen auch schnell reagieren muss - eventuell wäre hier ein zweiter fhem vielleicht hilfreich für diese Regelaufgabe - oder ganz was anderes?

Du wirst vermutlich schon wissen warum du so wehement darauf bestehst, dass du mit Sekundenwerten rechnen willst, dann mach das halt. Aber zeig doch mal deine Berechnung und vor allem das userreading und das notify, welches die Berechnung triggert. Selbst eine sekündliche Berechnung sollte einem System nicht derartig zusetzen. Ich hab da aber eine Vermutung und würde die gern prüfen....

Beta-User

Zitat von: sn0000py am 23 Dezember 2022, 10:38:36
Aber nein diesen einen Timer muss ich jede Sekunde durchlaufen lassen, weil sich eben die PV und der Verbrauch oft sehr schnell ändern, und ich auf diese schnellen Änderungen auch schnell reagieren muss
Wenn du genau nur dann reagierst, wenn sich entweder die PV-Leistung (halbwegs sgnifikant) oder der Verbrauch (halbwegs sgnifikant) ändern, muss das nicht unbedingt jede Sekunde sein. Und wenn es schneller wirklich signifikante Änderungen gibt, kann man doch auch gleich reagieren und muss nicht eine Sekunde warten.
Bin mit Wernieman einig: das ist und bleibt tendenziell schlechtes design.

Zitatfhem.save
wie bekomme ich die einträge da raus?
Ich habe zb ein dummy Device, das eben einige readings hat, die ich nur zum berechnen und nachschauen brauche, sprich die daten werden nur zur Laufzeit benötigt und brauchen niemals gespeichert werden.
Dann frage uch mich, warum man die überhaupt braucht. "Nachschauen" klingt eher danach, als würdest du deinen Codes nicht vertrauen. Aber Readings (triggernd) zu schreiben, ist m.E. nicht "best practice", sondern verschärft im Zweifel die Probleme. ($data ist bekannt?)

Zitat
mqtt2-server
ja da hast recht verwende nur mqtt2-client, ich dachte die frage war ob ich generell einen mqtt2 server verwende
Du verwendest ein MQTT2-IO, aber die Server sind "normale" MQTT-Server (das mit dem "2" ist nur eine FHEM-interne Unterscheidung zu der alten Modulgeneration, das Protokoll ist und bleibt MQTT...).

Nur meine 2ct..
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

sn0000py

Ok das mit dem $data schaue ich mir mal an, generell einem Reading zu sagen es soll nicht in fhem.save gepseichert werden und dort ignoriert werden gibt es nicht? (eine schnelle (und schmutzige) Möglichkeit das zu regeln)

der Code der zumindest im Moment sekündlich ausgeführt wird:
sub victron_recalc($$) {
    my ($device, $event) = @_;
    # Log 1, $device." ... ".$event;
    my $DCtoAC = ReadingsVal("victron", "PowerChargerA", 0)+ReadingsVal("victron", "PowerChargerB", 0);
    my $FroniusToAC = ReadingsVal("victron", "PowerPVFronius", 0);
    my $consume = ReadingsVal("victron", "PowerConsumeL1", 0)+ReadingsVal("victron", "PowerConsumeL2", 0)+ReadingsVal("victron", "PowerConsumeL3", 0);
    my $BatteryLoadMode = ReadingsVal("SolCast", "Battery.loadMode", 0);
    my $lastSetPoint = ReadingsVal("victron", "ESSAcPowerSetPoint", 0);

    my $setPoint = $lastSetPoint;

    # 110 Batterie in Warteposition fürs entleeren
    # 111 Batterie wird geladen
    # 112 Batterie wird entleert
    if ($BatteryLoadMode == 100) { $setPoint = -10; }
    elsif ($BatteryLoadMode == 99) { $setPoint = -100; }
elsif ($BatteryLoadMode == 110) {
        my $thisTime = time();
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($thisTime);
    # zwischen 8 und 13 uhr, wenn genug Leistung von der PV da ist, den Akku vollständig ins Netz entleeren
    if ( ($hour >= 8) && ($hour <= 13) && (($FroniusToAC + $DCtoAC) > 2000) && ( ($FroniusToAC + $DCtoAC - $consume) > 1000) ) {
        victron_speicher_entleeren();
# Danach wird BatteryLoadMode auf 112 gesetzt
    }
    }
elsif ($BatteryLoadMode == 111) { $setPoint = 100; }
elsif($BatteryLoadMode == 112) {
my $BatterySOC = ReadingsVal("victron", "BatterySOC", 0);
# Ausrechnen wieviel Watt noch raus müssen
    my $BatteryNeeds = ($BatterySOC-10) * 30800/100;
    my $batteryDischarge = 4000;

my $thisTime = time();
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($thisTime);
   
if ($BatterySOC < 9) {
    $batteryDischarge = 100;
$batteryDischarge = 0 if ($FroniusToAC + $DCtoAC < $consume);
}
elsif ($BatterySOC < 10) {
    $batteryDischarge = 500;
$batteryDischarge = 0 if ($FroniusToAC + $DCtoAC < $consume);
}
else {
my $hoursLeft = (14 - $hour);
$hoursLeft = 1 if ($hoursLeft < 1);
$batteryDischarge = $BatteryNeeds / $hoursLeft;
$batteryDischarge = 3000 if ($batteryDischarge < 3000);
$batteryDischarge = 4000 if ($FroniusToAC + $DCtoAC < $consume);

    }

# Log 1, "Fronius $FroniusToAC + $DCtoAC - $consume";

if ( ($hour >= 16) && (($FroniusToAC + $DCtoAC) < 1500) && ( ($FroniusToAC + $DCtoAC - $consume) < -50) ) {
# nach 16 Uhr, wenn nur mehr 1500 Watt von PV kommen, und bereits mindesten 50Watt aus dem Netz gekauft wird, kann der Akku wieder geladen werden aus dem Netz
        victron_speicher_laden();
    }
   
$setPoint = -$FroniusToAC - $DCtoAC + $consume - $batteryDischarge; # Ins Netz sollte alles vom FRonius + DC + 4kw von Batterie - verbrauch
}
    else {
        #if ($BatteryLoadMode == 1) { $DCtoAC = $DCtoAC / 2; }
        #if ($BatteryLoadMode == 2) { $DCtoAC = 0; }
       
        $setPoint = -($FroniusToAC + $DCtoAC - $consume);       
        if ($setPoint > -100) { $setPoint = -100; }
    }
# $setPoint = -($FroniusToAC + $DCtoAC - $consume);
   
$setPoint = floor($setPoint);
    if (abs($setPoint - $lastSetPoint) > 50) {
# fhem "setreading victron setESSAcPowerSetPoint $setPoint";
#Log 1, "SetPoint auf $FroniusToAC - $consume + $DCtoAC = $setPoint ($lastSetPoint) = ".(abs($setPoint - $lastSetPoint))." BatteryLoadMode $BatteryLoadMode";
        fhem "set victron ESSAcPowerSetPoint $setPoint";
    }
    # Log 1, "PowerdDC $PowerDC, Fronius : $PowerFronius, Consum : $consume";
}


und schon wieder sorry, es ist doch kein timer mit einer sekunde, aber er wird vermutlich so oft ausgeführt
[code]define victron.calc.PowerSetPoint notify victron.PowerChargerA.*|victron.PowerChargerB.*|victron.PowerPVFronius|victron.PowerConsume.* { victron_recalc($NAME, $EVENT)}
attr victron.calc.PowerSetPoint room PV
#   DEF        victron.PowerChargerA.*|victron.PowerChargerB.*|victron.PowerPVFronius|victron.PowerConsume.* { victron_recalc($NAME, $EVENT)}
#   FUUID      62285943-f33f-1e88-5677-6dd3f746a560acf0
#   FVERSION   91_notify.pm:0.258880/2022-03-27
#   NAME       victron.calc.PowerSetPoint
#   NR         353
#   NTFY_ORDER 50-victron.calc.PowerSetPoint
#   REGEXP     victron.PowerChargerA.*|victron.PowerChargerB.*|victron.PowerPVFronius|victron.PowerConsume.*
#   STATE      2022-12-23 11:48:36
#   TRIGGERTIME 1671792516.03357
#   TYPE       notify
#   READINGS:
#     2022-12-22 08:54:28   state           active
#     2022-12-23 11:48:36   triggeredByDev  victron
#     2022-12-23 11:48:36   triggeredByEvent PowerConsumeL3: 1374.0998172763811
#
setstate victron.calc.PowerSetPoint 2022-12-23 11:48:36
setstate victron.calc.PowerSetPoint 2022-12-22 08:54:28 state active
setstate victron.calc.PowerSetPoint 2022-12-23 11:48:36 triggeredByDev victron
setstate victron.calc.PowerSetPoint 2022-12-23 11:48:36 triggeredByEvent PowerConsumeL3: 1374.0998172763811

[/code]

Beta-User

Zitat von: sn0000py am 23 Dezember 2022, 11:49:22
Ok das mit dem $data schaue ich mir mal an, generell einem Reading zu sagen es soll nicht in fhem.save gepseichert werden und dort ignoriert werden gibt es nicht? (eine schnelle (und schmutzige) Möglichkeit das zu regeln)
Vielleicht kann man auf das "global:SAVE" reagieren und löschen, keine Ahnung, das ist zumindest gefühlt einfach ein übles Gewürge, mit dem ich mich nicht näher beschäftigen mag...

Zitat
der Code der zumindest im Moment sekündlich ausgeführt wird:
sub victron_recalc($$) {
    my ($device, $event) = @_;

Variablen zu übergeben, die man nicht braucht, ist lustig... vielleicht solltest du einfach mal einen Zähler einbauen und schauen, wie oft das WIRKLICH ausgeführt wird. Meine Vermutung: noch deutlich öfter als 1 Hz...

Zitat
define victron.calc.PowerSetPoint notify victron.PowerChargerA.*|victron.PowerChargerB.*|victron.PowerPVFronius|victron.PowerConsume.* { victron_recalc($NAME, $EVENT)}
attr victron.calc.PowerSetPoint room PV
#   DEF        victron.PowerChargerA.*|victron.PowerChargerB.*|victron.PowerPVFronius|victron.PowerConsume.* { victron_recalc($NAME, $EVENT)}
#   FUUID      62285943-f33f-1e88-5677-6dd3f746a560acf0
#   FVERSION   91_notify.pm:0.258880/2022-03-27
#   NAME       victron.calc.PowerSetPoint
#   NR         353
#   NTFY_ORDER 50-victron.calc.PowerSetPoint

Ahh, Weiterlesen hilft, und siehe da, NOTIFYDEF ist auch nicht gesetzt, und ab da wird es ziemlich sicher (nicht) "lustig"....
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: ZigBee2mqtt, MiLight@ESP-GW, BT@OpenMQTTGw | ZWave | SIGNALduino | MapleCUN | RHASSPY
svn: u.a Weekday-&RandomTimer, Twilight,  div. attrTemplate-files, MySensors

bartman121

juppp, sowas hatte ich erwartet ;)

mach mal an dein notify das Attribute disabledAfterTrigger mit dem Wert 1....

Ich bin mir sicher, dass dein Notify innerhalb kürzester Zeit dreimal getriggert wird ;)
Die Ergebnisse werden übrigens auch jedesmal anders sein, da du mittels readingsval verschiedene Werte zusammen sammelst, die je nach Zeitpunkt noch alt sein können ...