2024 年日本 PHP 研討會

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 則註釋

34
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)
{
// Remove double spaces to make it easier to extract values with explode()
$stats = preg_replace("/[[:blank:]]+/", " ", $stats);

// Separate lines
$stats = str_replace(array("\r\n", "\n\r", "\r"), "\n", $stats);
$stats = explode("\n", $stats);

// Separate values and find line for main CPU load
foreach ($stats as $statLine)
{
$statLineData = explode(" ", trim($statLine));

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

return
null;
}

// Returns server load in percent (just number, without percent sign)
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"))
{
// Collect 2 samples - each with 1 second period
// See: 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))
)
{
// Get difference
$statData2[0] -= $statData1[0];
$statData2[1] -= $statData1[1];
$statData2[2] -= $statData1[2];
$statData2[3] -= $statData1[3];

// Sum up the 4 values for User, Nice, System and Idle and calculate
// the percentage of idle time (which is part of the 4 values!)
$cpuTime = $statData2[0] + $statData2[1] + $statData2[2] + $statData2[3];

// Invert percentage to get CPU time, not idle time
$load = 100 - ($statData2[3] * 100 / $cpuTime);
}
}
}

return
$load;
}

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

$cpuLoad = getServerLoad();
if (
is_null($cpuLoad)) {
echo
"CPU load not estimateable (maybe too old Windows or missing rights at Linux or Windows)";
}
else {
echo
$cpuLoad . "%";
}

?>
25
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;

}
?>
4
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;
}
?>
9
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>";`
}

我必須調整負載和睡眠時間才能找到適合我腳本的數值,但現在我的伺服器完全不會卡住了。
3
匿名
15 年前
若要只取得目前的平均負載,您可以執行…

<?php
$output
= shell_exec('cat /proc/loadavg');
$loadavg = substr($output,0,strpos($output," "));
?>
3
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 作業的簡潔方法 - 如果負載過高,就不要繼續執行該任務(並在幾分鐘後重試)。
1
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;
?>
2
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);
}
}
2
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(
'Server too busy. Please try again later.');
}
}
}
?>
0
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 = 'Unknown';
}
echo '<div><b>CPU:</b> '.$cores .' 核心</div>';

// 顯示正確的 CPU 使用率
echo '<blockquote>';
$cpu = sys_getloadavg();
echo(round($cpu[0]*$corePerc) .'% - 最後 1 分鐘<br>');
echo(round($cpu[1]*$corePerc) .'% - 最後 5 分鐘<br>');
echo(round($cpu[2]*$corePerc) .'% - 最後 15 分鐘<br>');
echo '</blockquote>';
-1
匿名
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;
}
-2
wowabbs+php at gmail dot com
3 年前
<?php // Usage processor in Windows using FFI
if(!dl("ffi")) // Load the extension
throw new Exception('Cound not load the FFI extension.');

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'); // already has idle time
$UserTime = FFI::new('long long');

if(
$Kernel32->GetSystemTimes(FFI::addr($IdleTime), FFI::addr($KernelTime), FFI::addr($UserTime)))
return [
'Idle' =>$IdleTime ->cdata,
'Kernel' =>$KernelTime ->cdata, // already has idle time
'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 already has idle time
$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);
}
?>
-2
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); // 使用者+nice+系統
$iowait= round(100* ($b[4] - $a[4])/$total,2);
?>
To Top