(Не) очевидные особенности настроек TCP сокетов. Часть 2.
Начало тут.
Есть мнение, что механизмы autotuning TCP в Linux не просто так придумали и в норме стоит пользоваться именно ими, а хардкод стоит избегать.
Потому разберемся с настройкой
Перефразирую:
- дефолтное значение
- максимальное значение
Делаем промежуточные вывод, что:
1.
2.
Проверим!
Начнем с конца:
Действительно, максимальный
Теперь проверим, что
Размер буфера выставляется равным дефолтному
——
Особо пытливым для перепроверки можно обратиться к исходникам:
2. либо в определении начального TCP окна:
что все таки не бьется с документацией.
Выходит обманывают нас разработчики или я так интерпретирую тексты :)
Окончательные выводы:
1.
2.
В итоге решение задачи может быть следующим:
tags: #tcp #linux #kernel
Начало тут.
Есть мнение, что механизмы autotuning TCP в Linux не просто так придумали и в норме стоит пользоваться именно ими, а хардкод стоит избегать.
Потому разберемся с настройкой
net.ipv4.tcp_rmem и узнаем оказывает ли на него влияние net.core.rmem_max:# man 7 tcp
...
tcp_rmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These parameters are used by TCP to regulate receive buffer sizes. ...
min minimum size of the receive buffer used by each TCP socket. The default value is the system page size. (On Linux 2.4, the default value is 4 kB, lowered to PAGE_SIZE bytes in low-memory systems.)...
default the default size of the receive buffer for a TCP socket. This value overwrites the initial default buffer size from the generic global net.core.rmem_default defined for all protocols...
max the maximum size of the receive buffer used by each TCP socket. This value does not override the global net.core.rmem_max. This is not used to limit the size of the receive buffer declared using SO_RCVBUF on a socket...
Перефразирую:
- дефолтное значение
tcp_rmem перезаписывает net.core.rmem_default — это мы заметили в самом начале, до использования rcvbuf;- максимальное значение
tcp_rmem НЕ перезаписывает net.core.rmem_max и НЕ используется при выставлении SO_RCVBUF.Делаем промежуточные вывод, что:
1.
net.core.rmem_max задает жесткий лимит на размер TCP буфера;2.
tcp_rmem не участвует в игре при выставлении SO_RCVBUF.Проверим!
Начнем с конца:
# sysctl -a | grep rmem
net.core.rmem_default = 212992
net.core.rmem_max = 6291456
net.ipv4.tcp_rmem = 4096 131072 18874368
### Выставляем максимальное значение tcp_rmem ниже rmem_max
# sysctl net.ipv4.tcp_rmem="4096 131072 851968"
net.ipv4.tcp_rmem = 4096 131072 851968
# grep listen /etc/nginx/nginx.conf
listen 80 rcvbuf=6291456;
# systemctl restart nginx
# ss -ntlmO | grep '0.0.0.0:80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* skmem:(r0,rb12582912,t0,tb16384,f0,w0,o0,bl0,d0)
Действительно, максимальный
tcp_rmem не сыграл.Теперь проверим, что
net.core.rmem_max задает жесткий лимит над размером TCP сокетов:# sysctl -a | grep rmem
net.core.rmem_default = 212992
net.core.rmem_max = 6291456
net.ipv4.tcp_rmem = 4096 131072 851968
### Делаем net.core.rmem_max ниже чем дефолтный tcp_rmem, значение которого поднимем
# sysctl net.core.rmem_max=212992
net.core.rmem_max = 212992
# sysctl net.ipv4.tcp_rmem="4096 524288 851968"
net.ipv4.tcp_rmem = 4096 524288 851968
### Убираем директиву rcvbuf
# grep listen /etc/nginx/nginx.conf
listen 80;
# systemctl restart nginx
# ss -ntlmO | grep '0.0.0.0:80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* skmem:(r0,rb524288,t0,tb16384,f0,w0,o0,bl0,d0)
Размер буфера выставляется равным дефолтному
tcp_rmem (кстати без удвоений), который больше net.core.rmem_max. ——
Особо пытливым для перепроверки можно обратиться к исходникам:
1. net.core.rmem_max участвует либо в обработке опции SO_RCVBUF:...
case SO_RCVBUF:
...
__sock_set_rcvbuf(sk, min_t(u32, val, READ_ONCE(sysctl_rmem_max)));
2. либо в определении начального TCP окна:
...
space = max_t(u32, space, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2]));
space = max_t(u32, space, READ_ONCE(sysctl_rmem_max));
space = min_t(u32, space, *window_clamp);
*rcv_wscale = clamp_t(int, ilog2(space) - 15,
0, TCP_MAX_WSCALE);
что все таки не бьется с документацией.
Выходит обманывают нас разработчики или я так интерпретирую тексты :)
Окончательные выводы:
1.
net.core.rmem_max играет только при ручном выставлении размеров сокетов (SO_RCVBUF);2.
net.ipv4.tcp_rmem напротив, не участвует в SO_RCVBUF, зато позволяет использовать автоподстройку, что в большинстве случаев будет более гибким решением.В итоге решение задачи может быть следующим:
# sysctl net.ipv4.tcp_rmem="4096 1048576 12582912"
tags: #tcp #linux #kernel
Telegram
Performance matters!
(Не) очевидные особенности настроек TCP сокетов. Часть 1.
Задача: затюнить размеры сокетов у Nginx, чтобы без потерь переживать всплески трафика.
Уточним размер буфера чтения:
# ss -ntlmO | grep ':80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*…
Задача: затюнить размеры сокетов у Nginx, чтобы без потерь переживать всплески трафика.
Уточним размер буфера чтения:
# ss -ntlmO | grep ':80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*…
👍23
В главе When to Stop Analysis книги Systems Performance обсуждается, как определить момент, когда дальнейший анализ проблемы становится неэффективным из-за низкого соотношения затрат к выгоде (ROI).
Аппетит приходит во время игры, ага:)
Автор предлагает три критерия, когда стоит остановиться:
1. Если найденное решение покрывает основную часть проблемы (66+ % от деградации);
2. Если затраты на анализ превышают потенциальную выгоду (отрицательный ROI);
3. Если есть другие задачи с более высоким ROI.
На мой взгляд, удобнее смотреть на схему по другому — перевернуть с ног на голову и сверяться с ней на каждом шаге:
1. Выбираем наиболее приоритетную проблему — хорошо когда можем сделать количественную оценку (деньги, время);
2. Погружаемся в суть и ищем решение, которое закроет хотя бы 66% проблемы;
3. GOTO 1 — проводим переоценку: точно ли оставшиеся 34 % всё ещё важнее других задач?
Звучит просто, но сколько раз я залипал на часы, разбирая то, что к делу почти не относится — подсчёту не поддаётся:)
P.S. есть мнение, что подход будет работать далеко за пределами траблшутинга и IT.
Автор предлагает три критерия, когда стоит остановиться:
1. Если найденное решение покрывает основную часть проблемы (66+ % от деградации);
2. Если затраты на анализ превышают потенциальную выгоду (отрицательный ROI);
3. Если есть другие задачи с более высоким ROI.
На мой взгляд, удобнее смотреть на схему по другому — перевернуть с ног на голову и сверяться с ней на каждом шаге:
1. Выбираем наиболее приоритетную проблему — хорошо когда можем сделать количественную оценку (деньги, время);
2. Погружаемся в суть и ищем решение, которое закроет хотя бы 66% проблемы;
3. GOTO 1 — проводим переоценку: точно ли оставшиеся 34 % всё ещё важнее других задач?
Звучит просто, но сколько раз я залипал на часы, разбирая то, что к делу почти не относится — подсчёту не поддаётся:)
P.S. есть мнение, что подход будет работать далеко за пределами траблшутинга и IT.
Brendangregg
Systems Performance: Enterprise and the Cloud, 2nd Edition
Systems Performance: Enterprise and the Cloud, 2nd Edition (2020)
👍21
В нашей инфраструктуре мы давно используем PSI (Pressure Stall Information) для выявления перенасыщения (saturation) ресурсов: CPU, диск, память.
Есть мнение, что saturation — ключевой показатель, по которому легко понять состояние системы. Вокруг него построена методология USE Method.
PSI призван заменить Load Average, который не позволяет быстро и точно определять состояние системы.
Изначально PSI собирал данные per host — полезно, но шумно в контейнерных средах с множеством cgroup.
В Cgroup v2 появилась поддержка PSI для отдельных cgroup, а скоро cadvisor добавит сбор PSI по каждому контейнеру — вот тогда заживем!
P.S. Если будет запрос, могу в будущих заметках углубиться в детали. Дайте знать! 😊
tags: #cpu #k8s #metrics
Есть мнение, что saturation — ключевой показатель, по которому легко понять состояние системы. Вокруг него построена методология USE Method.
PSI призван заменить Load Average, который не позволяет быстро и точно определять состояние системы.
Изначально PSI собирал данные per host — полезно, но шумно в контейнерных средах с множеством cgroup.
В Cgroup v2 появилась поддержка PSI для отдельных cgroup, а скоро cadvisor добавит сбор PSI по каждому контейнеру — вот тогда заживем!
P.S. Если будет запрос, могу в будущих заметках углубиться в детали. Дайте знать! 😊
tags: #cpu #k8s #metrics
Brendangregg
The USE Method
👍61
Разовью тезис об ограниченности LA из предыдущего поста:
Load Average (средняя нагрузка) — обобщённая метрика, включающая в себя показатели совершенно разных подсистем (CPU и I/O). Это значит, что она не годится на роль интерпретатора проблем: «посмотрел и понял, где проблема».
Вторая особенность LA.
Метрика складывается (упрощённо) из суммы задач в (R)unnable и (D) состояниях.
Кейс 1
LA подскочил, видим большую нагрузку на CPU → скорее всего, у нас много задач, претендующих на процессор (Runnable state).
Система деградирует. Всё просто.
Кейс 2
LA подскочил, процессор не загружен → скорее всего, много заблокированных задач, ожидающих I/O-подсистему (D state).
Деградирует ли система? Возможно, да. Возможно, нет...
———
Конкретное значение LA мало о чём скажет. Вот 5 — это много или мало? А 55?
То есть всегда требуются дополнительные показатели, с которыми будем соотносить LA, например количество ядер на машине (что, судя по формуле выше, неверно).
Кейс 3
10 ядер на машине, LA = 5.00.
Что можем сказать? Ничего конкретного 🙂
В равной степени это могут быть:
- 0 заблокированных задач, 5 в Runnable (выглядит ок);
- 5 заблокированных, 0 в Runnable (выглядит не очень);
- 2 заблокированных, 3 в Runnable (это ок или не ок?).
И так далее.
———
Вывод: зачем использовать метрику, интерпретация которой требует стольких действий, чтобы хотя бы примерно очертить проблемное место?
PSI призван заменить Load Average, который не позволяет быстро и точно определять состояние системы.
Load Average (средняя нагрузка) — обобщённая метрика, включающая в себя показатели совершенно разных подсистем (CPU и I/O). Это значит, что она не годится на роль интерпретатора проблем: «посмотрел и понял, где проблема».
Вторая особенность LA.
Метрика складывается (упрощённо) из суммы задач в (R)unnable и (D) состояниях.
Кейс 1
LA подскочил, видим большую нагрузку на CPU → скорее всего, у нас много задач, претендующих на процессор (Runnable state).
Система деградирует. Всё просто.
Кейс 2
LA подскочил, процессор не загружен → скорее всего, много заблокированных задач, ожидающих I/O-подсистему (D state).
Деградирует ли система? Возможно, да. Возможно, нет...
———
Конкретное значение LA мало о чём скажет. Вот 5 — это много или мало? А 55?
То есть всегда требуются дополнительные показатели, с которыми будем соотносить LA, например количество ядер на машине (что, судя по формуле выше, неверно).
Кейс 3
10 ядер на машине, LA = 5.00.
Что можем сказать? Ничего конкретного 🙂
В равной степени это могут быть:
- 0 заблокированных задач, 5 в Runnable (выглядит ок);
- 5 заблокированных, 0 в Runnable (выглядит не очень);
- 2 заблокированных, 3 в Runnable (это ок или не ок?).
И так далее.
———
Вывод: зачем использовать метрику, интерпретация которой требует стольких действий, чтобы хотя бы примерно очертить проблемное место?
Telegram
Performance matters!
В нашей инфраструктуре мы давно используем PSI (Pressure Stall Information) для выявления перенасыщения (saturation) ресурсов: CPU, диск, память.
Есть мнение, что saturation — ключевой показатель, по которому легко понять состояние системы. Вокруг него построена…
Есть мнение, что saturation — ключевой показатель, по которому легко понять состояние системы. Вокруг него построена…
👍20
Про PSI, часть 3.
(часть 1, 2)
PSI (Pressure Stall Information) – это метрика показывает сколько времени задачи ждут доступа к ресурсам системы (CPU, память, диск). То есть отражает уровень насыщения (saturation): если значение больше нуля => есть конкуренция за ресурсы.
PSI делится на два типа:
- Some – одна и более задач ждут ресурс (это плохо, но может быть не критично)
- Full – все задачи находятся в ожидании ресурса (а это уже коллапс)
Примечание №1. Сегодня речь только про CPU.
Примеры:
- 2 CPU, 1 runnable задача → конкуренции за CPU нет, PSI = 0
- 2 CPU, 2 runnable задачи → конкуренции всё ещё нет, PSI = 0
- 2 CPU, 4 runnable задачи → две задачи исполняются, две ждут, PSI > 0 (две из четырех задач всегда ожидают своей очереди).
Примечание №2: под
Формула подсчета PSI (упрощенная):
где:
- runnable_tasks – общее число задач, готовых к выполнению;
- num_cpus – количество доступных CPU;
- delayed_tasks – задачи, ожидающие ресурсы;
- active_tasks – задачи, выполняемые в данный момент.
Примеры:
- для 2 CPU и 1 runnable задачи:
- для 2 CPU и 4 runnable задачи:
Это значит, что какие-то задачи всегда ожидают CPU (
Так чем полезен PSI?
Он даёт 100% чистый сигнал: если PSI > 0, значит, есть ожидание процессора, значит система замедляется.
Есть и недостаток - PSI не показывает тренды и реагирует лишь постфактум, когда проблема УЖЕ появилась.
Теперь вернемся к Load Average и представим сколько дополнительной информации нам потребуется, чтобы выявить перенасыщение CPU.
Ну как минимум количество runnable процессов и CPU на машине. Три показателя!
При этом рост LA может быть связан не только с CPU, но и с I/O, что усложняет интерпретацию и требует дополнительного времени на анализ.
А так хочется один простой показатель, по которому сразу понятно, есть проблема илиеще нет :)
——————-
❓На засыпку: почему на уровне системы может быть только PSI some? Бывают ли случаи когда появляется PSI full?
P.S. Скрин "на поразглядывать"
(часть 1, 2)
PSI (Pressure Stall Information) – это метрика показывает сколько времени задачи ждут доступа к ресурсам системы (CPU, память, диск). То есть отражает уровень насыщения (saturation): если значение больше нуля => есть конкуренция за ресурсы.
PSI делится на два типа:
- Some – одна и более задач ждут ресурс (это плохо, но может быть не критично)
- Full – все задачи находятся в ожидании ресурса (а это уже коллапс)
Примечание №1. Сегодня речь только про CPU.
Примеры:
- 2 CPU, 1 runnable задача → конкуренции за CPU нет, PSI = 0
- 2 CPU, 2 runnable задачи → конкуренции всё ещё нет, PSI = 0
- 2 CPU, 4 runnable задачи → две задачи исполняются, две ждут, PSI > 0 (две из четырех задач всегда ожидают своей очереди).
Примечание №2: под
runnable я подразумеваю как исполняемые в данный момент, так и готовые к исполнению задачи.Формула подсчета PSI (упрощенная):
threads = min(runnable_tasks, num_cpus)
SOME = min(delayed_tasks / threads, 1)
FULL = (threads - min(active_tasks, threads)) / threads
где:
- runnable_tasks – общее число задач, готовых к выполнению;
- num_cpus – количество доступных CPU;
- delayed_tasks – задачи, ожидающие ресурсы;
- active_tasks – задачи, выполняемые в данный момент.
Примеры:
- для 2 CPU и 1 runnable задачи:
threads = min(1, 2) = 1
SOME = min(0 / 1, 1) = 0
FULL = (1 - min(1, 1)) / 1 = 0
- для 2 CPU и 4 runnable задачи:
threads = min(4, 2) = 2
SOME = min((4 - 2) / 2, 1) = min(2 / 2, 1) = 1 # или 100%
FULL = (2 - min(2, 2)) / 2 = 0 # или 0%
Это значит, что какие-то задачи всегда ожидают CPU (
some), но в целом что-то да исполняется на процессоре.Так чем полезен PSI?
Он даёт 100% чистый сигнал: если PSI > 0, значит, есть ожидание процессора, значит система замедляется.
Есть и недостаток - PSI не показывает тренды и реагирует лишь постфактум, когда проблема УЖЕ появилась.
Теперь вернемся к Load Average и представим сколько дополнительной информации нам потребуется, чтобы выявить перенасыщение CPU.
Ну как минимум количество runnable процессов и CPU на машине. Три показателя!
При этом рост LA может быть связан не только с CPU, но и с I/O, что усложняет интерпретацию и требует дополнительного времени на анализ.
А так хочется один простой показатель, по которому сразу понятно, есть проблема или
——————-
❓На засыпку: почему на уровне системы может быть только PSI some? Бывают ли случаи когда появляется PSI full?
P.S. Скрин "на поразглядывать"
👍15❤1
Готовлюсь к внутреннему митапу с докладом о потерях сетевого трафика: как их диагностировать и устранять.
В основе GIF-анимация, иллюстрирующая путь и остановки входящего сетевого пакета в ядре Linux.
Очереди в ядре Linux
* RX queue. Первая остановка: очередь сетевой карты (см.
* QDisc. Приоритизация, модификация и многое другое возможны с помощью дисциплины очередей. Calico, Cilium и подобные ребята перехватывает пакеты именно здесь (eBPF)
* Input Packet Queue. Очередь перед стеком протоколов.
📍Для новых соединений
* SYN queue. Очередь, где SYN-сегменты дожидаются ACK;
* Accept queue. Приложение через
📍Для уже установленных соединений
* Out Of Order queue. При нарушении очередности (sequence number больше ожидаемого), пакет помещается в нее, до восстановления правильного порядка;
* Recv queue. TCP-буфер сокета, из него приложение читает данные системным вызовом
———
Подробнее я описывал весь процесс в двух частях: один, два.
P.S. Кстати, поддержать канал теперь можно на Бусти или просто донатом!
#network #tcp #kernel
В основе GIF-анимация, иллюстрирующая путь и остановки входящего сетевого пакета в ядре Linux.
Очереди в ядре Linux
* RX queue. Первая остановка: очередь сетевой карты (см.
ethtool -l eth0)* QDisc. Приоритизация, модификация и многое другое возможны с помощью дисциплины очередей. Calico, Cilium и подобные ребята перехватывает пакеты именно здесь (eBPF)
* Input Packet Queue. Очередь перед стеком протоколов.
📍Для новых соединений
* SYN queue. Очередь, где SYN-сегменты дожидаются ACK;
* Accept queue. Приложение через
accept()подтверждает, что соединение установлено - зеленый свет для обмена данными.📍Для уже установленных соединений
* Out Of Order queue. При нарушении очередности (sequence number больше ожидаемого), пакет помещается в нее, до восстановления правильного порядка;
* Recv queue. TCP-буфер сокета, из него приложение читает данные системным вызовом
read().———
Подробнее я описывал весь процесс в двух частях: один, два.
P.S. Кстати, поддержать канал теперь можно на Бусти или просто донатом!
#network #tcp #kernel
🔥20👍9
На днях node-exporter зарелизил версию 1.9.0, где среди изменений мне бросилось в глаза:
В обсуждении к MR был комментарий от @SuperQ:
Что за рекомендации такие и кого они аффектят?
—————
Для начала чуть теории 📖
Обработчики прерываний бывает двух типов: аппаратные (Hard IRQ) и программные (SoftIRQ).
Hard IRQ вызываются устройствами (диск, клавиатура, сеть и т. д.) и немедленно обрабатываются процессором. Они могут прервать любой код, поэтому их обработку делают минимальной, чтобы быстрее освободить CPU для других задач.
SoftIRQ обрабатывает прерывания асинхронно в контексте ядра, не блокируя CPU. Поэтому ему отдают наиболее длительные этапы обработки.
В CPU Usage нагрузка от Hard IRQ отображается в
—————
Теперь вернемся к изначальному вопросу.
Оказывается
В redhat-like дистрибутивах эта опция включена, тогда как в debian и им подобным её по умолчанию отключают!
А дальше самое интересное.
Если
1. если прерывание произошло в user mode, то время его обработки будет учтено как
2. если прерывание произошло во время выполнения процесса в system mode, его обработка будет засчитана в
3. если прерывание произошло во время выполнения фоновых задач ядра (kworker, ksoftirqd), то его обработка будет засчитана в
В итоге точность анализа загрузки CPU снижается, что может вводить в заблуждение. Говорят, что погрешность может достигать 5–7%! А это хорошо бы проверить😉
Судя по документации ядра, опцию отключают из-за её небольшого влияния на производительность:
И это проверим:)
P.S. Подробнее, с примерами про подсчет irq читай в блоге Танел Подера.
#cpu #kernel
- [FEATURE] pressure: add IRQ PSI metrics [#3048]
В обсуждении к MR был комментарий от @SuperQ:
Nice, it's too bad `CONFIG_IRQ_TIME_ACCOUNTING` is recommend to be off so very few people will benefit from this by default.
Что за рекомендации такие и кого они аффектят?
—————
Для начала чуть теории 📖
Обработчики прерываний бывает двух типов: аппаратные (Hard IRQ) и программные (SoftIRQ).
Hard IRQ вызываются устройствами (диск, клавиатура, сеть и т. д.) и немедленно обрабатываются процессором. Они могут прервать любой код, поэтому их обработку делают минимальной, чтобы быстрее освободить CPU для других задач.
SoftIRQ обрабатывает прерывания асинхронно в контексте ядра, не блокируя CPU. Поэтому ему отдают наиболее длительные этапы обработки.
В CPU Usage нагрузка от Hard IRQ отображается в
%irq, а от SoftIRQ в %softirq.—————
Теперь вернемся к изначальному вопросу.
Оказывается
%irq отображается только при включённой опции CONFIG_IRQ_TIME_ACCOUNTING, иначе он всегда равен нулю. В redhat-like дистрибутивах эта опция включена, тогда как в debian и им подобным её по умолчанию отключают!
# mpstat 1
Linux 5.10.0-20-amd64 02/18/2025 _x86_64_ (8 CPU)
11:28:51 PM CPU %usr %nice %sys %iowait %irq %soft %steal %idle
11:28:52 PM all 40.15 0.00 1.38 0.00 0.00 0.63 0.00 57.84
11:28:53 PM all 28.81 0.00 1.78 0.25 0.00 0.51 0.13 68.53
11:28:54 PM all 35.29 0.00 2.25 0.00 0.00 0.25 0.00 62.20
11:28:55 PM all 17.68 0.00 1.14 0.00 0.00 0.38 0.25 80.56
11:28:56 PM all 16.31 0.00 1.99 0.00 0.00 0.25 0.25 81.20
# mpstat -I ALL 1
11:32:53 PM CPU intr/s
11:32:54 PM all 18466.00
11:32:55 PM all 11983.00
11:32:56 PM all 14019.00
%irq нулевой, хотя кол-во прерываний десятки тысяч.А дальше самое интересное.
Если
CONFIG_IRQ_TIME_ACCOUNTING отключена, нагрузка от Hard IRQ никуда не исчезнет (кэп🙂), а учитывается как:1. если прерывание произошло в user mode, то время его обработки будет учтено как
%user того процесса, который выполнялся до прерывания.2. если прерывание произошло во время выполнения процесса в system mode, его обработка будет засчитана в
%sys этого процесса.3. если прерывание произошло во время выполнения фоновых задач ядра (kworker, ksoftirqd), то его обработка будет засчитана в
%sys системыВ итоге точность анализа загрузки CPU снижается, что может вводить в заблуждение. Говорят, что погрешность может достигать 5–7%! А это хорошо бы проверить😉
Судя по документации ядра, опцию отключают из-за её небольшого влияния на производительность:
Select this option to enable fine granularity task irq time
accounting. This is done by reading a timestamp on each
transitions between softirq and hardirq state, so there can be a
small performance impact.
If in doubt, say N here.
И это проверим:)
P.S. Подробнее, с примерами про подсчет irq читай в блоге Танел Подера.
#cpu #kernel
GitHub
Release 1.9.0 / 2025-02-17 · prometheus/node_exporter
[CHANGE] meminfo: Convert linux implementation to use procfs lib #3049
[CHANGE] Update logging to use Go log/slog #3097
[FEATURE] filesystem: Add node_filesystem_mount_info metric #2970
[FEATURE] b...
[CHANGE] Update logging to use Go log/slog #3097
[FEATURE] filesystem: Add node_filesystem_mount_info metric #2970
[FEATURE] b...
👍16🔥13
Из серии "Смотрите что нашел!"
Low latency tuning guide - сборник техник по оптимизации системы для минимизации задержек.
Внутри как привычные подходы вроде изоляции ядер и отключения гиперпоточности, так и совсем для меня новые:
- сокращение прерываний таймера планировщика через
- закрепление страниц в RAM с помощью
Особую ценность добавляет обилие ссылок для более глубокого погружения в предмет.
Упражнение: задавать себе вопросы из разряда: "Для low latency советуют SCHED_RR и SCHED_FIFO, а что если важнее пропускная способность? Как бы я изменил подход? Почему?"
#kernel #tuning #low_latency
Low latency tuning guide - сборник техник по оптимизации системы для минимизации задержек.
Внутри как привычные подходы вроде изоляции ядер и отключения гиперпоточности, так и совсем для меня новые:
- сокращение прерываний таймера планировщика через
nohz_full, что будет снижать накладные расходы на context swithing.- закрепление страниц в RAM с помощью
mlockall(MCL_CURRENT | MCL_FUTURE), чтобы избежать их выгрузки на диск.Особую ценность добавляет обилие ссылок для более глубокого погружения в предмет.
Упражнение: задавать себе вопросы из разряда: "Для low latency советуют SCHED_RR и SCHED_FIFO, а что если важнее пропускная способность? Как бы я изменил подход? Почему?"
#kernel #tuning #low_latency
rigtorp.se
Low latency tuning guide
This guide describes how to tune your AMD64/x86_64 hardware and Linux system for running real-time or low latency workloads.
🔥24👍8👎1
Не знаю как и зачем пишутся статьи на 40 минут чтения, но факт есть:
The case of the vanishing CPU: A Linux kernel debugging story
Ещё не погружался, но все ключевые слова на месте: CPU throttling, ebpf, perf, kernel bug.
Будем разбирать.
The case of the vanishing CPU: A Linux kernel debugging story
Ещё не погружался, но все ключевые слова на месте: CPU throttling, ebpf, perf, kernel bug.
Будем разбирать.
ClickHouse
The case of the vanishing CPU: A Linux kernel debugging story
Read about how a Linux kernel memory bug led to instability in ClickHouse Cloud on GCP, and the challenges of diagnosing and resolving it.
👍16👎1
В творческом затишье делюсь новостью: мой боевой товарищ запустил TG-канал о SRE.
Зная его, качество гарантировано!
https://xn--r1a.website/r9yo11yp9e
Зная его, качество гарантировано!
https://xn--r1a.website/r9yo11yp9e
Telegram
The Last of 9s
Последний оплот хардкорного SRE. Без воды, только польза! Кулстори, хаки и техгайды про наблюдаемость, перформанс, устойчивость, траблшутинг и все вокруг этого.
🔥 99,99 🔥
🔥 99,99 🔥
👍12🔥6🤝3👎1
В умных книгах пишут, что к анализу производительности стоит подходить в несколько этапов:
1. определить сколько времени должна занимать работа;
2. измерить сколько работа занимает на самом деле;
3. выдвинуть гипотезу почему есть различия и что фиксить;
4. внести изменения в систему с целью привести (2) к (1);
5. GOTO (2)
Если первый этап обычно стабилен и редко меняется, то основное внимание уделяется последующим шагам, при этом пункты с измерениями выглядят наиболее значимыми. И (возможно) самыми сложными.
———————————
Пример анализа потребления CPU
(очень упрощенно)
* замерь общее потребление CPU на машине (top, vmstat);
* определи долю целевого процесса и её распределение на user/system mode (top, pidstat);
* найди самые "горячие" функции/методы/системные вызовы (perf, profile);
* изучи код, чтобы понять, что именно «бьет» по производительности.
Когда узкое место найдено, принимай решение: оптимизировать логику, менять зависимости или что-то еще. И не забудь про мантры производительности.
Теперь внеси изменения и замерь их аффект.
А вот тут нас могут караулить неприятности: точно ли измерили то, что ожидали измерить?
———————————
В главе Measuring CPUs книги Understanding Software Dynamics разбирается случай измерения времени выполнения инструкции
В качестве решения "в лоб" автор приводит:
Здесь фиксируется начальное время (
Разделив полученную дельту на число итераций, автор получил 6.76 тактов процессора на один проход, что довольно дорого для такой "элементарной инструкции".
(и это среднее значение, а значит, разброс по перцентилям может быть значительным)
На этом можно было бы остановиться: "померяли же!", но если копнуть глубже (куда уж глубже🙂), то окажется, что на ассемблере цикл
Прямая речь:
Далее автор рассматривает способы минимизировать оверхед от цикла и выходит на почти "чистый" замер
А казалось бы "че там мерить, зашел вышел на пять минут"')
———————————
Кстати, не обязательно копаться так глубоко, чтобы столкнуться с подобными ошибками интерпретации, они встречаются повсеместно.
Например, можно думать, что измеряем задержки на сети, хотя узкое место в локальной очереди на машине.
Или радоваться быстрым дискам, хотя по факту запись шла асинхронно через файловую систему.
P.S. Товарищ, будь бдителен!
1. определить сколько времени должна занимать работа;
2. измерить сколько работа занимает на самом деле;
3. выдвинуть гипотезу почему есть различия и что фиксить;
4. внести изменения в систему с целью привести (2) к (1);
5. GOTO (2)
Если первый этап обычно стабилен и редко меняется, то основное внимание уделяется последующим шагам, при этом пункты с измерениями выглядят наиболее значимыми. И (возможно) самыми сложными.
———————————
Пример анализа потребления CPU
(очень упрощенно)
* замерь общее потребление CPU на машине (top, vmstat);
* определи долю целевого процесса и её распределение на user/system mode (top, pidstat);
* найди самые "горячие" функции/методы/системные вызовы (perf, profile);
* изучи код, чтобы понять, что именно «бьет» по производительности.
Когда узкое место найдено, принимай решение: оптимизировать логику, менять зависимости или что-то еще. И не забудь про мантры производительности.
Теперь внеси изменения и замерь их аффект.
А вот тут нас могут караулить неприятности: точно ли измерили то, что ожидали измерить?
———————————
В главе Measuring CPUs книги Understanding Software Dynamics разбирается случай измерения времени выполнения инструкции
add в тактах процессора.В качестве решения "в лоб" автор приводит:
start = RDTSC();
for (int n = 0; n < 5000; ++n) {
sum += 1;
}
delta = RDTSC() - start;
Здесь фиксируется начальное время (
start), затем выполняется инкремент (add) в цикле, после чего рассчитывается разница между началом и концом операции (delta).Разделив полученную дельту на число итераций, автор получил 6.76 тактов процессора на один проход, что довольно дорого для такой "элементарной инструкции".
(и это среднее значение, а значит, разброс по перцентилям может быть значительным)
На этом можно было бы остановиться: "померяли же!", но если копнуть глубже (куда уж глубже🙂), то окажется, что на ассемблере цикл
for{} раскладывается в:cmpl $999999999, -44(%rbp) # сравнение i с константой
jg .L3 # условный переход, если i > константа
addq $1, -40(%rbp) # sum += 1; значение sum хранится в памяти по адресу -40(%rbp)
addl $1, -44(%rbp) # ++i; значение i хранится в памяти по адресу -44(%rbp)
jmp .L4 # переход к началу цикла
Прямая речь:
[прим. alebsys: loop for{}] has five instructions, three of which access memory by three reads (cmpl, addq, addl) and two writes (addq, addl). So most of what we are measuring is in fact memory accesses, specifically to the L1 data cache.
Далее автор рассматривает способы минимизировать оверхед от цикла и выходит на почти "чистый" замер
add в 1.06 такта на инструкцию.А казалось бы "че там мерить, зашел вышел на пять минут"')
———————————
Кстати, не обязательно копаться так глубоко, чтобы столкнуться с подобными ошибками интерпретации, они встречаются повсеместно.
Например, можно думать, что измеряем задержки на сети, хотя узкое место в локальной очереди на машине.
Или радоваться быстрым дискам, хотя по факту запись шла асинхронно через файловую систему.
P.S. Товарищ, будь бдителен!
Telegram
Performance matters!
На Hacker News происходит множество обсуждений разной степени интересности и иногда попадаются настоящие самородки, где умные дядьки делятся с общественностью своими знаниями.
Одно из таких - Ask HN: How can I learn about performance optimization?
Народ…
Одно из таких - Ask HN: How can I learn about performance optimization?
Народ…
👍13🔥5👎1🎉1
CPU Isolation: исследование в шести частях о применение техник CPU Isolation для задержкочувствительных нагрузок.
Недостаточно просто выгнать все процессы, кроме целевого, с ядра с помощью cpuset и привязать его к CPU через taskset. Надо не забыть и о фоновых задачах ядра, т.н. housekeeping work.
Оборотной стороной housekeeping work является то, что она привносит непредсказуемые задержки (jitter), прерывая выполнение пользовательских задач.
Борьба с этими задержками и есть центральная тема цикла.
Недостаточно просто выгнать все процессы, кроме целевого, с ядра с помощью cpuset и привязать его к CPU через taskset. Надо не забыть и о фоновых задачах ядра, т.н. housekeeping work.
Housekeeping work – это совокупность фоновых операций, которые ядро Linux выполняет для поддержания своей внутренней инфраструктуры. Эти задачи включают обработку таймеров, обновление системного времени, управление очередями отложенной работы (workqueues), обработку прерываний, очистку ресурсов и прочее. Несмотря на то, что они обычно незаметны для пользователя, именно эти операции обеспечивают стабильность и корректное функционирование всей системы.
Оборотной стороной housekeeping work является то, что она привносит непредсказуемые задержки (jitter), прерывая выполнение пользовательских задач.
Борьба с этими задержками и есть центральная тема цикла.
Suse
CPU Isolation – Introduction – by SUSE Labs (p...
This blog post is the first in a technical series by SUSE Labs team exploring Kernel CPU Isolation along with one of its c...
👍7🔥5👎1
Профилируя процессы в Linux хорошо бы представлять оверхед от инструментов и выбирать подходящий под задачу.
На примере работы утилиты
Для начала запустим
Скорость в 2.3GB/s будет эталонной, с которой и будем все сравнивать.
strace
Падение скорости в ~76 раз, неплохо поработали!
perf
Замедление на треть уже и не выглядит чем-то страшным:)
bpftrace
Хваленный eBPF дал оверхеда более чем в 2 раза! А говорили, что "eBPF это про скорость" :(
——————————————————
С
Но в чем eBPF не справился? Давайте обсудим!
На примере работы утилиты
dd сравним накладные расходы strace, perf и bpftrace (eBPF).Для начала запустим
dd без оберток:# dd if=/dev/zero of=/dev/null bs=512 count=100k
102400+0 records in
102400+0 records out
52428800 bytes (52 MB, 50 MiB) copied, 0.0229283 s, 2.3 GB/s
Скорость в 2.3GB/s будет эталонной, с которой и будем все сравнивать.
strace
# strace -c dd if=/dev/zero of=/dev/null bs=512 count=100k
102400+0 records in
102400+0 records out
52428800 bytes (52 MB, 50 MiB) copied, 1.73851 s, 30.2 MB/s
...
Падение скорости в ~76 раз, неплохо поработали!
perf
# perf stat -e 'syscalls:sys_enter_*' dd if=/dev/zero of=/dev/null bs=512 count=100k
102400+0 records in
102400+0 records out
52428800 bytes (52 MB, 50 MiB) copied, 0.0287921 s, 1.8 GB/s
Замедление на треть уже и не выглядит чем-то страшным:)
bpftrace
# bpftrace -e 'tracepoint:syscalls:sys_enter_* /comm == "dd"/
{ @[probe] = count(); }' -c '/usr/bin/dd if=/dev/zero of=/dev/null bs=512 count=100k'
102400+0 records in
102400+0 records out
52428800 bytes (52 MB, 50 MiB) copied, 0.0475401 s, 1.1 GB/s
Хваленный eBPF дал оверхеда более чем в 2 раза! А говорили, что "eBPF это про скорость" :(
——————————————————
С
strace всё ясно: он через ptrace приостанавливает dd на каждом syscall, с переходом в kernel mode и обратно. Но в чем eBPF не справился? Давайте обсудим!
Важно помнить: dd генерирует много системных вызовов, поэтому такой большой оверхед у `strace`. Цифры выше это скорее утрированный пример, но суть отражают верно.
👍24🔥3👎1
Об IPC
(конспект по книге Performance Analysis and Tuning on Modern CPUs)
Я уже писал о показателе Instructions Per Cycle (IPC) (например тут и тут). Сейчас разберём детали глубже.
Instruction Per Cycle (IPC) — это среднее количество инструкций, завершённых за один такт процессора:
Определим ключевые понятия.
Инструкции делятся на executed и retired.
- Executed инструкции уже выполнены, но результат ещё не записан в память. Они могут выполняться вне порядка (out of order) и быть отменены, например, из-за miss branch prediction;
- Retired инструкции полностью завершены, то есть и выполнены и их результаты записаны (committed). Отменить их уже нельзя.
Executed напрямую не отслеживаются, а для retired есть отдельный счётчик:
Cycles (циклы) процессора бывают двух видов:
- core;
- reference.
Разница важна при динамическом изменении частоты процессора:
1. если CPU работает на штатной частоте: core = reference.
2. если CPU разогнан: core > reference.
Core Cycles отражают реальную текущую, когда Reference Cycles базовую (по паспорту) частоту процессора.
Следовательно IPC показывает единицу A) выполненной B) полезной работы в текущий момент.
Факторы, ограничивающие IPC
(перечислены в случайном порядке, список неполный):
- скорость памяти и cache misses;
- архитектура процессора: скалярность, загрузка слотов пайплайна;
- тип и сложность инструкций;
- branch misprediction (пенальти на ошибку по 10–25 ns);
- ...
Скалярность ограничивает количество инструкций, которые процессор может обработать за один такт, и задаёт теоретический максимум IPC.
На практике этот максимум недостижим: процессор может одновременно выполнять только определённые типы инструкций. Например, в 6-wide архитектуре за такт можно провести четыре операции сложения/вычитания, одну загрузку и одну запись, но не шесть загрузок одновременно.
to be continued...
#cpu #theory
(конспект по книге Performance Analysis and Tuning on Modern CPUs)
Я уже писал о показателе Instructions Per Cycle (IPC) (например тут и тут). Сейчас разберём детали глубже.
Instruction Per Cycle (IPC) — это среднее количество инструкций, завершённых за один такт процессора:
IPC = Retired Instructions / Core CyclesОпределим ключевые понятия.
Инструкции делятся на executed и retired.
- Executed инструкции уже выполнены, но результат ещё не записан в память. Они могут выполняться вне порядка (out of order) и быть отменены, например, из-за miss branch prediction;
- Retired инструкции полностью завершены, то есть и выполнены и их результаты записаны (committed). Отменить их уже нельзя.
Executed напрямую не отслеживаются, а для retired есть отдельный счётчик:
perf stat -e instructions -- ./a.exe
2173414 instructions # 0.80 insn per cycle
Cycles (циклы) процессора бывают двух видов:
- core;
- reference.
Разница важна при динамическом изменении частоты процессора:
1. если CPU работает на штатной частоте: core = reference.
2. если CPU разогнан: core > reference.
Core Cycles отражают реальную текущую, когда Reference Cycles базовую (по паспорту) частоту процессора.
perf stat -e cycles,ref-cycles -- ./a.exe
43340884632 cycles # 3.97 GHz <= Core Cycles
37028245322 ref-cycles # 3.39 GHz <= Reference Cycles
Следовательно IPC показывает единицу A) выполненной B) полезной работы в текущий момент.
IPC не зависит от изменения тактовой частоты, так как всегда рассчитывается на один цикл.
Факторы, ограничивающие IPC
(перечислены в случайном порядке, список неполный):
- скорость памяти и cache misses;
- архитектура процессора: скалярность, загрузка слотов пайплайна;
- тип и сложность инструкций;
- branch misprediction (пенальти на ошибку по 10–25 ns);
- ...
Скалярность ограничивает количество инструкций, которые процессор может обработать за один такт, и задаёт теоретический максимум IPC.
На практике этот максимум недостижим: процессор может одновременно выполнять только определённые типы инструкций. Например, в 6-wide архитектуре за такт можно провести четыре операции сложения/вычитания, одну загрузку и одну запись, но не шесть загрузок одновременно.
to be continued...
#cpu #theory
Telegram
Performance matters!
CPU Utilization is Wrong by Brendan Gregg
B. Gregg показывает почему метрика утилизации %CPU может вводить в заблуждение - она включает в себя не только время затраченное на полезную работу CPU, но и ожидание обращения к памяти.
Как решение предлагается…
B. Gregg показывает почему метрика утилизации %CPU может вводить в заблуждение - она включает в себя не только время затраченное на полезную работу CPU, но и ожидание обращения к памяти.
Как решение предлагается…
👍18🔥9👎1
Perf Weekly | №1
(инструменты, системы и производительность)
Troubleshooting Slow TCP Transfers: A Stack-Level Approach
Большинство проблем в production решаются без сложных инструментов. Обычно достаточно стандартных утилит, доступных из любого дистрибутива. Главное понимать, как и где их использовать. Например
Why strong engineers are rarely blocked
Заблокированными могут быть не только треды, но и инженеры. По ссылке о важности менеджмента своих активностей, чтобы двигаться быстрее.
Can We Know Whether a Profiler is Accurate?
Профайлеры, как и любой инструмент, имеют погрешность измерений. В статье разбирается любопытный способ оценивать их точность через контролируемое замедление программы.
(инструменты, системы и производительность)
Troubleshooting Slow TCP Transfers: A Stack-Level Approach
Большинство проблем в production решаются без сложных инструментов. Обычно достаточно стандартных утилит, доступных из любого дистрибутива. Главное понимать, как и где их использовать. Например
ss и nstat. Why strong engineers are rarely blocked
Заблокированными могут быть не только треды, но и инженеры. По ссылке о важности менеджмента своих активностей, чтобы двигаться быстрее.
Can We Know Whether a Profiler is Accurate?
Профайлеры, как и любой инструмент, имеют погрешность измерений. В статье разбирается любопытный способ оценивать их точность через контролируемое замедление программы.
Linkedin
Troubleshooting Slow TCP Transfers: A Stack-Level Approach
"Something is wrong with the network. I used to get 4Gbps transfers but now I'm only getting 120Mbps.
1🔥15👍9
Perf Weekly | №2
(инструменты, системы и производительность)
Good Performance for Bad Days
Часто перф анализ проводят при нормальной/обычной нагрузке (задержки низкие, пропускная способность высокая, поведение предсказуемо).
Автор напоминает, что настоящие проблемы начинаются при насыщении и перегрузке системы, а значит и фокус исследований стоит смещать в эту сторону.
Introduce tseries() For Capturing Time Series Data #3838
В v0.24.0 версии bpftrace наряду с привычными
Режим позволяет увидеть, как значения меняются во времени. И это уже не просто циферки в терминале, а настоящие time series!
NUMA Cost & Performance
Статья о том, почему многосокетные (NUMA) серверы часто оказываются дороже, сложнее в настройке и зачастую медленнее, чем односокетные системы, и что с этим делать.
(инструменты, системы и производительность)
Good Performance for Bad Days
Часто перф анализ проводят при нормальной/обычной нагрузке (задержки низкие, пропускная способность высокая, поведение предсказуемо).
Автор напоминает, что настоящие проблемы начинаются при насыщении и перегрузке системы, а значит и фокус исследований стоит смещать в эту сторону.
Introduce tseries() For Capturing Time Series Data #3838
В v0.24.0 версии bpftrace наряду с привычными
hist / lhist появился ещё один способ визуализации: tseries. Режим позволяет увидеть, как значения меняются во времени. И это уже не просто циферки в терминале, а настоящие time series!
NUMA Cost & Performance
Статья о том, почему многосокетные (NUMA) серверы часто оказываются дороже, сложнее в настройке и зачастую медленнее, чем односокетные системы, и что с этим делать.
brooker.co.za
Good Performance for Bad Days - Marc's Blog
👍9🔥8❤1
Perf Weekly | №3
(инструменты, системы и производительность)
Linux perf-top basics: understand the %
All Roads Lead to IPC: Rethinking CPU Performance Design
IPC как главная метрика CPU. Архитектура процессора, узкие места, latency vs occupation и как это всё применять, чтобы ускорить код. Дорогу осилит идущий 🙂.
How can I learn about performance optimization?
Большой тред о том, как расти в performance engineering: как учиться, на чем фокусироваться, типичные ловушки и куча полезных ссылок.
А возникшие вопросы можно обсудить в треде;)
(инструменты, системы и производительность)
Linux perf-top basics: understand the %
perf top базовая утилита, которая в три секунды покажет чем же занят процесс. Полезно делать это эффективно!All Roads Lead to IPC: Rethinking CPU Performance Design
IPC как главная метрика CPU. Архитектура процессора, узкие места, latency vs occupation и как это всё применять, чтобы ускорить код. Дорогу осилит идущий 🙂.
How can I learn about performance optimization?
Большой тред о том, как расти в performance engineering: как учиться, на чем фокусироваться, типичные ловушки и куча полезных ссылок.
dbi Blog
Linux perf-top basics: understand the %
By Franck Pachot . Linux kernel has a powerful instrumentation that can be accessed easily. When you want to drill down into your program functions to understand their CPU usage, “perf” is the easiest. It can attach to the processes, sample the CPU cycles…
🔥11👍6❤2
Замечали "странные" проценты в скобках в выводе
Это multiplexing.
Аппаратных счётчиков в CPU может быть меньше, чем событий, которые мы хотим измерить. И perf выкручивается тем, что по очереди переключается между событиями и далее масштабирует результат.
Соответственно проценты в скобках это доля времени от всего замера, когда конкретное событие реально измерялось.
Если хочется разобраться глубже (а как иначе?), читаем статью PMU counters and profiling basics.
perf stat?$ perf stat -e cycles,instructions,LLC-loads,LLC-load-miss,... -C 1 -- sleep 5
Performance counter stats for 'CPU(s) 1':
15989951459 cycles (62.40%)
8367516992 instructions (74.96%)
6897420 LLC-loads (75.04%)
1258051 LLC-load-miss (75.05%)
1977812325 dTLB-loads (75.05%)
1059510 dTLB-load-misses (75.05%)
1957630660 mem_load_retired.l1_hit (49.91%)
24843220 mem_load_retired.l1_miss (49.91%)
Это multiplexing.
Аппаратных счётчиков в CPU может быть меньше, чем событий, которые мы хотим измерить. И perf выкручивается тем, что по очереди переключается между событиями и далее масштабирует результат.
Соответственно проценты в скобках это доля времени от всего замера, когда конкретное событие реально измерялось.
Если хочется разобраться глубже (а как иначе?), читаем статью PMU counters and profiling basics.
easyperf.net
PMU counters and profiling basics. | Easyperf
🔥13❤2
Про L3 Cache (LLC)
L3 последний из “быстрых” уровней памяти, он способен отдавать данные за 30-60 циклов процессора.
А дальше идет DRAM, где стоимость доступа Local / Remote может составлять до 150–300 cycles!
Потому если перформанс для нас важен, то хорошо когда
Осознав масштаб трагедии, идём смотреть, как чувствуют себя наши системы.
—
Node exporter любезно предоставляет набор метрик (через perf коллектор) для оценки обращений к L3:
В perf им соответствуют ивенты:
Там и подсчитаем:
Разница существенна, какой метрике будем доверять? :)
cache-references / cache-misses
Это самые “шумные” ивенты, включают в себя:
- запросы как на read так и на store;
- prefetch;
- instruction fetch;
- спекулятивные выполнения.
То есть по этим событиям сложно сделать вывод о реальном положении дел с L3.
LLC-loads / LLC-load-misses
Здесь детализации побольше: отслеживаются только запросы на read (для write есть отдельные
В целом это уже то, с чем можно работать и делать более менее обоснованные выводы из полученных цифр.
Но может есть что-то более точное?
mem_load_retired.l3_*
Для процессоров Intel доступны события
А еще они precise (PEBS)! Но и об этом в другой раз:)
Итоги
1. если хочется быстро оценить ситуацию, то пользуйся
2. если хочется точнее разобраться откуда идут промахи, то
Гудлак 😊
—
p.s. поддержать плюсом на linkedin тут.
L3 последний из “быстрых” уровней памяти, он способен отдавать данные за 30-60 циклов процессора.
А дальше идет DRAM, где стоимость доступа Local / Remote может составлять до 150–300 cycles!
Потому если перформанс для нас важен, то хорошо когда
L3 Hit Rate большой, а L3 Miss Rate маленький ;)Осознав масштаб трагедии, идём смотреть, как чувствуют себя наши системы.
—
Node exporter любезно предоставляет набор метрик (через perf коллектор) для оценки обращений к L3:
- node_perf_cache_refs_total
- node_perf_cache_misses_total
- node_perf_cache_ll_read_hits_total
- node_perf_cache_ll_read_misses_total
В perf им соответствуют ивенты:
- cache-references
- cache-misses
- LLC-loads
- LLC-load-miss
Там и подсчитаем:
$ perf stat -e cache-references,cache-misses \
-e LLC-loads,LLC-load-misses \
-- sleep 5
166680 cache-references
38376 cache-misses # 23.0% miss rate
65552 LLC-loads
8997 LLC-load-misses # 13.7% miss rate
Разница существенна, какой метрике будем доверять? :)
cache-references / cache-misses
Это самые “шумные” ивенты, включают в себя:
- запросы как на read так и на store;
- prefetch;
- instruction fetch;
- спекулятивные выполнения.
Спекулятивное выполнение это когда процессор исполняет инструкции заранее, предполагая, что выбранный путь выполнения окажется верным.
То есть по этим событиям сложно сделать вывод о реальном положении дел с L3.
LLC-loads / LLC-load-misses
Здесь детализации побольше: отслеживаются только запросы на read (для write есть отдельные
LLC-store* события) + спекулятивные обращения.В целом это уже то, с чем можно работать и делать более менее обоснованные выводы из полученных цифр.
Но может есть что-то более точное?
mem_load_retired.l3_*
Для процессоров Intel доступны события
mem_load_retired.l3_hit и mem_load_retired.l3_miss. Они учитывают только те загрузки, которые были retired (реально выполнены и завершены процессором), то есть действительно повлияли на ход выполнения программы:$ perf stat -e cache-references,cache-misses \
-e LLC-loads,LLC-load-misses \
-e mem_load_retired.l3_hit,mem_load_retired.l3_miss \
-- sleep 5
199082 cache-references
55283 cache-misses # 27.7% miss rate
65554 LLC-loads
8796 LLC-load-misses # 13.4% miss rate
16790 mem_load_retired.l3_hit
3694 mem_load_retired.l3_miss # 22.0% miss rate
А еще они precise (PEBS)! Но и об этом в другой раз:)
Итоги
1. если хочется быстро оценить ситуацию, то пользуйся
LLC-load* (или соответствующие им метрики в Node exporter)2. если хочется точнее разобраться откуда идут промахи, то
mem_load_retired.l3_* в помощь.Гудлак 😊
—
p.s. поддержать плюсом на linkedin тут.
Linkedin
Про L3 Cache (LLC)
L3 последний из “быстрых” уровней памяти, он способен отдавать данные за 30-60 циклов процессора. А дальше идет DRAM, где стоимость доступа Local / Remote может составлять до 150–300 cycles! Потому если перформанс для нас важен, то хорошо когда L3 Hit Rate…
1🔥21✍3❤2