Patch für watchdog zur NOTIFYDEV zwecks Systementlastung

Begonnen von noansi, 08 Januar 2017, 12:04:49

Vorheriges Thema - Nächstes Thema

noansi

Hallo Rudolf,

ich setzte watchdog vielfältig ein, wie vermutlich andere auch, um Aktivitäten zu überwachen etc. .

watchdog basiert auf notifies. Also wird bei einem notify jeder definierte watchdog einmal in seiner notify Funktion durchlaufen, auch wenn er die Nachricht nicht benötigt.

Bisher wird NOTIFYDEV nicht automatisch genutzt, um für watchdogs die FHEM Systemlast zu reduzieren.

Der angehängte patch erstellt in watchdog automatisch nach der Initialisierung von FHEM eine NOTIFYDEV Liste für den watchdog, was bei mir einiges bringt (schon bei der Prozessorauslastung in deutlich geringeren Lastspitzen zu sehen), insbesondere im Bezug auf Homematic, da da Antwortzeiten weiterhin eine Rolle spielen.

Es wäre schön, wenn Du den patch übernehmen könntest. Groß ist er nicht.  :)

Gruß und Danke,

Ansgar.

PS: Ich habe die Initialisierung über Timer gewählt, um nach der Definition aller devices auch prüfen zu können, ob in den REs auch gültige devices drin stehen.

betateilchen

Um NOTIFYDEV zu setzen, gibt es in fhem.pl bereits seit drei Jahren eine passende Funktion.

Zitat von: RudiDie Funktion notifyRegexpChanged prueft sowas, und berechnet aus einem Regexp NOTIFYDEV bzw. loescht sie, falls NOTIFYDEV kontraproduktiv ist. Modulautoren sollten NOTIFYDEV nur ueber diese Funktion setzen, und nie direkt. Damit ist auch eine Aenderung/Optimierung eher moeglich.
-----------------------
Formuliere die Aufgabe möglichst einfach und
setze die Lösung richtig um - dann wird es auch funktionieren.
-----------------------
Lesen gefährdet die Unwissenheit!

rudolfkoenig

ZitatGroß ist er nicht.
Mag sein, ist aber immer noch zu gross: watchdog_InitNotifyDev ist ueberfluessig. Und es waere nicht Ansgar, wenn nicht Sachen angefasst waeren (Deklaration am Anfang), die nichts mit der Aenderung zu tun haben :)

Weiterhin: falls aus einem der Regexps kein devicename extrahiert werden kann, dann wird es ignoriert. Damit wird NOTIFYDEV nur mit dem Device aus dem anderen Regexp gefuellt, und der Watchdog fuer den vernachlaessigten Regexp nie aufgerufen.

Und betateilchen hat natuerlich auch noch recht :)

noansi

Hallo Ihr beiden,

ZitatUm NOTIFYDEV zu setzen, gibt es in fhem.pl bereits seit drei Jahren eine passende Funktion.
Hmm, danke für den Hinweis, aber habe ich mit notifyRegexpChanged versucht und des ging nicht mit den REs meiner watchdogs (simple devname1|devname2|devname3 REs).

Zitat(Deklaration am Anfang), die nichts mit der Aenderung zu tun haben
Autsch, ich bin manchmal unbelehrbar. ::) Aber ich habe mich doch diesmal wirklich massiv zurückgehalten. Sogar den fhemupdate aus der Versionsinfo des frischen Abbildes habe ich in rudolfkoenig korrigiert. :)

Zitatfalls aus einem der Regexps kein devicename extrahiert werden kann, dann wird es ignoriert. Damit wird NOTIFYDEV nur mit dem Device aus dem anderen Regexp gefuellt, und der Watchdog fuer den vernachlaessigten Regexp nie aufgerufen.
Hmm, dann müßte ich also bei einem nicht erfolgreichen Check auf ein gültiges device erst mal einfach mit unmodifziertem NOTIFYDEV abbrechen. Dann würden zumindest viele einfache Fälle abgedeckt und es würde was bringen.
Oder sind mehrdeutige RegExps als devicename erlaubt?
Würde das erst mal Zustimmung finden?

Zitatwatchdog_InitNotifyDev ist ueberfluessig
Du meinst, eine Funktion würde es auch tun, richtig. So, dachte ich, waere es klarer zu verstehen.

Gruß und danke,

Ansgar.

PS: Hintergrund, ich habe ein laufendes System auf FHEM 5.7 gehoben.
In der vorherigen Version hatte ich das in der Art in watchdog eingebaut. Dann aber vergessen, das zu korrigieren und mich über die plötzliche hohe Auslatung durch FHEM gewundert. Von daher halte ich das Thema für bedenkenswert.

rudolfkoenig

ZitatSogar den fhemupdate aus der Versionsinfo des frischen Abbildes habe ich in rudolfkoenig korrigiert.
Dafuer hat Markus schon ein Ticket bei trac geoeffnet: https://trac.edgewall.org/ticket/12655

ZitatOder sind mehrdeutige RegExps als devicename erlaubt?
Ja, aber. Da ich es schwer in Worte fassen kann: schau dir createNtfyHash und notifyRegexpChanged in fhem.pl an. Letzteres sollte aus der DefineFn aufgerufen werden, Ersteres wird danach "automatisch" ausgefuehrt. Direktes Setzen von NOTIFYDEV kommt nicht in Frage, notfalls muss _ich_ notifyRegexpChanged angepassen :), bitte Problemfall beschreiben.

noansi

Hallo Rudolf,

mein Gedanke war:

  my $res = $watchdog->{RE1}.'|'.$watchdog->{RE2};
  Log3 $name, 1, "Try watchdog_BuildNotifyDev $name with $res";
  notifyRegexpChanged($watchdog, $res);


in watchdog_BuildNotifyDev auszuführen. Ich muss ja für beide REs die passende NOTFYDEV Liste erzeugen.

Mein RE1 und damit auch RE2 sieht einfach so aus: CUL_WS_1|SCC_WS_1

Damit wird  notifyRegexpChanged($watchdog, $res); mit $res = "CUL_WS_1|SCC_WS_1|CUL_WS_1|SCC_WS_1" aufgerufen.

Aber ein NOTIFYDEV wird so in den devicer Internals nicht erzeugt.
Und die Matches in notifyRegexpChanged erzeugen bei mir derzeit nur viele Fragezeichen.

Daher habe ich das erst mal verworfen. Oder kannst Du mir sagen, mit welchem Trick ich das doch hinbekomme?

Gruß, Ansgar.

noansi

Hallo Rudolf,

hier mal eine andere Variante, wie vorhin angedeutet:

sub
watchdog_BuildNotifyDev($)
{
  my ($dm) = @_;
  my (undef, $name) = split(':', $dm, 2);

  if (!$init_done){
    InternalTimer(gettimeofday() + 0.001,"watchdog_BuildNotifyDev", "watchdog_BuildNotifyDev:".$name, 0); #noansi: wait until FHEM is operational
    return;
  }

  my $watchdog = $defs{$name};

  my $newNotifyDev = "";

  my $res = $watchdog->{RE1}.'|'.$watchdog->{RE2};
  my @cond = split(/\|/, $res);
  foreach my $c (@cond) {
    my @d =  split(/\:/, $c);
    if ( defined($defs{$d[0]}) ) { # only if such a device is really defined
      if ( !(   ($newNotifyDev =~ m/^($d[0])$/) # and not allready in NOTIFYDEV
             || ($newNotifyDev =~ m/^($d[0]),/)
             || ($newNotifyDev =~ m/,($d[0]),/)
             || ($newNotifyDev =~ m/,($d[0])$/)
            )
         ) {
        $newNotifyDev .= ',' if($newNotifyDev ne "");
        $newNotifyDev .= $d[0];
      }
    }
    else {
      return; # no chance by now, as it is not simply a name, but a complicated RE "basename.*", "(basename1.*|basename2.*)" ...
    }
  }

  return if( $newNotifyDev eq "" ); # normally this should not happen

  notifyRegexpChanged($watchdog, ""); # force rebuild works also this way?
#  %ntfyHash = (); # force rebuild
  $watchdog->{NOTIFYDEV} = $newNotifyDev; # and set the new list
}


das erzeugt mir die NOTIFYDEV Liste für einfache REs. Für .* REs wird keine Liste erzeugt. Schon das Einklammern eines Namens läßt die Funktion abbrechen. Damit passiert also nicht Schlimmes bei komplexeren REs.
Fällt Dir ein Gegenbeispiel ein, das da durch flutscht.

Gruß, Ansgar.

rudolfkoenig

Ich denke vermutlich zu einfach, aber folgendes:
--- 91_watchdog.pm    (revision 12986)
+++ 91_watchdog.pm    (working copy)
@@ -69,6 +69,11 @@

   }

