Pomysły na optymalizację HA, czyli przyspieszamy na maxa

Dziś chciałbym zainicjować na Forum sekcję poświęconą optymalizacji konfiguracji HA i niektórych jego najpopularniejszych dodatków, której jedynym celem jest przyspieszenie pracy automatyzacji, mimimalizacja lagów zarówno po stronie backendu (compute) jak i sekcji odpowiedzialnych za prezentację wyników i komunikację z użytkownikiem (UI).

Mam w tej materii swoje przemyślenia, wiele prób za sobą (w tym kilka nie do końca udanych), więc może to być ciekawa lektura dla tych z Was, którzy mają podobne problemy. Zachęcam także do prezentacji własnych pomysłów i ich skutków w tym obszarze..


Jeszcze do niedawna mój HA stał na zwykłym NUC (Intel Core 5i, 8GB, SDD 420GB), zainstalowany jako bare metal. Uznałem bowiem, że każda inna instalacja (na Proxmox, czy pod jakimkolwiek innym supervisorem) to czysta strata mocy maszynki i dodatkowo problemy z update’ami… Taką instalację można traktować wyłącznie jako środowisko testowe, gdzie wszelkie nasze programistyczne niepowodzenia, straty na wydajności sprzętu, czy wręcz utrata jakichś danych nie będą frustrowały i zniechęcały do dalszych infromatycznych peregrynacji..

Zatem bare metal na typowym, technologicznie leciwym sprzęcie był dla mnie opcją docelową.
W międzyczasie minęły już ponad 4 lata, HA szybko się rozwinął, przybyły nowe potrzeby i możliwości, a z nimi cała masa nowych integracji i rozwiązań. Obciążający moją instancję HA jest tu także fakt, że wszystkie swoje automatyzacje robię (z wrodzonego lenistwa) w Node-RED, który jest niestety dość pazerny na zasoby sprzętowe w porównaniu z natywnym edytorem automatyzacji HA, choć sam w sobie jest nieprawdopodobnie wygodnym, skutecznym i miłym w użyciu narzędziem.
Stąd od pewnego czasu obserwowałem postępującą degradację instalacji, coraz większe lagi w backendzie i coraz bardzej widoczną niewyróbę bazy danych.

Postanowiłem coś z tym zrobić i… dziś chciałem podrzucić Wam kilka swoich wdrożonych i chyba udanych pomysłów.

1. W serwerze podwoiłem RAM do 16GB.

Dzięki temu mogłem zmigrować swoją bazę do MariaDB w wersji in_memory, co spowodowało dramatyczne przyspieszenie pracy serwera.
In‑Memory MariaDB to jedna z tych zmian, które nie wyglądają spektakularnie na papierze , ale w praktyce potrafią odmienić Home Assistanta tak samo, jak przejście z HDD na SSD albo z 4 GB na 16 GB RAM. To jest po prostu inna liga działania recorder’a . Przy takim wypasie RAMu kluczowy parametr tmpfs mogłem ustawić aż na 4g, więc cała moja baza danych natychmiast znalazła się w pamięci RAM. Co to dało?

  • zapis i odczyt historii jest natychmiastowy,
  • iowait spada praktycznie do zera,
  • dysk przestaje być wąskim gardłem,
  • HA działa szybciej i płynniej,
  • UI nie laguje przy otwieraniu historii,
  • automatyzacje reagują szybciej,
  • dysk żyje dłużej (mniej zapisów).

To jest jak turbo‑doładowanie dla Home Assistanta.
Dodatkowo, podniesienie RAM do 16GB spowodowało bak potrzeby korzystania z dramatycznego spowalniacza, jakim jest swap, i którego nie sposób wyłączyć.

Zauważyłem więc ogromny wzrost prędkości recordera. Recorder to najbardziej obciążająca część HA, bo:

  • zapisuje każdy stan każdej encji,
  • generuje statystyki,
  • aktualizuje wykresy,
  • obsługuje historię.

Na HDD — dramat.
Na SSD to działa OK.
W RAM — po prostu Ferrari.

Efekt: historia otwiera się 5–10× szybciej.

In‑Memory MariaDB zapisuje wszystko w RAM, a dysku dotyka tylko przy backupie lub restarcie.
Efekt: dysk jest praktycznie bezczynny.

