Если вы строили графики загрузки процессора под управлением FreeBSD с помощью стандартного шаблона ucd/net CPU Usage то наверняка обратили внимание, что загрузка получается выше 100%.  На многопроцессорных системах могут быть вообще баснословные числа. Например, для  сервера с четырехъядерным процессором:

Давайте разберемся, откуда такие данные. Источники SNMP MIB:

  • CPU Usage User — .1.3.6.1.4.1.2021.11.50.0
  • CPU Usage Nice  — .1.3.6.1.4.1.2021.11.51.0
  • CPU Usage System — .1.3.6.1.4.1.2021.11.52.0

Посмотрим, что возвращает SNMP.

serf01# snmpwalk -Os -c public -v 2c 127.0.01 .1.3.6.1.4.1.2021.11

ssIndex.0 = INTEGER: 1
ssErrorName.0 = STRING: systemStats
ssSwapIn.0 = INTEGER: 7 kB
ssSwapOut.0 = INTEGER: -37 kB
ssIOSent.0 = INTEGER: 0 blocks/s
ssIOReceive.0 = INTEGER: 0 blocks/s
ssSysInterrupts.0 = INTEGER: 165 interrupts/s
ssSysContext.0 = INTEGER: 0 switches/s
ssCpuUser.0 = INTEGER: 43
ssCpuSystem.0 = INTEGER: 0
ssCpuIdle.0 = INTEGER: 32
ssCpuRawUser.0 = Counter32: 162371531
ssCpuRawNice.0 = Counter32: 5300
ssCpuRawSystem.0 = Counter32: 91083634
ssCpuRawIdle.0 = Counter32: 100392986
ssCpuRawWait.0 = Counter32: 0
ssCpuRawKernel.0 = Counter32: 87265687
ssCpuRawInterrupt.0 = Counter32: 3817947
ssIORawSent.0 = Counter32: 8
ssIORawReceived.0 = Counter32: 30619264
ssRawInterrupts.0 = Counter32: 273379803
ssRawContexts.0 = Counter32: 2
ssCpuRawSoftIRQ.0 = Counter32: 0
ssRawSwapIn.0 = Counter32: 44851
ssRawSwapOut.0 = Counter32: 58914

Откуда SNMP берет эти данные?  Правильно, из ядра! Проверяем

serf01# snmpwalk -Os -c public -v 2c 127.0.0.1 .1.3.6.1.4.1.2021.11 && sysctl kern.cp_time
ssIndex.0 = INTEGER: 1
ssErrorName.0 = STRING: systemStats
ssSwapIn.0 = INTEGER: -2 kB
ssSwapOut.0 = INTEGER: 41 kB
ssIOSent.0 = INTEGER: 0 blocks/s
ssIOReceive.0 = INTEGER: 0 blocks/s
ssSysInterrupts.0 = INTEGER: 0 interrupts/s
ssSysContext.0 = INTEGER: 0 switches/s
ssCpuUser.0 = INTEGER: 47
ssCpuSystem.0 = INTEGER: 0
ssCpuIdle.0 = INTEGER: 27
ssCpuRawUser.0 = Counter32: 162432132
ssCpuRawNice.0 = Counter32: 5300
ssCpuRawSystem.0 = Counter32: 91115741
ssCpuRawIdle.0 = Counter32: 100430658
ssCpuRawWait.0 = Counter32: 0
ssCpuRawKernel.0 = Counter32: 87296514
ssCpuRawInterrupt.0 = Counter32: 3819227
ssIORawSent.0 = Counter32: 8
ssIORawReceived.0 = Counter32: 30619264
ssRawInterrupts.0 = Counter32: 273370363
ssRawContexts.0 = Counter32: 3
ssCpuRawSoftIRQ.0 = Counter32: 0
ssRawSwapIn.0 = Counter32: 44445
ssRawSwapOut.0 = Counter32: 60481

kern.cp_time: 162432312 5300 87296662 3819242 100430895

В переменной kern.cp_time содержатся «попугаи», характеризующие загрузку User,  Nice, Kernel, Interrupt, Idle. Что сии попугаи обозначают? Сложим все вместе, получается  353979111 На секунду они не похожи, поскольку up 7+17:18:28, что составляет 667108 секунд. Делим попугаев на секунды и получаем 530! Это похоже на максимальное значение загрузки cacti. Причем на разных системах оно разное в зависимости от количества процессорных ядер. Делим 530 на число ядер 4 и получаем примерно 133. Интересное число, поищем в sysctl:

serf01# sysctl -a |grep 133
kern.clockrate: { hz = 1000, tick = 1000, profhz = 2000, stathz = 133 }
kern.cp_times: 41715910 1309 21335379 3455273 22338533 39403486 1125 21729552 49505 27662625 40190619 1380 21049129 19357 27585808 41761423 1486 23529286 309778 23244320
kern.sched.balance_interval: 133

Вот оно stathz! Частота обновления статистики загрузки процессоров. Теперь всё проясняется. В многоядерной системе SNMP отдает сумму времен загрузки всех процессоров умноженную на 133 и отображает в процентах. Таким образом максимальная теоретическая загрузка n-ядерной системы составляет  133*n %.

Призовая задача на смекалку — как привести этот срам к нормальному виду с максимумом 100%.