+  InternalTimer(1, sub($){
+    my $re = ($re1 eq "." ? "" : $re1)."|".($re2 eq "SAME" ? $re1 : $re2);
+    notifyRegexpChanged($watchdog, $re);
+  }, $watchdog, 0);
+
   return undef;
}

baut fuer
define CUL_WS_1 dummy
define SCC_WS_1 dummy
define wd watchdog CUL_WS_1|SCC_WS_1 00:00:10 CUL_WS_1|SCC_WS_1 { Log 1, "Hallo" }

ein funktionierendes NOTIFYDEV.
Das habe ich jetzt auch eingecheckt.

Zitatdie plötzliche hohe Auslatung durch FHEM
Wieviele watchdogs hast du denn?
Ich hatte gerade einen Patienten mit 600 HM Definitionen + 650 notifies.
Da kann man dann endlich messbar optimieren. :)

noansi

Hallo Rudolf, hallo betateilchen,

Zitatschau dir createNtfyHash und notifyRegexpChanged in fhem.pl an.
ja, Tomaten (oder Matches) auf den Augen bei Anschauen ...  :o
    if(@list && @list <= 5 && int(@list) == int(@list2)) {
Die 5 hat meinen Ansatz mit notifyRegexpChanged aufgehalten.

sub
watchdog_BuildNotifyDev($)
{
  my ($dm) = @_;
  my (undef, $name) = split(':', $dm, 2);

  if (!$init_done){
    InternalTimer(gettimeofday() + 0.001,"watchdog_AS_BuildNotifyDev", "watchdog_AS_BuildNotifyDev:".$name, 0); #noansi: wait until FHEM is operational
    return;
  }

  my $watchdog = $defs{$name};

  my $res = $watchdog->{RE1};
  $res .= '|'.$watchdog->{RE2} if ($watchdog->{RE1} ne $watchdog->{RE2});
  Log3 $name, 1, "Try watchdog_BuildNotifyDev $name with $res";
  notifyRegexpChanged($watchdog, $res);
}


Wie wäre der Vorschlag? notifyRegexpChanged muss den Gültigkeitscheck, wie bisher, richtig machen, dann ist es gut.

Die 5 in fhem.pl würde ich ja gerne noch erhöhen. 10? Oder als weitere Parameter an notifyRegexpChanged mit zu übergeben, wenn's doch mal mehr werden soll, weil die Notifyfunktion aufwändiger ist? Wenn undef, dann halt rückwärtskompatibel 5?
Ich verstehe schon, das Zusammenbauen des %ntfyHash soll nicht so lange dauern, gegen einen geringer werdenden Nutzen.

Andereseits ist so ein Hash Lookup recht fix, gegenüber dem Aufruf einer Notify Funktion, die dann auch noch mehrere davon macht oder mehrere Matches auf die gleichen hashes sozusagen. Wenn's beim Start länger dauert, dafür im Betrieb dann nicht mehr so sehr stört, dann ist das zu verschmerzen, denke ich.

Gruß, Ansgar.

noansi

Hallo Rudolf,

ZitatDas habe ich jetzt auch eingecheckt.
jetzt sind wir doch schon nah beieinander. Super! :)

Die Anzahl erlaubter Namen in NOTIFYDEV wäre dann noch meine offene Frage. Was hältst Du von dem Parameter Vorschlag?

ZitatIch hatte gerade einen Patienten mit 600 HM Definitionen
Server started with 690 defined entities
Die Anzahl der watchdogs ist nicht so hoch, sind aber recht viele.

Der RasPi, auf dem es läuft und laufen soll, ist aber auch keine Rakete.

Gruß und Danke, Ansgar.

rudolfkoenig

ZitatDie 5 in fhem.pl würde ich ja gerne noch erhöhen. 10?
Ist seit der Optimierung fuer den besagten Patienten auf 10. Wenn ich sinnvolle Anwendungen mit mehr Regexps sehe, bin ich auch bereit es zu erhoehen. Der Regexp-Pruefer wurde dabei auch geaendert.

noansi


noansi

Hallo Rudolf,

hier noch ein Änderungsvorschlag zu Deiner Änderung zu watchdog_Define:

  InternalTimer(1, sub($){
    my $re = ($re1 eq "." ? "" : $re1).($re2 eq "SAME" || $re2 eq $re1 ? "" : "|".$re2);
    notifyRegexpChanged($watchdog, $re);
  }, $watchdog, 0);


Warum gleiches zweimal auswerten?
Und um die 10 besser auszunutzen.  ;)

Gruß, Ansgar.

rudolfkoenig


noansi