PHP Conference Japan 2024

sys_getloadavg

(PHP 5 >= 5.1.3, PHP 7, PHP 8)

sys_getloadavg获取系统负载平均值

描述

sys_getloadavg(): 数组|false

分别返回三个样本,表示过去1、5和15分钟的平均系统负载(系统运行队列中进程的数量)。失败时返回false

参数

此函数没有参数。

返回值

返回一个包含三个样本(最近1、5和15分钟)的数组

示例

示例 #1 一个sys_getloadavg() 示例

<?php
$load
= sys_getloadavg();
if (
$load()[0] > 0.80) {
header('HTTP/1.1 503 Too busy, try again later');
die(
'服务器过载。请稍后再试。');
}
?>

注释

注意: 此函数在Windows平台上未实现。

添加注释

用户贡献的注释 13 个注释

stanislav dot eckert at vizson dot de
8 年前
用于在 Windows 和 Linux 下获取当前 CPU 负载百分比值的函数。

注意:函数为 getServerLoad()。它将返回当前 CPU 负载的十进制百分比值,如果出现错误(例如,访问权限不足),则返回 NULL。

<?php

header
("Content-Type: text/plain");

function
_getServerLoadLinuxData()
{
if (
is_readable("/proc/stat"))
{
$stats = @file_get_contents("/proc/stat");

if (
$stats !== false)
{
// 去除多余空格,以便于使用 explode() 函数提取值
$stats = preg_replace("/[[:blank:]]+/", " ", $stats);

// 分隔行
$stats = str_replace(array("\r\n", "\n\r", "\r"), "\n", $stats);
$stats = explode("\n", $stats);

// 分隔值并查找主CPU负载行
foreach ($stats as $statLine)
{
$statLineData = explode(" ", trim($statLine));

// 找到!
if
(
(
count($statLineData) >= 5) &&
(
$statLineData[0] == "cpu")
)
{
return array(
$statLineData[1],
$statLineData[2],
$statLineData[3],
$statLineData[4],
);
}
}
}
}

return
null;
}

// 返回服务器负载百分比(仅数字,无百分号)
function getServerLoad()
{
$load = null;

if (
stristr(PHP_OS, "win"))
{
$cmd = "wmic cpu get loadpercentage /all";
@
exec($cmd, $output);

if (
$output)
{
foreach (
$output as $line)
{
if (
$line && preg_match("/^[0-9]+\$/", $line))
{
$load = $line;
break;
}
}
}
}
else
{
if (
is_readable("/proc/stat"))
{
// 收集2个样本 - 每个样本周期为1秒
// 参见:https://de.wikipedia.org/wiki/Load#Der_Load_Average_auf_Unix-Systemen
$statData1 = _getServerLoadLinuxData();
sleep(1);
$statData2 = _getServerLoadLinuxData();

if
(
(!
is_null($statData1)) &&
(!
is_null($statData2))
)
{
// 获取差值
$statData2[0] -= $statData1[0];
$statData2[1] -= $statData1[1];
$statData2[2] -= $statData1[2];
$statData2[3] -= $statData1[3];

// 将用户、优先级、系统和空闲的4个值相加,并计算
// 空闲时间的百分比(这是4个值的一部分!)
$cpuTime = $statData2[0] + $statData2[1] + $statData2[2] + $statData2[3];

// 反转百分比以获取CPU时间,而不是空闲时间
$load = 100 - ($statData2[3] * 100 / $cpuTime);
}
}
}

return
$load;
}

//----------------------------

$cpuLoad = getServerLoad();
if (
is_null($cpuLoad)) {
echo
"无法估算CPU负载(可能是Windows版本太旧或Linux或Windows权限不足)";
}
else {
echo
$cpuLoad . "%";
}

?>
rick at rctonline dot nl
12年前
这是一个在Windows上也能工作的另一个方法。 请注意,此方法并不快,因此请注意对此函数的调用次数。

<?php
function get_server_load() {

if (
stristr(PHP_OS, 'win')) {

$wmi = new COM("Winmgmts://");
$server = $wmi->execquery("SELECT LoadPercentage FROM Win32_Processor");

$cpu_num = 0;
$load_total = 0;

foreach(
$server as $cpu){
$cpu_num++;
$load_total += $cpu->loadpercentage;
}

$load = round($load_total/$cpu_num);

} else {

$sys_load = sys_getloadavg();
$load = $sys_load[0];

}

return (int)
$load;

}
?>
Chris Wheeler
3年前
重要的是要注意,`sys_getloadavg()` 不返回百分比,如果您不知道 CPU 内核数量,它返回的数字毫无意义。要获得百分比形式的值,您需要将该值除以系统中的 CPU 内核数。(例如:如果值为 0.5 并且您有两个内核,那么您平均使用了 25% 的 CPU)。这是一个获取百分比值的简单函数