Gdy recorder nie blokuje dysku, to:

  • UI się nie przycina,
  • interfejs UI renderuje się szybciej,
  • historia nie zamraża interfejsu,
  • automatyzacje reagują natychmiast.

To wszystko prowadzi do znacznego wzrostu responsywności automatyzacji.
Automatyzacje - zależne od historii - (np. „jeśli sensor nie zmienił stanu od 10 minut”) działają szybciej, bo:

  • zapytania SQL są natychmiastowe,
  • nie ma opóźnień w odczycie stanu,
  • HA nie czeka na dysk (iowait = 0).

Zatem wnioski są następujące:
In‑Memory MariaDB usuwa największe wąskie gardło Home Assistanta — zapis i odczyt historii — przenosząc go do RAM, dzięki czemu HA działa szybciej, sprawniej, płynniej i stabilniej, a dysk przestaje być obciążony. A brak swapowania pamięci to już w ogóle najsłodsza wisienka na moim torcie.

2. Posprzątałem Node-RED

Ze wszystkich swoich flowów (pierwotnie flows.json zajmował 7MB) pousuwałem dokładnie wszystkie inne msg.* oprócz msg.payload’ów, pod które podstawiam jedynie entity_state i paru innych msg.* kluczowych dla wykonania określonej ścieżki automatyzacji. Dokładnie wszystkie typy zmiennych na wyjściach z nodów zamieniłem na string, co wymusiło jedynie drobne poprawki edytorskie na niektórych nodach odczytujących te wartości. Nie mam już ani jednego msg typu event, data, topic, itp. śmieci.
Po takim zabiegu nowy plik flows.json zajął… niecałe 4MB. Takie odchudzenie kodu o prawie 50% spowodowało, że automatyzacje Node-RED wykonują się w mgnieniu oka (przynajmniej takie mam wrażenie).

Okazało się, że odchudzenie kodu w Node‑RED ze zbędnych msg.* to jedna z tych optymalizacji, które wyglądają niepozornie, a w praktyce potrafią drastycznie zmniejszyć zużycie CPU, RAM i liczbę operacji wykonywanych przez każdy flow. To jest dokładnie ten typ „mikro‑poprawek”, które w środowisku z dużą liczbą integracji, Zigbee2MQTT, Whisperem, NGINX proxy, VSCode, automatyzacjami i intensywnym ruchem zdarzeń — robią ogromną różnicę. Trzeba bowiem pamiętać, że każdy msg to obiekt, który:

  • jest kopiowany między node’ami,
  • jest serializowany i deserializowany,
  • jest przetwarzany przez każdy nod po drodze,
  • może być logowany,
  • może być zapisywany do HA.

Jeśli msg zawiera tylko to, co potrzebne, to Node‑RED wykonuje minimalną pracę.

To tyle na dziś z mojego podwórka…


Napiszcie proszę, jakie są Wasze doświadczenia i osiągnięcia w zakresie optymalizacji procesów lub samego środowiska HA. Bo przecież na pewno są także inne metody i pomysły godne uwagi wszystkich..

2 Likes

Podstawowe pytanie czy dziś w dobie AI jest sens trzymać w kontenerze Node-Red? Claude z Google Gemini przepisują flow-y na automatyzacje HA a także tworzą nowe na podstawie opisu bez najmniejszego problemu. Do tego poproszone uzupełniają je o ładny opis jak one działają dzięki czemu można liznąć trochę wiedzy o kodowaniu. Ja już nawet nie patrzę w graficzny konfigurator automatyzacji.

To nie fair, bo piszesz o płatnej opcji. Tymczasem u mnie wszystko jest za darmochę…

Mówisz chyba o jakiś prostych automatyzacjach NR, chciałbym zobaczyć jak to gemini przepisuje kod jakiegoś Noda.

Mój sposób na wydajną instalację:

  • HP T620 z 12GB RAM, a na nim Proxmox z HA i 2 inne VM (6GB dla HA)
  • brak zbędnych (dla mnie) rzeczy, wliczając w to Node-RED, AI, card_mod, …
  • staram używać tylko to, czego działanie rozumiem i utrzymywać porządek; 90% UI to custom button, w którym lubię rzeźbić rzeczy

Efekt: zero problemów z czymkolwiek, dashboardy ładują się natychmiast, od razu w ostatecznej formie (nic nie skacze ani nie “morfuje”). Nie czepiam się card_mod - to świetny, dopracowany projekt, ale zupełnie nie dla mnie, “skaczące” UI działa mi na nerwy :slight_smile:

Tak u mnie wygląda obciążenie pracującego systemu:

Nie wiem co masz na myśli pod pojęciem prosta automatyzacja. Moje najdłuższe mają po kilkaset linijek kodu. I Gemini z Claude napisało je bez problemu. A jak pytam co by jeszcze zmieniło usprawniło to ma całkiem fajne pomysły. Mało tego potrafi uzupełniać skomplikowane customowe karty. Dla mnie laika w kodowaniu to petarda.

Wszystko za darmo. korzystam z agentów które są z firefoxem. Jak jednemu coś nie idzie to zmieniam na inny. Jeszcze nie było flow na którym by poległy.

Możesz dołączyć jakiś przykład jak było przed i po ? nie to, żebym się nie zgadał ale zależy jak i co zrobiłeś.
Sucha informacja to żadna porada. Chyba, że chciałeś się tylko pochwalić :wink:

Niestety, nie mam już archiwum z 2025, więc nie mam źródła, z którym mógłbym porównać dzisiejszy efekt. Odkąd zrobiłem te porządki (było to w czasie ostatnich Świąt), wywaliłem w kosmos stare, ubiegłoroczne archiwa, zeby było z Nowym Rokiem Nowym Krokiem.

Przeczytałeś post ze zrozumieniem? Opisałem w nim szczegółowo co i jak zrobiłem.

Chwalić?? Niby czym? Opisałem tu swój pomysł do wykorzystania. To NIE jest poradnik.
Po takich słowach zaczynam się zastanawiać, czy w ogóle warto dzielić się nimi tutaj, czy lepiej wszystko zachować dla siebie…

@Krzysztonek
Odnośnie rozwiązania 1. jest jedna kluczowa kwestia - to rozwiązanie wymaga używania UPSa i zamykania systemu w krytycznym stanie zasilania (dla mnie nierozwiązaną kwestią pozostaje ponowne uruchomienie HA - wymaga to odpornego na zaniki zasilania jakiegoś innego systemu, który może monitorować pracę UPSa, by wykryć taki poziom naładowania akumulatora który pozwoli na ponowne bezpieczne włączenie maszyny z HA).

Natomiast w kwestii szybkości obsługi bazy danych w RAM to nie mam żadnych uwag, zawsze w danym momencie historii RAMdyski są wielokrotnie szybsze od dostępnych pamięci masowych.

W ogóle odnośnie HAOS-generic w zasadzie zawsze jest dobrze dołożyć (licząc średnio “długookresowo”, czyli w sumie zaglądając w wielomiesięczne statystyki…) jakieś 100% RAMu więcej niż realnie używamy (wynika to z przyjętej polityki swapowania i taki nadmiar RAM powoduje, że swap istnieje, ale nie jest używany), oczywiście to też zależy od zapotrzebowania na RAM w piku (co po wielu latach używania HAOS na rozsądnie dobieranych konfiguracjach dopiero wczoraj otwarło mi oczy jakie mogą być skutki kompilacji w ESPHome zbyt niezoptymalizowanego projektu na “niewypasionym” sprzęcie - mam tu na myśli framework arduino i projekt z zależnościami “od wszystkiego” - kwestia jest rozwojowa, bo skorzystałem sobie z instalacji znajomego i nie było tam żadnych sensorów diagnostycznych, bym mógł zrozumieć co się stało, że kompilacja nie chciała się skończyć, więc dopiero czas pokaże co się dzieje w jego instalacji).

To samo dotyczy HAOS-ova - nie można zanadto oszczędzać na przydziałach dla VM z HAOS (2 rdzenie to za mało na rozbudowaną instalację, co do RAM to jak w generic).

