
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.
Spis Treści
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:
- zmienna startuje od 0,
- przy wystąpieniu zdarzenia zwiększamy ją o 1,
- okresowo odczytujemy wartość.
Tabela z prostymi przykładami:
| Język | Kod |
|---|---|
| C | int counter = 0; counter++; printf("%d\n", counter); |
| C++ | int counter = 0; counter++; std::cout << counter << std::endl; |
| Python | counter = 0counter += 1print(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ęzyk | Kod |
|---|---|
| C | int 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 */ }} |
| Python | comparisons = 0for i in range(n - 1):for j in range(n - i - 1):comparisons += 1if 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ę:
| Miara | Znaczenie |
|---|---|
| minimum | najlepszy możliwy przypadek |
| maksimum | najgorszy przypadek |
| średnia | typowe zachowanie |
| mediana | wynik odporny na skrajne wartości |
Wzór na średnią arytmetyczną:
| Wzór | Zastosowanie |
|---|---|
\(\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ór | Znaczenie |
|---|---|
\(\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ęzyk | Kod |
|---|---|
| Python | logins = {}user = "anna"if user in logins:logins[user] += 1else:logins[user] = 1print(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:
| Technologia | Kod |
|---|---|
| SQL | SELECT status, COUNT(*)FROM ordersGROUP 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ór | Znaczenie |
|---|---|
\(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