<?php
function percentloadavg(){
$cpu_count = 1;
if(
is_file('/proc/cpuinfo')) {
$cpuinfo = file_get_contents('/proc/cpuinfo');
preg_match_all('/^processor/m', $cpuinfo, $matches);
$cpu_count = count($matches[0]);
}

$sys_getloadavg = sys_getloadavg();
$sys_getloadavg[0] = $sys_getloadavg[0] / $cpu_count;
$sys_getloadavg[1] = $sys_getloadavg[1] / $cpu_count;
$sys_getloadavg[2] = $sys_getloadavg[2] / $cpu_count;

return
$sys_getloadavg;
}
?>
scott at corelevel dot com
18年前
我遇到了一个需要运行的大型脚本的问题——它循环遍历大约 50,000 条记录,并为其中许多记录下载几张图片,并更新数据库。

问题出现在我开始让访客访问我的网站时,服务器会落后,内存不足,iowait 飙升,mysql 速度变慢……这是一个完全下坡的螺旋。

用这个来解决它。

$load = sys_getloadavg();
$sleep=5;
$maxload=2;
if ($load[0] > $maxload) {
sleep($sleep);
echo "服务器繁忙 - 休眠 $sleep 秒<br>";
}

我必须调整负载和休眠时间才能找到适合我的脚本的方法,但现在我的服务器一点也不卡了。
匿名
15年前
要获取当前的平均负载,您可以执行以下操作:

<?php
$output
= shell_exec('cat /proc/loadavg');
$loadavg = substr($output,0,strpos($output," "));
?>
tom pittlik
18年前
下面的代码模拟了 sys_getloadavg() 的输出。您可能需要根据不同的发行版调整子字符串的捕获方式。

<?php

function sys_getloadavg_hack()
{
$str = substr(strrchr(shell_exec("uptime"),":"),1);
$avs = array_map("trim",explode(",",$str));

return
$avs;
}

print_r(sys_getloadavg_hack());

// 数组
// (
// [0] => 6.24
// [1] => 4.92
// [2] => 3.99
// )

?>

这个函数是在繁忙服务器上运行低优先级或非必需的 cron 作业的一种巧妙方法——如果负载很高,则不要继续执行任务(并在几分钟后重试)。
kexianbin at diyism dot com
10年前
使用这个
<?php
$loads
=sys_getloadavg();
$core_nums=trim(shell_exec("grep -P '^physical id' /proc/cpuinfo|wc -l"));
$load=$loads[0]/$core_nums;
echo
$load;
?>
surfchen at gmail dot com
18年前
以下代码将为旧版本的 PHP 提供此函数。
if (!function_exists('sys_getloadavg')) {
function sys_getloadavg()
{
$loadavg_file = '/proc/loadavg';
if (file_exists($loadavg_file)) {
return explode(chr(32),file_get_contents($loadavg_file));
}
return array(0,0,0);
}
}
828586 at gmail dot com
14年前
Windows 等效代码
<?php
ob_start
();
passthru('typeperf -sc 1 "\processor(_total)\% processor time"',$status);
$content = ob_get_contents();
ob_end_clean();
if (
$status === 0) {
if (
preg_match("/\,\"([0-9]+\.[0-9]+)\"/",$content,$load)) {
if (
$load[1] > get_config('busy_error')) {
header('HTTP/1.1 503 Too busy, try again later');
die(
'服务器过于繁忙。请稍后再试。');
}
}
}
?>
seb dot gibbs at ymail dot com
23天前
// 获取正确的 CPU 内核数量
// 以计算正确的使用率

function getCpuCores() {
// Linux
if (stristr(PHP_OS, 'linux')) {
// 首先,尝试 /proc/cpuinfo
if (file_exists('/proc/cpuinfo')) {
preg_match_all('/^processor/m', file_get_contents('/proc/cpuinfo'), $matches);
if ($matches[0]) return count($matches[0]);
}
// 备用方案:使用 nproc 命令
return (int)shell_exec('nproc');
}

// macOS
if (stristr(PHP_OS, 'darwin')) {
return (int)shell_exec('sysctl -n hw.physicalcpu');
}

// Windows
if (stristr(PHP_OS, 'win')) {
// 首先尝试 wmic 命令
$cpuCount = shell_exec('wmic cpu get NumberOfLogicalProcessors');
if ($cpuCount) {
preg_match('/\d+/', $cpuCount, $matches);
if (isset($matches[0])) return (int)$matches[0];
}
// 备用方案:使用环境变量
return (int)getenv('NUMBER_OF_PROCESSORS');
}

// 如果失败
return false;
}

