Как Рассчитывается Средняя Нагрузка?



Постановка вопроса Недавно во время собеседования в крупной компании мне задали простой вопрос, что такое Load Average. Не знаю, насколько я ответил правильно, но лично для себя я пришел к осознанию того, что точного ответа я на самом деле не знаю.

Большинство людей, вероятно, знают, что средняя нагрузка это средняя загрузка системы за определенный период времени (1, 5 и 15 минут).

Вы также можете узнать некоторые подробности у Эта статья , о том, как его использовать.

В большинстве случаев этих знаний достаточно, чтобы оценить нагрузку системы по значению LA, но я по профессии физик, и когда я вижу «среднее значение за период времени», меня сразу интересует частота дискретизации для данный период. И когда я вижу термин «ожидание ресурсов», становится интересно, какие и как долго мне нужно ждать, а также сколько тривиальных процессов нужно запустить, чтобы за короткий промежуток времени получить высокий LA. И самое главное, почему 5 минут Google не могут дать ответы на эти вопросы? Если вам тоже интересны эти тонкости, добро пожаловать под кат.



Что-то здесь не так.

Для начала давайте определим, что мы знаем.

В общих чертах, средняя нагрузка — это среднее количество процессов, ожидающих ресурсов ЦП в течение одного из трех периодов времени.

Также мы знаем, что это значение в нормальном состоянии колеблется от 0 до 1, и единица соответствует 100% загрузке одноядерной системы без перегрузки.

В дальнейшем буду рассматривать систему как одноядерную, так как она проще и показательнее.

Что здесь не так? Во-первых , мы все это знаем средний нескольких величин равна сумме этих величин, деленной на их количество.

Из той информации, которой мы располагаем, эта самая величина совершенно неясна.

Если посчитать ожидающие процессы за всю минуту, то среднее значение будет равно количеству процессов в минуту, делённому на единицу.

Если мы будем считать каждую секунду, то количество процессов в каждом подсчете будет уменьшаться вместе с диапазоном, и мы будем делить на 60. Таким образом, чем выше частота дискретизации набора данных, тем меньшее среднее значение мы получим.

Во-вторых Что означает «процесс, ожидающий ресурсов»? Если запустить сразу большое количество быстрых процессов, то они все встанут в очередь, и по логике вещей за небольшой промежуток времени LA должен вырасти до совершенно неприемлемых значений, а при длительном мониторинге должны наблюдаться постоянные скачки, что в обычной ситуации не так.

Третий , одноядерная система при 100% загрузке должна давать Load Average, равный 1. Но зависимости от параметров этого ядра нет, хотя количество процессов может существенно отличаться.

Эту проблему можно решить либо правильным определением «процесса, ожидающего ресурсов», либо наличием какой-то нормализации параметров ядра.



Литература

Найти ответы на поставленные вопросы оказалось не так уж и сложно.

Правда только на английском и не все сразу стало понятно.

В частности, были найдены две статьи: «Изучение средней нагрузки» «Средняя загрузка UNIX» Пользователь Рондо также предложил вторую часть статьи с более подробным рассмотрением математического аппарата: «Средняя нагрузка UNIX. Часть 2» И небольшой тест для тех, кто уже все понимает, указано во второй статье.

Я бы посоветовал заинтересованным прочитать обе статьи, хотя они описывают очень похожие вещи.

В первом в общих чертах описано много разных интересных деталей работы системы, а во втором более подробно рассмотрен расчет ЛА, приведены примеры с нагрузками и комментарии специалистов.



Немного ядерной магии

Из этих материалов можно узнать, что каждому вызванному процессу дается ограниченный период времени на использование ЦП; в стандартной архитектуре Intel этот период составляет 10 мс.

Это целая сотая доля секунды и в большинстве случаев процесс не требует столько времени.

Однако если процесс использовал все отведенное ему время, вызывается аппаратное прерывание, и система восстанавливает контроль над процессором.

Кроме того, каждые 10 мс увеличивается счетчик тиков (счетчик мигов).

Эти тики отсчитываются с момента запуска системы и каждые 500 тиков (каждые 5 секунд) рассчитывается средняя нагрузка.

Код самого расчета находится в ядре в файле timer.c (код приведен для версии 2.4, в версии 2.6 все это несколько разогнано, но логика не изменилась, дальше, надеюсь, нет существенные изменения тоже есть, но я, честно говоря, последние релизы не проверял):

  
  
  
   

646 unsigned long avenrun[3]; 647 648 static inline void calc_load(unsigned long ticks) 649 { 650 unsigned long active_tasks; /* fixed-point */ 651 static int count = LOAD_FREQ; 652 653 count -= ticks; 654 if (count < 0) { 655 count += LOAD_FREQ; 656 active_tasks = count_active_tasks(); 657 CALC_LOAD(avenrun[0], EXP_1, active_tasks); 658 CALC_LOAD(avenrun[1], EXP_5, active_tasks); 659 CALC_LOAD(avenrun[2], EXP_15, active_tasks); 660 } 661 }

Как видите, по очереди рассчитываются одни и те же три значения ЛА, но не уточняется, что именно рассчитывается и как именно рассчитывается.

Это тоже не проблема, код функции count_active_tasks() находится в том же файле, чуть выше:

625 static unsigned long count_active_tasks(void) 626 { 627 struct task_struct *p; 628 unsigned long nr = 0; 629 630 read_lock(&tasklist_lock); 631 for_each_task(p) { 632 if ((p->state == TASK_RUNNING || 633 (p->state & TASK_UNINTERRUPTIBLE))) 634 nr += FIXED_1; 635 } 636 read_unlock(&tasklist_lock); 637 return nr; 638 }

А CALC_LOAD находится в sched.h вместе с несколькими интересными константами:

61 #define FSHIFT 11 /* nr of bits of precision */ 62 #define FIXED_1 (1<<FSHIFT) /* 1.0 as fixed-point */ 63 #define LOAD_FREQ (5*HZ) /* 5 sec intervals */ 64 #define EXP_1 1884 /* 1/exp(5sec/1min) as fixed-point */ 65 #define EXP_5 2014 /* 1/exp(5sec/5min) */ 66 #define EXP_15 2037 /* 1/exp(5sec/15min) */ 67 68 #define CALC_LOAD(load,exp,n) \ 69 load *= exp; \ 70 load += n*(FIXED_1-exp); \ 71 load >>= FSHIFT;

Из всего вышесказанного можно сказать, что раз в 5 секунд ядро смотрит, сколько процессов находится в состояниях РАБОТАЮЩИЙ и БЕСПЕРЕБОЙНЫЙ (кстати, в других UNIX-системах такого нет) и для каждого такого процесса увеличивает счетчик на FIXED_1, который равен 1< 49 /* 50 * These are the constant used to fake the fixed-point load-average 51 * counting. Some notes: 52 * - 11 bit fractions expand to 22 bits by the multiplies: this gives 53 * a load-average precision of 10 bits integer + 11 bits fractional 54 * - if you want to count load-averages more often, you need more 55 * precision, or rounding will get you. With 2-second counting freq, 56 * the EXP_n values would be 1981, 2034 and 2043 if still using only 57 * 11 bit fractions. 58 */

Немного ядерного деления

Нет, ядро системы здесь не разваливается, просто формула CALC_LOAD, по которой рассчитывается Load Average, основана на закон радиоактивного распада или просто экспоненциальное затухание.

Этот закон есть не что иное, как решение дифференциального уравнения

Как рассчитывается средняя нагрузка?

, то есть каждое новое значение рассчитывается из предыдущего и скорость уменьшения количества элементов напрямую зависит от количества элементов.

Решением этого дифференциального уравнения является показательный закон:

Как рассчитывается средняя нагрузка?

На самом деле Load Average не является средним показателем в обычном понимании средней арифметической.

Это дискретная функция, которая рассчитывается периодически с момента запуска системы.

В этом случае значением функции является количество процессов, действующих в системе в условиях экспоненциального затухания.

Эту конструкцию мы наблюдаем, переписав расчетную часть CALC_LOAD на математический язык:

Как рассчитывается средняя нагрузка?

2^11 для нас в данном случае эквивалентно единице, мы это зафиксировали изначально и добавили везде, количество новых процессов тоже рассчитывается в этих значениях.

А

Как рассчитывается средняя нагрузка?

, где Т – интервал измерения (1, 5 или 15 минут).

Стоит отметить, что при фиксированном временном интервале и фиксированном времени между измерениями значения показателя степени можно легко вычислить заранее и использовать в качестве константы, что и сделано в коде.

Последняя операция — сдвиг вправо на 11 бит дает нам искомое значение Load Average с отбрасыванием младших порядков.



выводы

Теперь, разобравшись в том, как рассчитывается ЛА, можно попытаться ответить на вопросы, поставленные в начале статьи: 1) Среднее значение не является средним арифметическим, а является средним значением функции, которое рассчитывается каждые 5 секунд с момента запуска системы.

2) «Ожидание ресурсов ЦП» — все процессы в состояниях РАБОТАЮЩИЙ и НЕПРЕРЫВНЫЙ.

И значительных скачков Load Average при длительном мониторинге мы не наблюдаем, так как затухающая экспонента играет роль сглаживающей функции (хотя их можно заметить при рассмотрении периода в 1 минуту).

3) И вот один из самых интересных выводов.

Дело в том, что приведенная выше функция Load Average при любом значении n монотонно возрастает до этого значения, но если n так

Как рассчитывается средняя нагрузка?

Однако, помимо ответов на изначально существовавшие вопросы, анализ кода ставит и новые.

Например, применима ли затухающая экспонента для уменьшения количества ожидающих процессов? Если рассматривать радиоактивный распад, то его скорость ограничена только количеством ядер, а в нашем случае при большом количестве процессов все будет зависеть от пропускной способности процессора.

Также, если сравнить полученную формулу с показательным законом, то станет ясно, что

Как рассчитывается средняя нагрузка?

, где T — продолжительность интервала сбора данных (1, 5 или 15 минут).

Таким образом, разработчики ядра считают, что скорость снижения Load Average обратно пропорциональна длительности измерений, что несколько непонятно, по крайней мере для меня.

Что ж, нетрудно смоделировать ситуации, когда огромные значения LA не будут реально отражать загрузку системы, или наоборот. В конечном итоге похоже, что для расчета Load Average была выбрана функция сглаживания, максимально быстро уменьшающая его значение, что в целом логично для получения конечного числа, но не отражает реальный процесс.

И если мне кто-нибудь объяснит, почему именно экспонента и почему именно в такой форме, я буду очень благодарен.

Теги: #*nix #Системное администрирование #ядро Linux #средняя нагрузка

Вместе с данным постом часто просматривают: