Сценарий знаком каждому: вентилятор воет (если он вообще есть), курсор подлагивает, Safari еле ворочается, а в голове крутится вопрос "почему mac тормозит". Самый частый неверный ход - открыть мониторинг, увидеть "свободно 200 МБ из 16 ГБ" и побежать докупать память. На macOS это почти всегда ложная тревога. Цифра "свободно" тут не значит ничего полезного, и сейчас ты поймёшь почему.
Этот урок - про честную диагностику нагрузки. Разберём Activity Monitor (Мониторинг системы) по столбцам, спустимся в терминал к top, ps и htop, и главное - вскроем модель памяти Mac, где "свободной мало" это норма, а не диагноз. Плюс специфика Apple Silicon: P- и E-ядра, App Nap и фоновая активность. Если ты пришёл из Linux - предупреждаю сразу: интуиция оттуда местами врёт, и я буду показывать где именно.

Память Mac: почему "свободно" - бесполезная цифра
Главная мысль урока: современная ОС не оставляет память пустой. Пустая RAM - это деньги, которые не работают. macOS (как и Linux, и Windows) заполняет свободное место кэшем файлов и страницами приложений, потому что данные в RAM достаются мгновенно, а с диска - медленно. Поэтому система памяти на Mac устроена так, что почти вся RAM всегда "занята", и это правильно.
Память делится на категории, и в Activity Monitor ты увидишь их внизу окна вкладки Память:
- Wired (зарезервированная) - страницы, которые нельзя выгрузить и нельзя сжать. Это ядро, драйверы, критичные структуры. Они обязаны лежать в RAM физически. Чем больше wired - тем меньше реально доступно остальным.
- Active (активная) - память, которую процессы используют прямо сейчас или использовали недавно.
- Inactive (неактивная) - страницы, которые приложение трогало, но сейчас не использует. Это НЕ "свободная" память в бытовом смысле, но система мгновенно заберёт её под новые нужды. По сути горячий резерв.
- Compressed (сжатая) - вот ключевая особенность Mac. Когда RAM кончается, macOS не бежит сразу в своп на диск. Она сжимает неактивные страницы прямо в RAM (обычно алгоритмом WKdm), ужимая их в 2-3 раза. Декомпрессия процессора стоит микросекунды, а чтение с диска - миллисекунды. Сжатие в сотни раз быстрее свопа.
- App Memory - суммарно то, что заняли приложения (active + неактивная анонимная память).
- Cached Files (кэш файлов) - содержимое файлов, которое система держит на всякий случай. Эта память отдаётся приложениям моментально по требованию. Именно поэтому "свободно" всегда около нуля - всё съел дисковый кэш, и это хорошо.
- Зелёный - памяти достаточно, всё ок, даже если "свободно" показывает 100 МБ.
- Жёлтый - система начала активно сжимать, ресурс на исходе.
- Красный - RAM реально не хватает, идёт своп на SSD, пора закрывать прожорливые приложения или докупать память.
Activity Monitor по вкладкам: что значат столбцыГрабли из Linux-мира: там ты привык к free -m и колонке available. На Mac аналог "available" - это не свободно, а зелёная зона давления. И своп тут вторичен - сначала компрессия, диск только в крайнем случае.
Открой Activity Monitor (Программы -> Утилиты -> Мониторинг системы, или просто Spotlight по "activity monitor"). Это штатный инструмент для mac мониторинга, и в нём пять вкладок.
CPU. Столбец "% ЦП" может быть больше 100 - это нормально: 100% это одно полное ядро, а ядер много. Восьмиядерный M-чип теоретически даёт до 800%. Колонка "Потоки" - сколько потоков у процесса. Внизу два важных числа: Система (red, время ядра) и Пользователь (синий). Если System стабильно высокий без видимой причины - чаще всего виноваты драйверы, шифрование диска или сетевой стек.
Память. Сортируй по столбцу "Память" по убыванию - сразу видно пожирателя. Колонка "Сжатая память" показывает, кто из процессов ушёл под компрессию. "Память (реальная)" в деталях процесса (двойной клик) - это RPRVT, реально занятые приватные страницы.
Энергия. Самая недооценённая вкладка для ноутбуков. Столбец "Влияние энергопотребления" - усреднённая нагрузка с учётом частоты CPU и пробуждений. Тут же "App Nap" - видно, усыплено ли приложение. И "Препятствие сну" - кто не даёт Mac заснуть.
Диск. "Прочитано байтов" / "Записано байтов" нарастающим итогом, плюс операции в секунду внизу. Полезно ловить процесс, который молотит SSD - например, indexer Spotlight (mds_stores) после большого копирования.
Сеть. Кто и сколько шлёт/принимает. Ловит фоновые синхронизации и подозрительный трафик.
Терминал: top, ps и htop без иллюзий
GUI хорош, но в SSH-сессии на удалённом Mac или в скрипте нужен терминал. Тут важно: macOS - это BSD, и top здесь не такой, как в Linux. Флаги другие.
Запусти top с сортировкой по CPU:
Код: Выделить всё
top -o cpu
Код: Выделить всё
Processes: 478 total, 2 running, 476 sleeping, 2891 threads
Load Avg: 2.14, 2.45, 2.60 CPU usage: 8.21% user, 5.40% sys, 86.38% idle
PhysMem: 15G used (2451M wired, 4123M compressor), 521M unused.
VM: 234T vsize, 4521M framework vsize, 0(0) swapins, 0(0) swapouts.
PID COMMAND %CPU TIME #TH #WQ #PORT MEM PURG CMPRS
9921 WindowServer 22.4 11:02.31 18 5 2871 612M 48M 190M
431 kernel_task 9.8 41:15.06 412 0 0 201M 0B 0B
2287 Safari 7.1 03:21.55 28 3 1204 890M 120M 340M
Полезные вызовы top:
Код: Выделить всё
top -o mem -n 10 # топ-10 по памяти
top -l 1 | head -n 12 # один снимок (logging mode) для скрипта, без интерактива
top -stats pid,command,cpu,mem,th -o cpu # выбрать столбцы
Теперь ps. На BSD синтаксис ближе к классике, но есть нюансы. Найти топ пожирателей CPU:
Код: Выделить всё
ps -Ao pid,ppid,%cpu,%mem,rss,state,comm -r | head -n 8
Код: Выделить всё
PID PPID %CPU %MEM RSS STAT COMM
9921 1 21.8 3.7 627488 R WindowServer
2287 431 6.9 5.4 912340 S Safari
431 0 4.1 1.2 205712 S kernel_task
- R - выполняется или готов к выполнению
- S - спит, ждёт события (нормальное состояние большинства)
- I - бездействует, спит дольше ~20 секунд (idle)
- U - непрерываемое ожидание, обычно ввод-вывод (если завис тут надолго - возможно проблема с диском/сетью)
- Z - зомби, процесс умер, но родитель не забрал статус
- T - остановлен (например, после Ctrl-Z или SIGSTOP)
Для интерактивного мониторинга многие ставят htop через Homebrew:
Код: Выделить всё
brew install htop
htop
Apple Silicon: P-ядра, E-ядра и куда уходит нагрузка
Чипы M-серии - асимметричные (AMP, asymmetric multiprocessing). Ядра двух типов: P-ядра (Performance) - быстрые и прожорливые, для интерактивной работы; E-ядра (Efficiency) - медленнее, но экономичные, для фона. В htop на M-чипе первые полоски обычно E-кластер, дальше P-кластер (порядок зависит от модели).
Кто решает, на каком ядре крутить поток? Не приложение. Решает планировщик macOS, опираясь на QoS (Quality of Service) - класс, который приложение присваивает своей задаче. Классы (по убыванию приоритета):
- User Interactive (QoS 33) - отрисовка интерфейса, реакция на клики. Идёт на P-ядра.
- User Initiated (QoS 25) - пользователь запросил и ждёт результат (открыть документ). Преимущественно P-ядра.
- Utility (QoS 17) - длительная работа без срочности (загрузка, индексация). P-ядра, но может перетекать на E.
- Background (QoS 9) - фон, невидимый пользователю (Time Machine, синхронизация). Идёт на E-ядра.
Управлять этим из терминала можно через taskpolicy. Например, запустить тяжёлый конвертер так, чтобы он не лез на P-ядра и не мешал:
Код: Выделить всё
taskpolicy -c background ffmpeg -i in.mov out.mp4
Код: Выделить всё
taskpolicy -b -p 2287 # -b сбрасывает процесс в фоновый приоритет (E-ядра)
App Nap, фоновая активность и поиск пожирателя
App Nap - механизм, который замораживает приложение, когда его окно не видно и оно ничего полезного не делает. Скрытый Safari с открытой, но невидимой вкладкой почти не ест CPU - его усыпили. В Activity Monitor на вкладке Энергия колонка App Nap покажет "Да". Польза огромная для батареи, но есть грабли: некоторые программы (эмуляторы, серверы, QEMU) App Nap ломает - процесс должен работать, а его подморозили. Лечится отключением через свойство приложения или специальным API, который разработчик обязан выставить.
Алгоритм поиска "кто сожрал ресурсы", когда mac тормозит:
- Открой Activity Monitor, вкладка CPU, сортировка по "% ЦП" убыванием. Кандидат номер один наверху.
- Не нашёл по CPU - смотри Память, сортировка по "Память". Возможно, давление красное и идёт своп.
- Глянь на kernel_task. Высокий kernel_task часто не баг, а фича: так система намеренно занимает CPU пустышкой, чтобы снизить температуру и не дать железу перегреться. Лечится охлаждением, а не убийством процесса (его и не убить).
- WindowServer высокий - перегружена графика: куча мониторов, прозрачности, анимаций, или приложение спамит перерисовкой.
- mds / mds_stores крутится - это индексатор Spotlight. После большого копирования это норма, через время утихнет.
Код: Выделить всё
kill 2287 # послать SIGTERM (15) - вежливая просьба завершиться
kill -9 2287 # SIGKILL - убить немедленно, без шанса на cleanup
killall Safari # прибить все процессы по имени
killall -9 "Google Chrome Helper" # имя с пробелом в кавычках
Мини-лаба: продиагностируй свой Mac за 5 минут
Повтори руками, чтобы закрепить:
- Открой Activity Monitor, вкладка Память. Запиши значения wired, compressed, cached files и цвет давления памяти. Убедись, что "свободно" близко к нулю, а график зелёный - и проникнись, что это норма.
- В терминале выполни top -l 1 | head -n 8 и найди в строке PhysMem значения compressor и swapouts. Свопов 0? Значит RAM хватает.
- Выведи топ-5 по CPU: ps -Ao pid,%cpu,%mem,state,comm -r | head -n 6. Опознай состояния в столбце state.
- Поставь htop (brew install htop), запусти и найди, какие полоски-ядра у тебя E, а какие P (E обычно менее загружены в простое и стоят первыми).
- Запусти любую долгую команду через taskpolicy -c background (например, taskpolicy -c background find / -name "*.log" 2>/dev/null) и убедись в htop, что нагрузка легла на E-ядра, а интерфейс остался отзывчивым.
- Найди в Activity Monitor на вкладке Энергия приложение с App Nap = Да.
- Почему на здоровом Mac значение "свободно" почти всегда около нуля, и на какой индикатор смотреть вместо него?
- Чем компрессия памяти (compressed) на Mac выгоднее обычного свопа на диск, и как по выводу top понять, что система реально начала свопить?
- Кто решает, на P- или E-ядро попадёт поток, и каким классом QoS это управляется? Как принудительно загнать процесс на E-ядра из терминала?
- В чём разница kill и kill -9, и почему убитый kill-ом фоновый процесс может тут же воскреснуть?
Память Mac устроена не как в Linux или Windows: вся RAM всегда занята, "свободно" - мусорная метрика, а правду говорит давление памяти (зелёный/жёлтый/красный) и компрессия вместо свопа. CPU читаем через Activity Monitor и BSD-шные top -l/-o и ps -r, помня про асимметрию Apple Silicon: P-ядра под интерактив, E-ядра под фон, а распределяет планировщик по QoS - и этим можно рулить через taskpolicy. Пожирателя ищем сортировкой по CPU и памяти, а гасим сначала вежливым kill, и только в крайнем случае kill -9, держа в уме, что службами заведует launchd. Теперь "mac тормозит" - не повод паниковать, а повод за 30 секунд найти виноватого.