Posiadacze SBC (jak maliny, Tinkerboard, Odroid i paru innych wspieranych) są na z góry przegranej pozycji pod tym względem… brak możliwości rozbudowy RAMu to strzał w kolano (można wprawdzie oszczędzać RAM, ale to jest działanie intensywnie ograniczające wydajność), więc jeśli na dzień dobry nie kupili sobie mocno nadmiarowych konstrukcji, to któregoś dnia będą musieli zmienić sprzęt.


Odnośnie punktu 2. nic nie powiem, bo nie używam NR… więc mam o nim zerowe pojęcie.


@maciej1 Sam musiałem się pozbyć card-mod (czego nie żałuję jakoś bardzo) bo istnieją customowe karty z nim na tyle niekompatybilne, że są problemy z działaniem lovelace…

Swoją drogą im bardziej instalacja odbiega od “standardowej” tym więcej jest roboty z jej utrzymaniem technicznym (więc sens systemu automatyki w którym MUSIMY tracić więcej czasu, niż go oszczędzamy na tym co jego stosowanie generuje, jest dość wątpliwy; i tu pomijam, że to może być hobby, czy używanie HA generuje jakąś wyższą wygodę niż dom zupełnie bez automatyki i integrowania istniejących rozwiązań).

Niby zawsze warto się chwalić, ale prawda jest taka, że bez twardych danych zwykle takie chwalenie nic nikomu z czytelników nie daje, zawsze potrzeba jakiegoś czynnika edukacyjnego, bez tego publikacja może tracić sens…
(akurat tutaj czynnik edukacyjny jest, ale na takim poziomie, że skorzystają z tego co najwyżej zaawansowani użytkownicy)

Niestety jedynie zwyczaj chomikowania umożliwia dzielenie się danymi porównawczymi (najstarszy backup mam gdzieś z połowy roku 2022 gdy zautomatyzowałem w końcu ich tworzenie automatyczne, to w sumie dzięki temu, że mogłem sobie na to pozwolić mając tez mocno nadmiarową pojemność nośnika, którą dobrałem na podstawie wcześniejszych statystyk ilości zapisów, a tymczasem wtedy już na tyle zoptymalizowano HA, że przestał być niszczycielem nośników półprzewodnikowych).


A tak ogólnie odnośnie optymalizacji to kiedyś ograniczałem ilość encji zapisywanych w bazie, w końcu z tego całkowicie zrezygnowałem, bo po pierwsze zoptymalizowano HA w bardzo poważnym stopniu (i nie ukrywajmy zmiany w HA wymuszały też zbędną dodatkową robotę…); a po drugie to zapis czegoś, co może służyć za dane diagnostyczne jest ważniejszy niż zysk na mniejszej bazie danych.

1 Like

@Krzysztonek pytałem o szczegóły ponieważ w NR msg. to jest obiekt i z noda do noda przekazywany jest wskaźnik - czyli stała ilość bajtów. Chciałem więc zrozumieć gdzie te oszczędności. Nie ma się co obrażać… bo słaby nie zrozumie a dobry będzie miał wątpliwości. To, że plik jest mniejszy to nie znaczy wprost, że szybszy.
Dobra… nie będę dyskutował✋️

Oto domyślny node event w NR:


Jak widać, poza oczywistą wiadomością msg.payload, tworzą się jeszcze:

  • msg.data
  • msg.topic

Jeśli następujące po nim nody nie potrzebują niczego poza zawartością payload, to wszystkie pozostałe msg można (i należy) bezkarnie usunąć, żeby nie musiały się przetwarzać. Na tym polega oszczędność.

A to, że flows.json się znacząco zmniejszył dowodzi tylko ogromu śmieci zalegających (i przez to zbędnie przetwarzanych) dotychczas na moich przepływach.
Wcześniej nie zwracałem na nie uwagi, budując z zapałem coraz to nowe automatyzacje. Dopiero po zrobieniu tych porządków zdałem sobie sprawę, jak bardzo niehigienicznie do tej pory postępowałem i jak nieodpowiedzianie i rozrzutnie gospodarowałem zasobami serwera.

3 Likes

Warto dopowiedzieć, że ważnym problemem jest również właściwe ustawienie zapisu logów.

