Ankündigung

Einklappen

Sammelbestellung ETS6 Vollversionen aktiv!

Sammelbestellung für ETS6 Vollversionen (Prof., Home, Lite) mit 40% Rabatt aktiv! Infos im Forum!
Mehr anzeigen
Weniger anzeigen

Item mit Zeitberechnung bspw für Verbrauchsauswertung als Systemitems bereitstellen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Sisamiwe
    antwortet
    Hallo,

    nachdem Onkelandy die Funktionen der shtime erweitert hat und somit auch die relative Zeitpunkt-Ermittlung einfach möglich ist (wird wahrscheinlich im Release 1.8 kommen) hier mal ein Update der evals für die Ermittlung von historischen Verbrauchswerten.

    Ich habe ein struct für die Berechnung der historischen Verbrauchswerte und den passenden evals angelegt. Dabei wird auch geprüft, ob zum Abfragezeitpunkt auch Daten in der DB vorhanden sind. Nur dann werden auch die Berechnungen durchgeführt, ansonsten wird der Wert 0 gesetzt.

    struct.yaml im Ordern \etc
    Code:
    wertehistorie_total:
        # Aktualisierung erfolgt über Logik, die täglich um Mitternacht getriggert wird.
        name: Struct für Wertehistorie total
        heute:
            type: num
            visu_acl: ro
            eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.today(), 'im')) + 'i', str(shtime.time_since(shtime.today(), 'im')) + 'i')), 2)
            eval_trigger:
              - ..
            cache: yes
    
        woche:
            type: num
            visu_acl: ro
            eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i')), 2)
            eval_trigger:
              - ..
            cache: yes
    
        monat:
            type: num
            visu_acl: ro
            eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(), 'im')) + 'i') is not None else 0
            eval_trigger:
              - ..
            cache: yes
    
        jahr:
            type: num
            visu_acl: ro
            eval: round((sh...() - sh...db('max', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_year(), 'im')) + 'i') is not None else 0
            eval_trigger:
              - ..
            cache: yes
    
        gestern:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.today(), 'im')) + 'i', str(shtime.time_since(shtime.today(), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-1), 'im')) + 'i', str(shtime.time_since(shtime.today(-1), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-1), 'im')) + 'i', str(shtime.time_since(shtime.today(-1), 'im')) + 'i') is not None else 0
            enforce_updates: yes
    
        gestern_minus1:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.today(-1), 'im')) + 'i', str(shtime.time_since(shtime.today(-1), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-2), 'im')) + 'i', str(shtime.time_since(shtime.today(-2), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-2), 'im')) + 'i', str(shtime.time_since(shtime.today(-2), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
        
        gestern_minus2:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.today(-2), 'im')) + 'i', str(shtime.time_since(shtime.today(-2), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-3), 'im')) + 'i', str(shtime.time_since(shtime.today(-3), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-3), 'im')) + 'i', str(shtime.time_since(shtime.today(-3), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
            
        gestern_minus3:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.today(-3), 'im')) + 'i', str(shtime.time_since(shtime.today(-3), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-4), 'im')) + 'i', str(shtime.time_since(shtime.today(-4), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-4), 'im')) + 'i', str(shtime.time_since(shtime.today(-4), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
            
        gestern_minus4:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.today(-4), 'im')) + 'i', str(shtime.time_since(shtime.today(-4), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-5), 'im')) + 'i', str(shtime.time_since(shtime.today(-5), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-5), 'im')) + 'i', str(shtime.time_since(shtime.today(-5), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
    
        gestern_minus5:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.today(-5), 'im')) + 'i', str(shtime.time_since(shtime.today(-5), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.today(-6), 'im')) + 'i', str(shtime.time_since(shtime.today(-6), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.today(-6), 'im')) + 'i', str(shtime.time_since(shtime.today(-6), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes        
            
        vorwoche:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, - 1), 'im')) + 'i') is not None else 0
            database: init
            enforce_updates: yes
    
        vorwoche_minus1:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -1), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
            
        vorwoche_minus2:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -2), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
            
        vorwoche_minus3:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -3), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_week(shtime.calendar_week(), None, -4), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
            
        vormonat:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i') is not None else 0
            database: init
            enforce_updates: yes
            
        vormonat_minus1:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
            
        vormonat_minus2:
            type: num
            visu_acl: ro
            eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i')), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -3), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
    
        vormonat_zaehlerstand:
            type: num
            visu_acl: ro
            eval: round(sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i'), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, 0), 'im')) + 'i') is not None else 0
            database: init
            enforce_updates: yes
            
        vormonat_minus1_zaehlerstand:
            type: num
            visu_acl: ro
            eval: round(sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i'), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -1), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
        
        vormonat_minus2_zaehlerstand:
            type: num
            visu_acl: ro
            eval: round(sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i'), 2) if sh...db('max', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(None, None, -2), 'im')) + 'i') is not None else 0
            cache: yes
            enforce_updates: yes
    Im Item sieht es dann so aus:
    item.yaml:
    Code:
    heizung:
        brenner:
            name: Brennerstatus Heizung
            type: bool
            betriebsstunden_knx:
                name: Betriebsstundenzähler Brenner in Stunden
                type: num
                database: init
                struct: wertehistorie_total
    Die Aktualisierung der Items mit historischen Verbrauchswerten erfolgt über eine Logik, die per crontab jeweils um Mitternacht und kurz nach Start von shNG ausgeführt wird. Dabei werden beim ersten Start der Logik alle Items die "gestern", "vorwoche" oder "vormonat" im Pfad haben in eine persistente Variable geschrieben. Danach wird die Berechnung (Ausführen des Evals) der Items durch das Zuweisen von "1" ausgelöst, sobald die zeitlichen Bedingungen dafür erfüllt sind.
    Eine manuelle Berechnung kann durch das "manuelle" Auslösen der Logik erreicht werden.

    berechnung_wertehistorie.py
    Code:
    #!/usr/bin/env python3
    # berechnung_wertehistorie.py
    
    # Die Logik stößt die Neuberechnung der Wertehistorie gemäß struct an.
    # Alle Item werden nach gestern, vorwoche und vormonat durchsucht und entsprechende Aktionen ausgeführt
    
    logger.info("Logik 'Berechnung Wertehistorie' durch: {} und {}".format(trigger['by'], trigger['source'] ))
    
    from lib.item import Items
    items = Items.get_instance()
    
    if not hasattr(logic, 'all_historical_items_gestern'):
        logic.all_historical_items_gestern = items.match_items('*gestern*')
        logger.info("Logik 'Berechnung Wertehistorie' hat folgende Items für GESTERN gefunden: {}".format(logic.all_historical_items_gestern))
        
    if not hasattr(logic, 'all_historical_items_vorwoche'):
        logic.all_historical_items_vorwoche = items.match_items('*vorwoche*')
        logger.info("Logik 'Berechnung Wertehistorie' hat folgende Items für VORWOCHE gefunden: {}".format(logic.all_historical_items_vorwoche))
        
    if not hasattr(logic, 'all_historical_items_vormonat'):
        logic.all_historical_items_vormonat = items.match_items('*vormonat*')
        logger.info("Logik 'Berechnung Wertehistorie' hat folgende Items für VORMONAT gefunden: {}".format(logic.all_historical_items_vormonat))
        
    if trigger['by'] == 'Scheduler':
        if sh.now().hour == 0 and sh.now().minute == 0:
            logger.info("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item GESTERN durchgeführt")
            for item in logic.all_historical_items_gestern:
                item(1)
        else:
            logger.debug("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item GESTERN nicht durchgeführt")
    
        if sh.now().hour == 0 and sh.now().minute == 0 and shtime.weekday(shtime.today()) == 1:
            logger.info("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORWOCHE durchgeführt")
            for item in logic.all_historical_items_vorwoche:
                item(1)
        else:
            logger.debug("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORWOCHE nicht durchgeführt")
        
        if sh.now().hour == 0 and sh.now().minute == 0 and sh.now().day == 1:
            logger.info("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORMONAT durchgeführt")
            for item in logic.all_historical_items_vormonat:
                item(1)
        else:
            logger.debug("Logik 'Berechnung Wertehistorie' hat Aktualisierung der Item VORMONAT nicht durchgeführt")
            
    elif trigger['by'] == 'Admin':
        logger.info("Logik 'Berechnung Wertehistorie' manuell ausgelöst und Aktualisierung aller Items durchgeführt")
        for item in logic.all_historical_items_gestern:
            item(1)
        for item in logic.all_historical_items_vorwoche:
            item(1)
        for item in logic.all_historical_items_vormonat:
            item(1)
    Vielleicht kann es einer nutzen.
    Beste Grüße

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Hallo,

    Mitten in der Überarbeitung des struct kam der Jahreswechsel und damit die Erkenntnis, dass die bisherige Berechnung für den Vormonat etc nicht immer richtig war.
    Bislang habe ich den Wert für den Vormonat so ermittelt:
    Code:
    eval: round((sh...db('max', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month()), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month()), 'im')) + 'i') - sh...db('max', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month() - 1), 'im')) + 'i', str(shtime.time_since(shtime.beginning_of_month(shtime.current_month() - 1), 'im')) + 'i')), 2)
    Da nun aber der aktuelle Monat Januar und damit shtime.current_month() = 1 ist, ergibt shtime.current_month() - 1) = 0 und ist damit für die weitere Berechnung ungültig.
    Gibt es eine Möglichkeit mit Boardmitteln im eval den Vormonat zu ermitteln?

    Das Python Modul dateutil bzw. das darin enthaltene "relativedelta" kann das, nur wir kann man das im eval nutzen?
    Hat jemand eine Idee?

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    Mir ist übrigens aufgefallen, dass die Berechnung der Vormonate nicht stimmt.. Zum einen sind vormonat und vormonat_minus1 identisch, zum anderen passen die Werte einfach nicht. Die sind bei mir viel zu hoch.
    Ich mache das mittlerweile mit einem struct und der neuen implementierten shtime.

    Ich überarbeite das grad und stelle es dann hier mal wieder ein.

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Mir ist übrigens aufgefallen, dass die Berechnung der Vormonate nicht stimmt.. Zum einen sind vormonat und vormonat_minus1 identisch, zum anderen passen die Werte einfach nicht. Die sind bei mir viel zu hoch.
    https://knx-user-forum.de/forum/supp...99#post1508399

    Einen Kommentar schreiben:


  • Onkelandy
    antwortet
    Aber da das Item ein eval hat, sollte dann der errechnete Wert in die db eingetragen werden.

    Die Items brauchen ein enforce_updates: yes
    Zuletzt geändert von Onkelandy; 21.12.2020, 14:33. Grund: checked

    Einen Kommentar schreiben:


  • Msinn
    antwortet
    Wird hier nicht dem Item der Wert "1" zugewiesen?
    Ja

    Einen Kommentar schreiben:


  • Sisamiwe
    antwortet
    Zitat von Onkelandy Beitrag anzeigen
    elif sh.now().strftime("%d") == "1" and "wertehistorie.vormonat" in item.property.path: item(1)
    Hallo,

    ich muss hier nochmal nachfragen: Was genau bewirkt
    Code:
    item(1)
    Wird hier nicht dem Item der Wert "1" zugewiesen?

    Einen Kommentar schreiben:


  • kaiwerner
    antwortet
    Das habe ich schon gesehen. Cooles Feature!

    Die Größe der Datenbank.... naja...
    Datengrab.JPG


    Läuft sonst aber sehr gut.

    Wenn das Testsystem diese Woche Durchhält, werde ich mal auf v1.7.2 umsteigen!
    Tolle arbeit von euch.

    Einen Kommentar schreiben:


  • Msinn
    antwortet
    Das hängt stark von der Anzahl History Werte und der Größe der Datenbank ab. Das könntest Du mit SmartHomeNG v1.7.2 evtl. entschärfen.
    Falls Du die Detaildaten nicht mehr benötigst, z.B. weil Du sie in Summen-Items zusammengerechnet hast, kannst Du sie Löschen lassen.

    Du kannst für solche Items das neue Attribut database_maxage (Anzahl Tage) setzen. Dann werden automatisch History Werte die älter sind gelöscht.

    Bitte beachten. Wenn Du bei einem solchen Item sehr viele History Werte hast, kann das database Plugin beim 1. Start nach dem setzen des Attributes viel Zeit/Rechenleistung benötigen um die große Menge alter Daten zu löschen. Im späteren Verlauf werden die raus-alternden Daten regelmäßig gelöscht, so dass das dann von der Zeit/Rechenleistung her unauffällig ist.

    Einen Kommentar schreiben:


  • kaiwerner
    antwortet
    Ich habe mir in den Scheduler ein logging Ausgabe eingebaut, die mir sagt wie viele Aufgaben in der Queue sind, wenn diese größer der Anzahl der Worker ist.

    Code:
    2020-06-24 09:00:00 INFO lib.scheduler Needing more worker threads 8! (Queue size: 70)
    2020-06-24 09:00:00 INFO lib.scheduler Needing more worker threads 8! (Queue size: 70)
    2020-06-24 09:00:00 INFO lib.scheduler Adding worker thread. Total: 9
    2020-06-24 09:00:00 INFO lib.scheduler Adding worker thread. Total: 9
    2020-06-24 09:00:01 INFO lib.scheduler Needing more worker threads 9! (Queue size: 70)
    2020-06-24 09:00:01 INFO lib.scheduler Needing more worker threads 9! (Queue size: 70)
    2020-06-24 09:00:01 INFO lib.scheduler Needing more worker threads 9! (Queue size: 68)
    2020-06-24 09:00:01 INFO lib.scheduler Needing more worker threads 9! (Queue size: 68)
    2020-06-24 09:00:02 INFO lib.scheduler Needing more worker threads 9! (Queue size: 68)
    2020-06-24 09:00:02 INFO lib.scheduler Needing more worker threads 9! (Queue size: 68)
    2020-06-24 09:00:02 INFO lib.scheduler Needing more worker threads 9! (Queue size: 64)
    2020-06-24 09:00:02 INFO lib.scheduler Needing more worker threads 9! (Queue size: 64)
    2020-06-24 09:00:03 INFO lib.scheduler Needing more worker threads 9! (Queue size: 63)
    2020-06-24 09:00:03 INFO lib.scheduler Needing more worker threads 9! (Queue size: 63)
    2020-06-24 09:00:03 INFO lib.scheduler Needing more worker threads 9! (Queue size: 59)
    2020-06-24 09:00:03 INFO lib.scheduler Needing more worker threads 9! (Queue size: 59)
    2020-06-24 09:00:04 INFO lib.scheduler Needing more worker threads 9! (Queue size: 57)
    2020-06-24 09:00:04 INFO lib.scheduler Needing more worker threads 9! (Queue size: 57)
    2020-06-24 09:00:04 INFO lib.scheduler Needing more worker threads 9! (Queue size: 54)
    2020-06-24 09:00:04 INFO lib.scheduler Needing more worker threads 9! (Queue size: 54)
    2020-06-24 09:00:05 INFO lib.scheduler Needing more worker threads 9! (Queue size: 53)
    2020-06-24 09:00:05 INFO lib.scheduler Needing more worker threads 9! (Queue size: 53)
    2020-06-24 09:00:05 INFO lib.scheduler Needing more worker threads 9! (Queue size: 53)
    2020-06-24 09:00:05 INFO lib.scheduler Needing more worker threads 9! (Queue size: 53)
    2020-06-24 09:00:06 INFO lib.scheduler Needing more worker threads 9! (Queue size: 52)
    2020-06-24 09:00:06 INFO lib.scheduler Needing more worker threads 9! (Queue size: 52)
    2020-06-24 09:00:06 INFO lib.scheduler Needing more worker threads 9! (Queue size: 50)
    2020-06-24 09:00:06 INFO lib.scheduler Needing more worker threads 9! (Queue size: 50)
    2020-06-24 09:00:07 INFO lib.scheduler Needing more worker threads 9! (Queue size: 50)
    2020-06-24 09:00:07 INFO lib.scheduler Needing more worker threads 9! (Queue size: 50)
    2020-06-24 09:00:07 INFO lib.scheduler Needing more worker threads 9! (Queue size: 48)
    2020-06-24 09:00:07 INFO lib.scheduler Needing more worker threads 9! (Queue size: 48)
    2020-06-24 09:00:08 INFO lib.scheduler Needing more worker threads 9! (Queue size: 47)
    2020-06-24 09:00:08 INFO lib.scheduler Needing more worker threads 9! (Queue size: 47)
    2020-06-24 09:00:08 INFO lib.scheduler Needing more worker threads 9! (Queue size: 44)
    2020-06-24 09:00:08 INFO lib.scheduler Needing more worker threads 9! (Queue size: 44)
    2020-06-24 09:00:09 INFO lib.scheduler Needing more worker threads 9! (Queue size: 43)
    2020-06-24 09:00:09 INFO lib.scheduler Needing more worker threads 9! (Queue size: 43)
    2020-06-24 09:00:09 INFO lib.scheduler Needing more worker threads 9! (Queue size: 40)
    2020-06-24 09:00:09 INFO lib.scheduler Needing more worker threads 9! (Queue size: 40)
    2020-06-24 09:00:10 INFO lib.scheduler Needing more worker threads 9! (Queue size: 38)
    2020-06-24 09:00:10 INFO lib.scheduler Needing more worker threads 9! (Queue size: 38)
    2020-06-24 09:00:10 INFO lib.scheduler Needing more worker threads 9! (Queue size: 36)
    2020-06-24 09:00:10 INFO lib.scheduler Needing more worker threads 9! (Queue size: 36)
    2020-06-24 09:00:11 INFO lib.scheduler Needing more worker threads 9! (Queue size: 33)
    2020-06-24 09:00:11 INFO lib.scheduler Needing more worker threads 9! (Queue size: 33)
    2020-06-24 09:00:11 INFO lib.scheduler Needing more worker threads 9! (Queue size: 33)
    2020-06-24 09:00:11 INFO lib.scheduler Needing more worker threads 9! (Queue size: 33)
    2020-06-24 09:00:12 INFO lib.scheduler Needing more worker threads 9! (Queue size: 28)
    2020-06-24 09:00:12 INFO lib.scheduler Needing more worker threads 9! (Queue size: 28)
    2020-06-24 09:00:12 INFO lib.scheduler Needing more worker threads 9! (Queue size: 27)
    2020-06-24 09:00:12 INFO lib.scheduler Needing more worker threads 9! (Queue size: 27)
    2020-06-24 09:00:13 INFO lib.scheduler Needing more worker threads 9! (Queue size: 22)
    2020-06-24 09:00:13 INFO lib.scheduler Needing more worker threads 9! (Queue size: 22)
    2020-06-24 09:00:13 INFO lib.scheduler Needing more worker threads 9! (Queue size: 22)
    2020-06-24 09:00:13 INFO lib.scheduler Needing more worker threads 9! (Queue size: 22)
    2020-06-24 09:00:14 INFO lib.scheduler Needing more worker threads 9! (Queue size: 15)
    2020-06-24 09:00:14 INFO lib.scheduler Needing more worker threads 9! (Queue size: 15)
    2020-06-24 09:00:14 INFO lib.scheduler Needing more worker threads 9! (Queue size: 15)
    2020-06-24 09:00:14 INFO lib.scheduler Needing more worker threads 9! (Queue size: 15)
    2020-06-24 10:00:00 INFO lib.scheduler Needing more worker threads 9! (Queue size: 67)
    2020-06-24 10:00:00 INFO lib.scheduler Needing more worker threads 9! (Queue size: 67)
    2020-06-24 10:00:00 INFO lib.scheduler Adding worker thread. Total: 10
    2020-06-24 10:00:00 INFO lib.scheduler Adding worker thread. Total: 10
    2020-06-24 10:00:01 INFO lib.scheduler Needing more worker threads 10! (Queue size: 67)
    2020-06-24 10:00:01 INFO lib.scheduler Needing more worker threads 10! (Queue size: 67)
    2020-06-24 10:00:02 INFO lib.scheduler Needing more worker threads 10! (Queue size: 62)
    2020-06-24 10:00:02 INFO lib.scheduler Needing more worker threads 10! (Queue size: 62)
    2020-06-24 10:00:02 INFO lib.scheduler Needing more worker threads 10! (Queue size: 61)
    2020-06-24 10:00:02 INFO lib.scheduler Needing more worker threads 10! (Queue size: 61)
    2020-06-24 10:00:03 INFO lib.scheduler Needing more worker threads 10! (Queue size: 55)
    2020-06-24 10:00:03 INFO lib.scheduler Needing more worker threads 10! (Queue size: 55)
    2020-06-24 10:00:03 INFO lib.scheduler Needing more worker threads 10! (Queue size: 54)
    2020-06-24 10:00:03 INFO lib.scheduler Needing more worker threads 10! (Queue size: 54)
    2020-06-24 10:00:04 INFO lib.scheduler Needing more worker threads 10! (Queue size: 48)
    2020-06-24 10:00:04 INFO lib.scheduler Needing more worker threads 10! (Queue size: 48)
    2020-06-24 10:00:04 INFO lib.scheduler Needing more worker threads 10! (Queue size: 46)
    2020-06-24 10:00:04 INFO lib.scheduler Needing more worker threads 10! (Queue size: 46)
    2020-06-24 10:00:05 INFO lib.scheduler Needing more worker threads 10! (Queue size: 40)
    2020-06-24 10:00:05 INFO lib.scheduler Needing more worker threads 10! (Queue size: 40)
    2020-06-24 10:00:05 INFO lib.scheduler Needing more worker threads 10! (Queue size: 40)
    2020-06-24 10:00:05 INFO lib.scheduler Needing more worker threads 10! (Queue size: 40)
    2020-06-24 10:00:06 INFO lib.scheduler Needing more worker threads 10! (Queue size: 34)
    2020-06-24 10:00:06 INFO lib.scheduler Needing more worker threads 10! (Queue size: 34)
    2020-06-24 10:00:06 INFO lib.scheduler Needing more worker threads 10! (Queue size: 33)
    2020-06-24 10:00:06 INFO lib.scheduler Needing more worker threads 10! (Queue size: 33)
    2020-06-24 10:00:07 INFO lib.scheduler Needing more worker threads 10! (Queue size: 27)
    2020-06-24 10:00:07 INFO lib.scheduler Needing more worker threads 10! (Queue size: 27)
    2020-06-24 10:00:07 INFO lib.scheduler Needing more worker threads 10! (Queue size: 25)
    2020-06-24 10:00:07 INFO lib.scheduler Needing more worker threads 10! (Queue size: 25)
    2020-06-24 10:00:08 INFO lib.scheduler Needing more worker threads 10! (Queue size: 19)
    2020-06-24 10:00:08 INFO lib.scheduler Needing more worker threads 10! (Queue size: 19)
    2020-06-24 10:00:08 INFO lib.scheduler Needing more worker threads 10! (Queue size: 17)
    2020-06-24 10:00:08 INFO lib.scheduler Needing more worker threads 10! (Queue size: 17)
    2020-06-24 10:00:09 INFO lib.scheduler Needing more worker threads 10! (Queue size: 11)
    2020-06-24 10:00:09 INFO lib.scheduler Needing more worker threads 10! (Queue size: 11)
    Damit erklärt sich der Anstieg der Worker zum Stundenwechsel bis auf die besagten 70 Stück.

    Ich hab erstmal die restart_on_num_workers hoch gesetzt. Da werde ich wohl doch mal was umbauen müssen. Hätte nicht gedacht das die DB-Aufgaben so lange brauchen. Läuft ja bis zu 15 Sekunden.

    Danke für die Unterstützung!

    Einen Kommentar schreiben:


  • Msinn
    antwortet
    Du könntest auch noch statt eine Logik zu erstellen, mit den Item Attributen on_update bzw. oh_change arbeiten und Threads sparen.

    Du könntest ein Hilfsitem erzeugen, welches rechnet. Etwa so:

    Code:
    hilfsitem:
        contab: ...
        on_change:
          - <item1>=<eval Ausdruck>
          - <item2>=<eval Ausdruck>
          - <item3>=<eval Ausdruck>
    Damit würde nur ein Task für das hilfsitem erzeugt und per on_change würden die berechneten Werte in den ganzen anderen Items geschrieben.

    Einen Kommentar schreiben:


  • Msinn
    antwortet
    Woher soll SmartHomeNG wissen, dass bei Dir über 20 Threads gebraucht werden? Bei mir sind nach der Initialisierung nur 6 Worker-Threads aktiv und die Zahl steigt innerhalb der ersten 3-4 Tage auf das dann konstante Maxium von 11.

    Du siehst in dem Graphen auch, dass Du bei vollständiger Entzerrung der Laufzeiten nur um die 5 Worker Threads bräuchtest.

    Einen Kommentar schreiben:


  • kaiwerner
    antwortet
    Danke für die ausführliche Erklärung .

    Das Verhalten sieht im Moment halt so aus:

    Threads.JPG
    Es könnten doch die ersten 20-30 Therads erzeugt werden, wenn sie benötigt werden. Alles was da über geht wird begrenzt.

    Aber klar es läuft bei vielen auf dünnerer Hardware und
    Zitat von Msinn Beitrag anzeigen
    Weil das in smarthome.py ursprünglich mal so definiert wurde
    ist auch ein Punkt.

    Danke nochmal!

    Einen Kommentar schreiben:


  • Msinn
    antwortet
    Zitat von kaiwerner Beitrag anzeigen
    Danke für den Tipp den Wert zu überschreiben.
    Nicht überschreiben, setzen. Der Wert ist in der smarthome.yaml normalerweise nicht gesetzt. Dann wird 30 angenommen.
    Zitat von kaiwerner Beitrag anzeigen
    Wo ich aber noch auf dem Schlauch sehe ist, warum nur alle 60 Sekunden ein neuer Worker erzeugt wird wenn er nötig ist.
    Zitat von kaiwerner Beitrag anzeigen
    Wo ich aber noch auf dem Schlauch sehe ist, warum nur alle 60 Sekunden ein neuer Worker erzeugt wird wenn er nötig ist.
    Zwei Antworten:
    1. Weil das in smarthome.py ursprünglich mal so definiert wurde
    2. Damit nicht eine hohe Zahl an Tasks die Anzahl der Worker-Threads instant ins unermessliche treibt. (Das Erzeugen eines Threads ist im Verhältnis ein sehr großer Rechen-/Resoucen Aufwand) und: Threads werden nicht wieder abgebaut, weil das nochmal ein hoher Aufwand wäre, und im Zweifelsfall dann doch wieder ein neuer Thread erzeugt werden müsste.

      Wenn Du gesetzt den (übertriebenen) Fall hättest, dass zur gleichen Zeit 1.000 Scheduler Tasks starten sollen die jeweils 1 bis 2 Millisekunden rechnen, würdest Du sonst 1.000 Threads erzeugen, und das obwohl die sequenzielle Abarbeitung der nur 1 bis 2 Sekunden benötigt. So lange würde das übrigens auch dauern wenn Du 1000 Worker-Threads hättest, da Python nur einen Core der CPU nutzt. Da käme sogar noch die Rechenzeit zur Erzeugung der 1000 Threads dazu. Außerdem würdest Du dann aufgrund des GIL (Global Interpreter Lock) von Python die Abarbeitung zum erliegen bringen, wenn Du nicht eine sehr schnelle CPU hast.

    Nachtrag: Threads sollen eine quasi-Parallelisierung ermöglichen. Das macht bei sehr kurz laufenden Tasks nur sehr begrenzt sinn, da dann der Verwaltungsoverhead einen großen Teil der quasi-Parallelisierung wieder auffrisst (oder sogar überkompensiert).
    Zuletzt geändert von Msinn; 23.06.2020, 15:10. Grund: Nachtrag

    Einen Kommentar schreiben:


  • kaiwerner
    antwortet
    Danke für den Tipp den Wert zu überschreiben. Soweit habe ich wieder mal nicht gedacht. Läuft bei mir in einen VM. Da ist Luft nach oben.

    Werde mir die Sache mit einer Logik aber mal ansehen.
    Ich finde sehr übersichtlich, wenn crontab Definition an einem Item bzw. an einem Itemstruct ist. Das würde dann ja entfallen.

    Wo ich aber noch auf dem Schlauch sehe ist, warum nur alle 60 Sekunden ein neuer Worker erzeugt wird, wenn er benötig wird.
    Code:
    now = self.shtime.now()
      if self._runq.qsize() > len(self._workers):
        delta = now - self._last_worker
        if delta.seconds > self._worker_delta:
          if len(self._workers) < self._worker_max:
             self._add_worker()
    Was ist der Grund dafür? Um Spitzen auszugleichen?
    Zuletzt geändert von kaiwerner; 23.06.2020, 15:02.

    Einen Kommentar schreiben:

Lädt...
X