Liczniki i statystyki
Kodowanie,  Poradnik

Liczniki i statystyki

Systemy informatyczne bardzo rzadko działają wyłącznie na danych „tu i teraz”. W praktyce trzeba wiedzieć, ile razy coś się wydarzyło, jak często występuje błąd, ilu użytkowników wykonało operację, ile zapytań obsłużył serwer albo ile elementów przeszło przez algorytm sortowania. Bez takich informacji trudno diagnozować problemy, planować wydajność i oceniać poprawność działania programu. Właśnie dlatego tak duże znaczenie mają Liczniki i statystyki.

Liczniki i statystyki jako podstawowy mechanizm obserwacji działania programu i systemu

Licznik to najprostsza struktura przechowująca informację o liczbie wystąpień zdarzenia. Może zliczać wejścia do funkcji, liczbę błędów, liczbę operacji zapisu, odczytu albo wykonanych iteracji pętli.

Statystyka jest pojęciem szerszym. Oprócz samego zliczania obejmuje analizę danych: średnie, minimum, maksimum, medianę, odchylenie standardowe, rozkład wartości czy trendy w czasie.

W praktyce licznik odpowiada na pytanie „ile razy”, a statystyka odpowiada również na pytania:

  • kiedy najczęściej występuje problem,
  • jaka jest typowa wartość,
  • czy wynik odbiega od normy,
  • czy system działa stabilnie.

Przykład prosty:

jeżeli serwer HTTP obsłużył 12 000 żądań w godzinę, to licznik mówi tylko o tej liczbie. Statystyka może dodatkowo pokazać:

  • średni czas odpowiedzi: 120 ms,
  • najwolniejsze zapytanie: 4300 ms,
  • 95 percentyl: 280 ms,
  • liczba błędów 500: 37.

To już pozwala podejmować decyzje techniczne.

Najprostszy licznik inkrementowany przy każdym zdarzeniu

Najczęstszy model wygląda tak:

  1. zmienna startuje od 0,
  2. przy wystąpieniu zdarzenia zwiększamy ją o 1,
  3. okresowo odczytujemy wartość.

Tabela z prostymi przykładami:

JęzykKod
Cint counter = 0; counter++; printf("%d\n", counter);
C++int counter = 0; counter++; std::cout << counter << std::endl;
Pythoncounter = 0
counter += 1
print(counter)

To wygląda banalnie, ale dokładnie na tej zasadzie działają także bardziej rozbudowane systemy monitoringu.

Liczniki monotoniczne i resetowane okresowo

W praktyce spotyka się dwa typy liczników.

Monotoniczny – tylko rośnie.
Przykład: całkowita liczba zapytań od uruchomienia usługi.

Okresowy – resetowany po czasie.
Przykład: liczba błędów w ostatniej godzinie.

To rozróżnienie ma znaczenie przy analizie wydajności. Licznik monotoniczny dobrze nadaje się do monitoringu długoterminowego, ale do szybkiego wykrywania awarii często lepszy jest licznik w oknie czasowym.

Liczniki i statystyki w algorytmach pozwalające mierzyć złożoność zamiast zgadywać

Na zajęciach z algorytmiki często mówi się o złożoności obliczeniowej O(n), O(n log n), O(n²). Problem zaczyna się wtedy, gdy student zna teorię, ale nie widzi jej w praktyce.

Najprostsza metoda to dodanie liczników operacji.

Zamiast zakładać, że algorytm „powinien być szybki”, można policzyć:

  • liczbę porównań,
  • liczbę zamian elementów,
  • liczbę wywołań rekurencyjnych,
  • liczbę alokacji pamięci.

To daje realny obraz działania programu.

Przykład licznika porównań w sortowaniu bąbelkowym

Sortowanie bąbelkowe jest dobrym przykładem, bo wykonuje bardzo dużo porównań.

