[2026-09-18] eagle: family/tech/t610-hw-metrics-addon.md

This commit is contained in:
Alexey Martemyanov
2026-09-18 11:08:14 +06:00
parent d658f3de00
commit c5b36eac24
+102
View File
@@ -324,6 +324,108 @@ Device — `t610`, имя сущности в первой редакции бы
--- ---
## 10a. 🔍 Разбор 2026-09-18: «free RAM упала до 380 МБ, used растёт — течёт?»
> **Вопрос Alex:** почему `free RAM != available used`, почему `free` скачкообразно упала
> уже до 380 МБ, а `used` медленно растёт. Гипотеза: «походу течёт что-то».
>
> **Ответ: течи нет.** Это **рост файлового кэша (`Cached`)** + **нормальное поведение Linux**.
> `MemAvailable` за 23 часа почти не изменился: **2 554 → 2 508 МБ (46 МБ, 1.8 %)**.
### 10a.1. Почему `free != available used` — это НЕ баг датчиков
`free` и `used` меряют **разные вещи**, они и не должны сходиться:
| Датчик | Формула | Смысл |
|---|---|---|
| `ram_free` | `MemFree` | память, не занятая **ничем вообще** (даже кэшем) |
| `ram_used` | `MemTotal MemAvailable` | реально занято приложениями (ядро **уже вычло** кэш, который можно отдать) |
| `ram_available` | `MemAvailable` | сколько **дадут**, если приложению попросить (free + отдаваемый кэш) |
Тождество: `MemTotal = MemFree + Cached + Buffers + AnonPages + Slab + …`
`MemAvailable ≈ MemFree + Cached + Buffers − несжимаемая часть`.
Проверено живой строкой лога:
```
free(392588) + cached(1925740) + swapfree(1145356) = 3 463 684
MemAvailable = 2 508 852
разница = 954 832 kB ≈ 932 МБ
```
**Разница 932 МБ — это `Active(file)` кэша, который ядро НЕ считает «легко отдаваемым».**
Значит `available used` и `free` **обязаны** расходиться на сотни МБ. Расхождение — **норма, не дефект**.
### 10a.2. Почему `free` упала ступеньками — растёт `Cached`
Часовые средние из `/share/ha-metrics/hw-2026-09.log` (23 ч аптайма):
| Час (UTC) | `Cached` МБ | `MemFree` МБ | `MemAvailable` МБ |
|---|---|---|---|
| 09-17 06 | 1 621 | 769 | 2 493 |
| 09-17 12 | 1 637 | 713 | 2 478 |
| 09-17 21 | 1 665 | 653 | 2 458 |
| **09-17 22** | **1 752 (+87)** | **554 (99)** | 2 456 |
| **09-18 04** | **1 840 (+88)** | **448 (106)** | 2 453 |
| 09-18 05 | 1 879 | 381 | 2 447 |
> 🔑 **Механизм:** `MemFree` падает **ступеньками ровно тогда**, когда растёт `Cached`.
> Числа сходятся с точностью до десятков МБ: `−87 МБ free` ↔ `+87 МБ cached` (22:00),
> `106 МБ free` ↔ `+88 МБ cached` (04:00).
> **Это не утечка — это страничный кэш.** Файловая система читает что-то новое (SQLite-БД
> 105 МБ + WAL, логи, бэкапы), ядро оставляет страницы в памяти «на всякий случай».
> **Ступеньки = моменты активного чтения файлов** (запись в БД, бэкап-джоб, дневной цикл recorder).
### 10a.3. Почему `used` медленно растёт — это тоже норма
`ram_used` (МБ): 896 → 899 → … → 957 за 23 ч. **+61 МБ за сутки ≈ 2.6 МБ/ч.**
`used = MemTotal MemAvailable`, а `MemAvailable` падает не от забивания памяти,
а от **снижения «легко отдаваемой» доли кэша**: чем больше `Active(file)` (страницы, к которым
недавно обращались), тем меньше ядро готово отдать «прямо сейчас».
> ✅ **Диагностический признак НАСТОЯЩЕЙ течи** (которого здесь **нет**):
> `MemFree + Cached` **вместе** падают, а `AnonPages`/`Slab` растут. Тогда память реально
> уходит в процесс и не возвращается.
>
> Здесь: `free + cached` = 09-17 06 → **2 390 МБ**, 09-18 05 → **2 260 МБ** (130 МБ за сутки,
> и это в пределах колебаний кэша). `MemAvailable` за те же сутки −46 МБ. **Оба почти плоские.**
### 10a.4. Замер ключевого инварианта (снято 2026-09-18 05:03 UTC, аптайм 23 ч)
```
MemTotal: 3 470 776 kB = 3.31 ГБ ✅ память на месте (не 1.44 — регрессии нет)
MemAvailable: 2 508 852 kB = 2.39 ГБ ✅ почти не изменилась за 23 ч
MemFree: 392 588 kB = 383 МБ ← «380 МБ» из вопроса Alex
Cached: 1 925 740 kB = 1.84 ГБ ← вот куда ушла память
SwapTotal/Free: 1 145 356 / 1 145 356 ✅ swap 0 % — ядро НЕ вытесняет, давление низкое
AnonPages: 795 772 kB = 777 МБ ← реально занято приложениями (не растёт)
Slab (SUnreclaim): 39 556 kB = 39 МБ ← ядро не течёт
pressure/memory: some=0.00 full=0.00 ✅ НЕТ давления на память вообще
pressure/io: some=2.55 full=2.20 ← вот это стоит смотреть: I/O-давление
```
> 🔴 **Главный вывод: признаков утечки НЕТ.**
> `Swap 0 %` + `pressure/memory = 0.00` = ядру **хватает** памяти, оно ничего не вытесняет
> и не ждёт. Настоящая утечка дала бы рост swap и ненулевой `pressure/memory`.
>
> ⚠️ **Что действительно заслуживает внимания — `pressure/io` (2.22.6 %).**
> Это давление на **ввод-вывод**, не на память. Прямо бьётся с главным кандидатом
> расследования — деградацией носителя ([[family/tech/t610-hang-investigation]] §5).
> Но 2 % — **низкое** значение, критичным считается sustained >1020 %.
### 10a.5. Что это значит для Alex
1. **Действий не требуется.** 383 МБ `MemFree` при 2.39 ГБ `MemAvailable` — здоровая картина
Linux; «свободная память» в простое почти всегда низкая, потому что излишки уходят в кэш.
2. **`ram_used` как датчик тренда — плохой выбор** (он растёт от кэша). Смотреть надо
**`ram_available`** (главный) и **`swap_used`** (должен оставаться `0`).
3. **Пропущено в текущем аддоне:** `AnonPages`, `Slab`, `Buffers`, `Active(file)` — их нет
в логе, поэтому «течёт ли реально» приходится выводить косвенно. Добавление `AnonPages`
закрыло бы вопрос утечки **прямым** замером. (`Cached` в логе есть — этого хватило.)
4. **`MemTotal` = 3.31 ГБ держится 23 ч** — регрессии к 1.44 ГБ нет. Это уже полезный факт
для расследования зависаний: ступенька не проявлялась за сутки на 3.31 ГБ.
---
## 11. Связанные ## 11. Связанные
- [[family/how-to/home-automation]] — контур автоматизации, §3.5 (ограничения `core_ssh`), §3.9 (память) - [[family/how-to/home-automation]] — контур автоматизации, §3.5 (ограничения `core_ssh`), §3.9 (память)