// 使用示例
// 获取 CPU 内核数
$cores = getCpuCores();

if (is_numeric($cores)) {
$corePerc = 100/$cores;
} else {
$corePerc = 100;
$cores = '未知';
}
echo '<div><b>CPU:</b> '.$cores .' 个核心</div>';

// 显示正确的 CPU 使用率
echo '<blockquote>';
$cpu = sys_getloadavg();
echo(round($cpu[0]*$corePerc) .'% - 上一分钟<br>');
echo(round($cpu[1]*$corePerc) .'% - 过去 5 分钟<br>');
echo(round($cpu[2]*$corePerc) .'% - 过去 15 分钟<br>');
echo '</blockquote>';
匿名
3年前
一个简单的函数,用于获取大多数操作系统平台的 CPU 负载,因为实际上我还没有找到类似的协议,如果您碰巧正在测试各种操作系统平台……

function cpu_load():?string {
$load='';
if(strtolower(PHP_OS_FAMILY)=="windows") {
exec("wmic cpu get loadpercentage /all",$out);
if($out) {
foreach($out as $line) {
if($line&&preg_match("/^[0-9]+\$/",$line)) {
$load=$line;
break;
}
}
}
} else {
$load=sys_getloadavg();
}
return $load;
}
wowabbs+php at gmail dot com
3年前
<?php // 使用 FFI 在 Windows 中使用处理器
if(!dl("ffi")) // 加载扩展
throw new Exception('无法加载 FFI 扩展。');

function
GetSystemTimes()
{
static
$Kernel32;
$Kernel32??=FFI::cdef(<<<'IDL'
bool GetSystemTimes(long long *IdleTime, long long *KernelTime, long long *UserTime);
int GetLastError();
IDL, 'Kernel32.dll');

$IdleTime = FFI::new('long long');
$KernelTime = FFI::new('long long'); // 已有空闲时间
$UserTime = FFI::new('long long');

if(
$Kernel32->GetSystemTimes(FFI::addr($IdleTime), FFI::addr($KernelTime), FFI::addr($UserTime)))
return [
'Idle' =>$IdleTime ->cdata,
'Kernel' =>$KernelTime ->cdata, // 已有空闲时间
'User' =>$UserTime ->cdata,
];
return [];
}

function
GetSystemTimesDelta()
{
static
$Last=null;
static
$Delta=[0,1];
$Times=GetSystemTimes();
$Last??=$Times;
$Idle =$Times['Idle' ]-$Last['Idle' ];
$All =$Times['Kernel' ]-$Last['Kernel' ]+ // Kernel 已有空闲时间
$Times['User' ]-$Last['User' ];
if(
$All>1_000_000) // 100ms
{
$Delta=[$Idle, $All];
$Last=$Times;
}
return
$Delta;
}

function
ProcessorLoad()
{
static
$Load=0;
[
$Idle, $All]=GetSystemTimesDelta();
if(
$All>0.0)
$Load=1-$Idle/$All;
return
$Load;
}

function
KbHit()
{
Static
$Sys;
$Sys??=FFI::cdef('bool _kbhit();', 'msvcrt.dll');
return
$Sys->_kbhit();
}

while(!
KbHit())
{
echo
str_pad((string)round(ProcessorLoad()*100), 3, ' ', STR_PAD_LEFT), "%\n";
sleep(1);
}
?>
vladvarna at gmail dot com
12年前
您可以使用此方法模拟 loadavg。也可以用来获取 iowait

<?php
function ProcStats()
{
$fp=fopen("/proc/stat","r");
if(
false===$fp)
return
false;
$a=explode(' ',fgets($fp));
array_shift($a); //去除 'cpu'
while(!$a[0])
array_shift($a); //去除 ' '
var_dump($a);
fclose($fp);
return
$a;
}

$a=ProcStats();
sleep(5);
$b=ProcStats();


$total=array_sum($b)-array_sum($a);

$loadavg = round(100* (($b[0]+$b[1]+$b[2]) - ($a[0]+$a[1]+$a[2])) / $total, 2); // user+nice+system
$iowait= round(100* ($b[4] - $a[4])/$total,2);

?>
To Top