JęzykKod
Cint comparisons = 0;
for(int i=0;i<n-1;i++)
for(int j=0;j<n-i-1;j++){
comparisons++;
if(arr[j] > arr[j+1]){ /* zamiana */ }
}
Pythoncomparisons = 0
for i in range(n - 1):
for j in range(n - i - 1):
comparisons += 1
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]

Dla n = 100 liczba porównań może dojść do 4950.

To już nie jest abstrakcja z podręcznika, tylko konkretna liczba.

Średnia, minimum i maksimum jako realna ocena działania

Jedno uruchomienie programu nie daje wiarygodnego obrazu. System operacyjny, pamięć podręczna procesora i obciążenie komputera wpływają na wynik.

Dlatego mierzy się wiele prób.

Najczęściej zapisuje się:

MiaraZnaczenie
minimumnajlepszy możliwy przypadek
maksimumnajgorszy przypadek
średniatypowe zachowanie
medianawynik odporny na skrajne wartości

Wzór na średnią arytmetyczną:

WzórZastosowanie
\(\overline{x} = \frac{x_1 + x_2 + ... + x_n}{n}\)średni czas wykonania programu

Jeżeli czasy wykonania wynoszą 10 ms, 12 ms, 11 ms, 200 ms, to sama średnia może wprowadzać w błąd. Mediana pokaże znacznie lepiej typowe zachowanie programu.

Odchylenie standardowe i stabilność systemu

Dwa systemy mogą mieć tę samą średnią, ale działać zupełnie inaczej.

System A:

100 ms, 102 ms, 98 ms

System B:

20 ms, 250 ms, 30 ms

Średnia może być podobna, ale drugi system jest niestabilny.

Wzór:

WzórZnaczenie
\(\sigma = \sqrt{\frac{\sum (x_i - \overline{x})^2}{n}}\)odchylenie standardowe

Im większe odchylenie, tym mniej przewidywalne działanie.

W systemach produkcyjnych stabilność często jest ważniejsza niż sama szybkość.

Liczniki i statystyki w bazach danych, aplikacjach webowych i monitoringu produkcyjnym

Na produkcji problemy kosztują czas i pieniądze. Jeżeli sklep internetowy przez godzinę nie zapisuje zamówień, strata jest realna. Właśnie dlatego liczenie zdarzeń nie jest dodatkiem, tylko podstawą utrzymania systemu.

Najczęściej monitoruje się:

  • liczbę zapytań SQL,
  • liczbę błędów HTTP 500,
  • liczbę timeoutów,
  • liczbę logowań,
  • liczbę nieudanych prób autoryzacji,
  • czas odpowiedzi API,
  • wykorzystanie pamięci RAM,
  • użycie CPU.

Prosty licznik logowań użytkowników

Przykład w Pythonie:

JęzykKod
Pythonlogins = {}
user = "anna"
if user in logins:
logins[user] += 1
else:
logins[user] = 1
print(logins)

To już jest statystyka per użytkownik, a nie pojedyncza zmienna.

Takie rozwiązanie później rozwija się do systemów raportowych i analitycznych.

SQL i grupowanie danych

Bardzo duża część statystyk wykonywana jest bezpośrednio w bazie danych.

Przykład:

TechnologiaKod
SQLSELECT status, COUNT(*)
FROM orders
GROUP BY status;

To pozwala policzyć liczbę zamówień w każdym statusie:

  • nowe,
  • opłacone,
  • wysłane,
  • anulowane.

Zamiast ręcznie analizować tysiące rekordów, baza robi to natychmiast.

Współczynnik błędów jako ważniejsza informacja niż sama liczba błędów

100 błędów brzmi źle, ale bez kontekstu nic nie znaczy.

Jeżeli system obsłużył:

  • 1000 żądań → 100 błędów to katastrofa,
  • 10 000 000 żądań → 100 błędów to bardzo dobry wynik.

Dlatego stosuje się wskaźniki procentowe.

WzórZnaczenie
\(error\ rate = \frac{liczba\ błędów}{liczba\ wszystkich\ żądań} \times 100\%\)procent błędnych operacji

Przykład:

37 błędów / 12 000 żądań = 0,308%

To już daje sensowną informację operacyjną.

Najczęstsze błędy przy projektowaniu liczników i analizie danych

Pierwszy błąd to zliczanie wszystkiego bez celu.

Jeżeli system zapisuje 300 różnych metryk, ale nikt ich nie analizuje, powstaje tylko szum informacyjny.

Drugi błąd to brak kontekstu czasowego.

Liczba 500 błędów bez informacji „na godzinę”, „na dobę” albo „od początku działania” jest mało użyteczna.

Trzeci błąd to brak synchronizacji w programach współbieżnych.

W aplikacjach wielowątkowych zwykłe counter++ może prowadzić do błędnych wyników. Potrzebne są operacje atomowe albo mechanizmy synchronizacji.

Przykład problemu:

dwa wątki jednocześnie zwiększają wartość 100 do 101, a wynik końcowy nadal wynosi 101 zamiast 102.

Czwarty błąd to analizowanie samej średniej.

Średnia bez mediany, maksimum i percentyli bardzo często ukrywa problem.

Piąty błąd to brak retencji danych.

Jeżeli logi i metryki są usuwane po 24 godzinach, analiza awarii z poprzedniego tygodnia staje się niemożliwa.

Krótkie uwagi praktyczne z pracy z systemami produkcyjnymi

Najbardziej użyteczne liczniki zwykle są bardzo proste:

  • liczba błędów,
  • liczba retry,
  • liczba timeoutów,
  • liczba restartów procesu.

To one najczęściej wskazują realny problem.

Warto też od początku ustalić jednostki:

  • ms zamiast sekund,
  • bajty zamiast „dużo pamięci”,
  • procent zamiast ogólnego opisu.

Bez spójnych jednostek porównywanie wyników staje się chaosem.

Dobrą praktyką jest także rozdzielenie metryk technicznych i biznesowych.

Techniczne:

  • CPU,
  • RAM,
  • latency,
  • błędy HTTP.

Biznesowe:

  • zamówienia,
  • płatności,
  • rejestracje,
  • porzucone koszyki.

Dopiero połączenie obu grup pokazuje pełny obraz systemu.

FAQ

Czy prosty licznik w zmiennej zawsze wystarcza?

Nie. W małych programach tak, ale w systemach wielowątkowych lub rozproszonych potrzebne są operacje atomowe, bazy danych albo systemy monitoringu takie jak Prometheus czy Grafana.

Dlaczego sama średnia czasu wykonania jest niewystarczająca?

Bo pojedyncze bardzo wolne przypadki mogą być ukryte przez dobre wyniki większości operacji. Dlatego analizuje się także medianę, maksimum i percentyle.

Czy warto liczyć operacje w algorytmach, skoro istnieje notacja O()

Tak, bo notacja asymptotyczna opisuje trend, a licznik pokazuje realne zachowanie dla konkretnych danych wejściowych. Obie rzeczy się uzupełniają.

Kiedy licznik powinien być resetowany?

To zależy od celu. Do analizy historycznej lepszy jest licznik monotoniczny. Do szybkiego wykrywania awarii lepiej sprawdza się okno czasowe, na przykład ostatnie 15 minut.

Czy statystyki w bazie danych obciążają system?

Tak, jeśli są źle zaprojektowane. Częste ciężkie zapytania agregujące na dużych tabelach mogą spowalniać produkcję. Dlatego stosuje się indeksy, tabele pomocnicze i przetwarzanie okresowe.

Licznik sam w sobie jest prosty, ale jego znaczenie rośnie razem ze skalą systemu. W małym programie pomaga zrozumieć działanie algorytmu, a w dużej aplikacji potrafi uratować godziny pracy i bardzo konkretne pieniądze. Dobrze zaprojektowana obserwowalność zwykle zaczyna się właśnie od kilku poprawnie policzonych wartości.

Źródło Foto: Freepik

Dodaj komentarz