如何对 php/mysql 网站进行基准测试
Posted
技术标签:
【中文标题】如何对 php/mysql 网站进行基准测试【英文标题】:How to benchmark php/mysql site 【发布时间】:2010-12-22 11:19:27 【问题描述】:我想知道。
我们有一个几乎完成并准备上线的网络应用程序,我们知道有多少人将在一年内使用它,但完全不知道普通用户需要多少带宽,他们消耗了多少时间数据库等。我们需要确定要购买的正确服务器。
是否有服务器端 linux 可以监控每个用户的这些统计信息?这样我们就可以获取这些数据并进行推断?
如果我完全搞错了,请告诉我,但我相信这是新网络应用程序的常见活动。
编辑:我可能要求提供不正确的信息。我们可以看到数据库查询需要多长时间以及加载页面需要多长时间,但不知道服务器上的负载是多少。我要问的问题是我们可以平均一次处理 100 个用户...1000 个吗?达到 100 万用户需要什么类型的服务器要求。等等。
感谢您的帮助。
【问题讨论】:
抱歉,我编辑了我的问题,因为我不相信这很清楚。 【参考方案1】:我觉得相当有用的一个工具是jmeter,它允许(最基本的)你将浏览器设置为使用 jmeter 作为代理,然后你在你的网站上四处游荡,它会记录你所做的一切。
一旦您对它对您的大部分网站的测试感到满意,您就可以将测试保存在 jmeter 中并告诉它使用设定的线程数和每个线程的循环数来运行您的测试,以模拟您的负载网站。
例如,您可以运行 50 个客户端,每个客户端运行测试计划 10 次。
然后您可以上下调整数字以查看它对网站的性能影响,它会为您绘制响应时间图表。
这让您可以调整不同的参数、尝试不同的缓存策略并检查这些更改对现实世界的影响。
【讨论】:
【参考方案2】:您可以使用 ApacheBench 工具(ab,通常是 apache web-server 包的一部分)进行压力测试(10 个客户端的 1k 请求 = ab -c 10 -n 1000 http://url)脚本,您怀疑这可能足够慢。 它将向您显示响应时间的分布(在 90% 的情况下,请求的处理时间少于 200 毫秒)。
您还可以获取由该特定脚本执行的 SQL 查询并为它们执行“解释计划”,以便粗略了解当表中的记录数增加 10-100-1000 万倍时它将如何降级。
关于它可以服务多少用户 - 您可以使用您最喜欢的浏览器并模拟典型的用户访问,获取 access_log 文件并汇总发送的字节数(日志行中的最后一个数字之一)。例如,每次用户访问是 5kb text/html+50kb png/jpg/etc.=55kb。加上标题/等,假设每次访问 60kb*1m=每天 60gb 流量。您的带宽是否足够好? (60gb/86.4ksec=700kb/sec)。
【讨论】:
【参考方案3】:除非您使用heavyweight framework or something like that,否则数据库查询可能是您应用中最慢的部分。
我所做的监控是测量我的数据库抽象对象中每个查询的执行时间。然后,对于每个花费超过 X 毫秒的查询(填写您自己的 X),我在查询日志文件中写入一行,标识 php 脚本文件和查询出现的行号(使用 debug_backtrace()
查找信息)以及其他相关的上下文数据(例如用户身份、日期时间等)。
这个日志文件可以在以后统计分析各种信息。
例如,您可以找出哪些查询占用的总时间最长(与服务器负载相关)。或者哪些是最慢的(与用户体验相关)。或者哪个用户加载系统最多(可能是滥用或机器人)。
我还绘制帕累托图来确定最适合在哪里花费我的查询优化工作。
【讨论】:
不错的答案!我将为我正在从事的一些更大的项目实施它! 您能否简要解释一下您如何使用帕累托图来确定最适合花费时间的地方? en.wikipedia.org/wiki/Pareto_chart 列出每个查询的总查询时间和平均查询时间,并按一个或另一个指标对列表进行排序。按照 Wikipedia 链接中的描述绘制图表,以可视化您在最慢的 N 个查询上花费了多少时间以及它们是哪些查询。从列表顶部开始优化工作。【参考方案4】:最重要的是,您需要定义您想要的性能:您可以始终找到需要优化的区域。但是,将响应时间从 750ms 提高到 650ms 可能不值得花时间。
正如 fsb 所说,您的瓶颈可能是您的数据库查询。但是,我还要规定,您的瓶颈并不总是(甚至可能)在您认为的位置。我建议先阅读this,然后对您的网站进行全球测试。
如果是您的应用程序,请使用 xdebug 来分析您的 PHP 代码。然后使用 WinCacheGrind 或 KCacheGrind 分析输出。这可能会让您大吃一惊。
为了解决数据库问题,它是非常特定于数据库的。对于 mysql,我开启了慢查询日志,记录不使用索引的查询,启用查询日志,并使用 Maatkit 之类的工具包来分析查询并找到瓶颈。
【讨论】:
【参考方案5】:我最近开发了一个 PHP 组件,可以轻松地为您的基准测试进行测试并生成报告。我还发表了一篇关于基准测试重要性的文章,我指出了测试的重要性,因为不测试可能会对您的 Web 服务器造成压力。基准测试非常重要,但我认为在当今时代人们往往会忘记这一点,而实际上它应该位于清单的顶部。错误检查、安全检查,然后是基准测试。
按这个顺序。
http://www.binpress.com/app/benchmark-testing-framework/534?ad=1229 - 我开发的框架 http://www.binpress.com/blog/2011/08/04/the-important-of-benchmark-testing/?ad=1229 - 我写的文章
【讨论】:
【参考方案6】:试试这个:
<?php
/**
* Created by PhpStorm.
* User: NEO
* Date: 9/18/2016
* Time: 10:57 AM
*/
/**
* PHP Script to benchmark PHP and MySQL-Server
*
* inspired by / thanks to:
* - www.php-benchmark-script.com (Alessandro Torrisi)
* - www.webdesign-informatik.de
*
* @author odan
* @license MIT
*/
// -----------------------------------------------------------------------------
// Setup
// -----------------------------------------------------------------------------
set_time_limit(120); // 2 minutes
$options = array();
// Optional: mysql performance test
$options['db.host'] = '127.0.0.1';
$options['db.user'] = 'root';
$options['db.pw'] = '';
$options['db.name'] = 'bache3';
// -----------------------------------------------------------------------------
// Main
// -----------------------------------------------------------------------------
// check performance
$benchmarkResult = test_benchmark($options);
// html output
echo "<!DOCTYPE html>\n<html><head>\n";
echo "<style>
table
color: #333; /* Lighten up font color */
font-family: Helvetica, Arial, sans-serif; /* Nicer font */
width: 640px;
border-collapse:
collapse; border-spacing: 0;
td, th
border: 1px solid #CCC; height: 30px;
/* Make cells a bit taller */
th
background: #F3F3F3; /* Light grey background */
font-weight: bold; /* Make sure they're bold */
td
background: #FAFAFA; /* Lighter grey background */
</style>
</head>
<body>";
echo array_to_html($benchmarkResult);
echo "\n</body></html>";
exit;
// -----------------------------------------------------------------------------
// Benchmark functions
// -----------------------------------------------------------------------------
function test_benchmark($settings)
$timeStart = microtime(true);
$result = array();
$result['version'] = '1.1';
$result['sysinfo']['time'] = date("Y-m-d H:i:s");
$result['sysinfo']['php_version'] = PHP_VERSION;
$result['sysinfo']['platform'] = PHP_OS;
$result['sysinfo']['server_name'] = $_SERVER['SERVER_NAME'];
$result['sysinfo']['server_addr'] = $_SERVER['SERVER_ADDR'];
test_math($result);
test_string($result);
test_loops($result);
test_ifelse($result);
if (isset($settings['db.host']))
test_mysql($result, $settings);
$result['total'] = timer_diff($timeStart);
return $result;
function test_math(&$result, $count = 99999)
$timeStart = microtime(true);
$mathFunctions = array("abs", "acos", "asin", "atan", "bindec", "floor", "exp", "sin", "tan", "pi", "is_finite", "is_nan", "sqrt");
for ($i = 0; $i < $count; $i++)
foreach ($mathFunctions as $function)
call_user_func_array($function, array($i));
$result['benchmark']['math'] = timer_diff($timeStart);
function test_string(&$result, $count = 99999)
$timeStart = microtime(true);
$stringFunctions = array("addslashes", "chunk_split", "metaphone", "strip_tags", "md5", "sha1", "strtoupper", "strtolower", "strrev", "strlen", "soundex", "ord");
$string = 'the quick brown fox jumps over the lazy dog';
for ($i = 0; $i < $count; $i++)
foreach ($stringFunctions as $function)
call_user_func_array($function, array($string));
$result['benchmark']['string'] = timer_diff($timeStart);
function test_loops(&$result, $count = 999999)
$timeStart = microtime(true);
for ($i = 0; $i < $count; ++$i)
$i = 0;
while ($i < $count)
++$i;
$result['benchmark']['loops'] = timer_diff($timeStart);
function test_ifelse(&$result, $count = 999999)
$timeStart = microtime(true);
for ($i = 0; $i < $count; $i++)
if ($i == -1)
elseif ($i == -2)
else if ($i == -3)
$result['benchmark']['ifelse'] = timer_diff($timeStart);
function test_mysql(&$result, $settings)
$timeStart = microtime(true);
$link = mysqli_connect($settings['db.host'], $settings['db.user'], $settings['db.pw']);
$result['benchmark']['mysql']['connect'] = timer_diff($timeStart);
//$arr_return['sysinfo']['mysql_version'] = '';
mysqli_select_db($link, $settings['db.name']);
$result['benchmark']['mysql']['select_db'] = timer_diff($timeStart);
$dbResult = mysqli_query($link, 'SELECT VERSION() as version;');
$arr_row = mysqli_fetch_array($dbResult);
$result['sysinfo']['mysql_version'] = $arr_row['version'];
$result['benchmark']['mysql']['query_version'] = timer_diff($timeStart);
$query = "SELECT BENCHMARK(1000000,ENCODE('hello',RAND()));";
$dbResult = mysqli_query($link, $query);
$result['benchmark']['mysql']['query_benchmark'] = timer_diff($timeStart);
mysqli_close($link);
$result['benchmark']['mysql']['total'] = timer_diff($timeStart);
return $result;
function timer_diff($timeStart)
return number_format(microtime(true) - $timeStart, 3);
function array_to_html($array)
$result = '';
if (is_array($array))
$result .= '<table>';
foreach ($array as $k => $v)
$result .= "\n<tr><td>";
$result .= '<strong>' . htmlentities($k) . "</strong></td><td>";
$result .= array_to_html($v);
$result .= "</td></tr>";
$result .= "\n</table>";
else
$result = htmlentities($array);
return $result;
【讨论】:
【参考方案7】:我对基准测试工具没有任何经验,但在某些情况下,我会创建一个简单的表格,其中包含 id
、ipaddress
、parsetime
、queries
字段。每次页面刷新或被调用(在 ajax 情况下)时,只需插入一个新行。然后分析一周/月/季度/年收集的数据。这不是您喜欢的情况,而是一种在短时间内获得一些统计数据的简单方法。
PHP 基准测试的一些结果: http://www.google.nl/search?hl=nl&source=hp&q=php+benchmark&meta=&aq=f&oq=
【讨论】:
是的,我想我正在寻找更“外部”的应用程序来跟踪它的行为。 我已经更新了我的答案并提供了一个链接,希望它能进一步帮助你。 为什么要投反对票?给出它的人可以解释这个答案有什么问题吗?以上是关于如何对 php/mysql 网站进行基准测试的主要内容,如果未能解决你的问题,请参考以下文章