• Модуль: perfmon
  • Путь к файлу: ~/bitrix/modules/perfmon/classes/general/cluster.php
  • Класс: CPerfCluster
  • Вызов: CPerfCluster::Measure
function Measure($host, $port, $url, $threads, $iterations = 3, $arOptions = array())
{
	$strRequest = "GET ".$url." HTTP/1.0rn";
	$strRequest .= "User-Agent: BitrixSMCluster (thread #thread#)rn";
	$strRequest .= "Accept: */*rn";
	$strRequest .= "Host: ".$host."rn";
	$strRequest .= "Accept-Language: enrn";

	$socket_timeout = intval($arOptions["socket_timeout"]);
	if ($socket_timeout <= 0)
		$socket_timeout = 20;

	$rw_timeout = intval($arOptions["rw_timeout"]);
	if ($rw_timeout <= 0)
		$rw_timeout = 20;

	$iteration_timeout = intval($arOptions["iteration_timeout"]);
	if ($iteration_timeout <= 0)
		$iteration_timeout = 30;

	if ($port == 443)
		$proto = "ssl://";
	else
		$proto = "";

	$start = getmicrotime();
	$end = $start + $iterations;
	$end_after_end = $start + $iteration_timeout;

	$errors = 0;
	$arConnections = array();
	$arCookie = array();
	$arStartTimes = array();
	$Pages = 0;
	$arPageExecTime = array();
	$arResponseTime = array();
	while (getmicrotime() < $end)
	{
		//Open new connection if needed
		if (count($arConnections) < $threads)
		{
			//Find first free slot
			for ($j = 0; $j < $threads; $j++)
			{
				if (!isset($arConnections[$j]))
				{
					$arStartTimes[$j] = getmicrotime();
					$socket = fsockopen($proto.$host, $port, $errno, $errstr, $socket_timeout);
					if ($socket)
					{
						$request = str_replace("#thread#", $j, $strRequest);
						if (isset($arCookie[$j]))
							$request .= "Cookie: ".implode(';', $arCookie[$j])."rn";
						$request .= "rn";

						stream_set_blocking($socket, true);
						stream_set_timeout($socket, $rw_timeout);
						fputs($socket, $request);
						stream_set_blocking($socket, false);
						$arConnections[$j] = $socket;
						$Pages++;
					}
					else
					{
						$arConnections[$j] = false;
						$errors++;
					}
					break;
				}
			}
		}

		//Try to read connections
		foreach ($arConnections as $j => $socket)
		{
			if ($socket)
			{
				if (feof($socket))
				{
					$arResponseTime[] = getmicrotime() - $arStartTimes[$j];
					fclose($socket);
					unset($arConnections[$j]);
				}
				else
				{
					$line = fgets($socket);
					if ($line !== false)
					{
						if (preg_match("/^Set-Cookie: (.*?)=(.*?);/", $line, $match))
						{
							$arCookie[$j][$match[1]] = $match[1].'='.$match[2];
						}
						elseif (preg_match("/(\d+\.\d+)<\/span>/", $line, $match))
						{
							$arPageExecTime[] = $match[1];
						}
						elseif (preg_match("/^HTTP\/\d+\.\d+\s+(\d+)\s/", $line, $match))
						{
							if ($match[1] !== '200')
								$errors++;
						}
						elseif (preg_match("/^Status:\s+(\d+)\s/", $line, $match))
						{
							if ($match[1] !== '200')
								$errors++;
						}
					}
				}
			}
		}
	}

	//Finish all connections
	while (count($arConnections) > 0)
	{
		//Try to read connections
		foreach ($arConnections as $j => $socket)
		{
			if ($socket)
			{
				if (feof($socket))
				{
					$arResponseTime[] = getmicrotime() - $arStartTimes[$j];
					fclose($socket);
					unset($arConnections[$j]);
				}
				else
				{
					$line = fgets($socket);
					if ($line !== false)
					{
						if (preg_match("/(\d+\.\d+)<\/span>/", $line, $match))
						{
							$arPageExecTime[] = $match[1];
						}
						elseif (preg_match("/^HTTP\/\d+\.\d+\s+(\d+)\s/", $line, $match))
						{
							if ($match[1] !== '200')
								$errors++;
						}
						elseif (preg_match("/^Status:\s+(\d+)\s/", $line, $match))
						{
							if ($match[1] !== '200')
								$errors++;
						}
					}
				}
			}
			else
			{
				unset($arConnections[$j]);
			}
			if (getmicrotime() > $end_after_end)
				break;
		}
		if (getmicrotime() > $end_after_end)
			break;
	}

	$this->Add(array(
		"THREADS" => $threads,
		"HITS" => $Pages,
		"ERRORS" => $errors,
		"PAGES_PER_SECOND" => $Pages / $iterations,
		"PAGE_EXEC_TIME" => count($arPageExecTime)? array_sum($arPageExecTime) / count($arPageExecTime): 0,
		"PAGE_RESP_TIME" => count($arResponseTime)? array_sum($arResponseTime) / count($arResponseTime): 0,
	));
}