Przy instalacjach docker:
Docker przechwytuje wszystko, co kontener wysyła na konsolę, i zapisuje to w pliku tekstowym (zazwyczaj w formacie JSON) na dysku.
Lokalizacja zazwyczaj jest w /var/lib/docker/containers/[ID_KONTENERA]/[ID]-json.log.

Domyślnie Docker nie limituje wielkości tych plików. Jeśli Twój proces generuje dużo błędów lub komunikatów debug, plik ten może urosnąć do wielu gigabajtów, co zapcha dysk.

Możesz sprawdzić, ile miejsca zajmują logi Twojego kontenera, wpisując komendę:
docker ps -a --format '{{.ID}}' | xargs -I{} docker inspect {} --format '{{.LogPath}}' | xargs du -sh
Jeśli chcesz, aby wszystkie kontenery miały limit logów, możesz edytować (lub stworzyć) plik /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

Jeśli tylko dla konkretnego dockera to w pliku docker-compose.yml dodaj:

  node-red:
    image: nodered/node-red
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"


W konfiguracji HAOS jest inaczej i występują dwa główne strumienie logów:

  • Logi silnika Node-RED: Te, które widzisz w zakładce “Logi” wewnątrz dodatku Node-RED.
  • Logi kontenera (Docker logs): Przechwytywane przez Supervisora i składowane w systemie plików HAOS.

Supervisor sam rotuje logi.
Warto mieć log_level na warn w konfiguracji dodatku.

Największym obciążeniem dla logów i dysku w NR są zazwyczaj dwa błędy w projektowaniu przepływów:

  • Pętle: Gdy jeden nod wysyła dane do drugiego, a ten z powrotem do pierwszego – generuje to tysiące linii logów w kilka sekund.
  • Debug nody: Pozostawienie włączonych nodów typu “debug” ustawionych na “complete msg object” lub “system console”.

Wskazówka: Zawsze sprawdzaj, czy nody Debug mają zaznaczoną opcję “debug window” (tylko w przeglądarce), a nie “system console” (zapis do logów na dysku).

Pierwszy efekt zapchania dysku - to losowe kontenery przestają działać - Niekoniecznie sprawca.

Z tego prawdopodobnie wynika opinia, że NR to “zło wcielone” :wink:

Później dopisze jak to zrobić w proxmox (muszę najpierw sprawdzić).
c.d.

Node-Red w LXC

N początek (od końca) efekt działań

root@node-red:~# du -h --max-depth=1 /var/log
1.0K /var/log/runit
30K /var/log/apt
422M /var/log/journal
512 /var/log/private
422M /var/log
root@node-red:~# nano /etc/systemd/journald.conf
root@node-red:~# nano /etc/systemd/journald.conf
root@node-red:~# systemctl restart systemd-journald
root@node-red:~# journalctl --disk-usage
Archived and active journals take up 97.7M in the file system.
root@node-red:~# du -h --max-depth=1 /var/log
1.0K /var/log/runit
30K /var/log/apt
98M /var/log/journal
512 /var/log/private
98M /var/log

Ograniczyło rozmiar logów z 422M (rósł do zapchania dysku) ``do 98M

root@node-red:~# nano /etc/systemd/journald.conf

ustaw porametry i zapisz

[Journal]
Storage=persistent
Compress=yes
SystemMaxUse=100M
SystemMaxFileSize=20M
RuntimeMaxUse=50M
MaxFileSec=1week
systemctl restart systemd-journald

W tej chwili masz ustawione ograniczenia logów całego systemu LXC.

Teraz trzeba ograniczyć liczbę logów produkowanych przez NR

nano ~/.node-red/settings.js

zmień sekcję

// Configure the logging output
  logging: {
    // Only console logging is currently supported
    console: {
      // Level of logging to be recorded. Options are:
      // fatal, error, warn, info, debug, trace
      level: "warn", 
      
      // Whether or not to include metric events in the log output
      metrics: false,
      // Whether or not to include audit events in the log output
      audit: false,
    },
  },

restart.

Myślę, że to się przyda również w innych przypadkach.

Wprowadziłem równie zmiany w MariaBD proponowane przez @Krzysztonek ale przy moim 32G RAM i 12CPU, na przeglądarce przyspieszenia nie widać
(ograniczenia samej przeglądarki).
Na pewno dysk odpocznie i dłużej pożyje.
Po audiofilsku to “Radykalne poszerzenie sceny” :grin:

4 Likes

Sprawę obsługi zdarzenia zaniku zasilania rozwiązałem w następujący sposób:

Skoro mój serwer HA stoi na lapciu, to ochoczo wykorzystuję sensor wskazujący poziom jego baterii sensor.home_assistant_server_battery_charge wystawiony do HA z integracji Glances.

  1. Mając dostępną tę kluczową informację uruchamiam automatyzację polecenia shutdown w warunkach spadku poziomu baterii poniżej 85% przez czas minimum 2 minut (aby uniknąć stanów false positive):
alias: Awaryjny Shutdown serwera HA
description: Awaryjny Shutdown serwera HA
triggers:
  - trigger: numeric_state
    entity_id:
      - sensor.home_assistant_server_battery_charge
    for:
      hours: 0
      minutes: 2
      seconds: 0
    below: 85
conditions: []
actions:
  - data:
      title: Awaria zasilania serwera HA
      message: |-
        Bateria serwera < 85% — zamykam serwer HA.
         Sprawdź jego zasilanie i uruchom ponownie.
    action: notify.mobile_app_krzysztonek_telefon
  - action: shell_command.shutdown_server
mode: single

Wykorzystuję przy tym fakt, że sensor.home_assistant_server_battery_charge pokazuje wartość 100 zawsze, gdy laptop zasilany jest z sieci nawet wtedy, gdy faktyczny poziom baterii jest dowolnie poniżej tej wartości. Zatem nawet, gdy po powrocie zasilania jego bateria dopiero zacznie się z powrotem ładować (i nie osiąga jeszcze progu 85%), ponownie unikam stanu false positive.

  1. Polecenie shutdown_server mam zdefiniowane w pliku configuration.yaml w sposób następujący:
shell_command:
  shutdown_server: 'ssh -i /config/ssh/id_rsa -o StrictHostKeyChecking=no <user@HA_server_IP> "sudo /sbin/shutdown -h now"'

Wykonane próby powiodły się, serwer zamyka się łagodnie i podnosi równie gładko. Zatem rozwiązanie działa, czyli cel osiągnięty.

  1. Co do sposobu ponownego załączania serwera po shutdownie, to:
  • wykorzystuję funkcję BIOS’a: Wake_on_Power, która automatycznie wybudza serwer z chwilą powrotu zasilania sieciowego,
  • brak tej funkcji w BIOS’ie można zrekompensować ręcznym (niestety) odpaleniem magicznego pakietu Wake_on_LAN wprost ze smartfona np. przy pomocy stosownej apki. Mozna to zrobić zarówno z własnej sieci LAN jak i z internetu (dzięki DDNS). Ale wtedy trudno mówić o pełnej automatyzacji tego procesu, bo przecież każdy kierowca wie, że …manual to nie automat. :wink:

Gdybyś Concorde’a zatankował nawet eterem, to i tak nie poleciałbyś szybciej :smiley:
Fizyka też ma swoje granice…

Bardzo ładna karta :slight_smile:
Pokazałbyś jej kod i templatki sensorów?

U mnie wygląda to tak:

2 Likes

Dla użytkowników Proxmoxa, dbających o “higienę” LXC, istnieje gotowe rozwiązanie.

Skrypt, który w sposób zautomatyzowany robi to co opisałeś dla wszystkich LXC jednocześnie.

1 Like

Zaglądałem do skryptu

      find /var/log -type f -delete 2>/dev/null
      find /tmp -mindepth 1 -delete 2>/dev/null

Jest tak jak mówisz - sprząta i tylko LXC.
Na podstawie niego można zrobić sobie własne skrypty dla innych sposobów instalacji.
W tym co opisałem jest drobna różnica - tych logów produkuje się mniej, rotują się i zawsze jest “kilka” ostatnich.
Tak naprawdę mało kto z nich korzysta :wink:

Według mnie pierwsze co po sprzątaniu SQL to usuwanie niepotrzebnych record i zmienienie w Node Red kodu pod względem pobierania danych polecam rest api jeśli się mylę to mnie poprawcie.