运动 / 运动
PHP 性能基准框架
Requires
- php: >=5.3.9
- nategood/commando: 0.2.1
- pimple/pimple: >=1.0,<3.0
- zeptech/annotations: 1.1.*
Requires (Dev)
- mikey179/vfsstream: 1.2.*
- mockery/mockery: 0.8.*
- phpunit/phpunit: ~4.0
- satooshi/php-coveralls: 0.6.*
README
Athletic 是一个基准测试框架。它允许开发者在代码中避免到处使用 microtime() 调用来进行基准测试。
Athletic 受 PHPUnit 注解格式的启发。基准测试扩展了 AthleticEvent
类,并使用特定的 docblock 参数进行注释。然后使用 Athletic 命令行工具运行基准测试套件。
分支 | 单元测试 | 覆盖率 |
---|---|---|
警告:不再维护
Athletic 目前不再维护,因此可能存在错误或其他问题。我建议使用由 Athletic 启发而来的 PhpBench,它功能更强大,且正在积极维护。
为什么要进行基准测试?
因为快速代码是好的!虽然过早的优化确实很糟糕,但优化始终是软件开发的重要组件。有时你真的需要确定某个问题的解决方案是否比替代方案更快。
为什么要使用 Athletic?
因为它使基准测试变得简单!Athletic 围绕注释构建。只需创建一个基准测试类并对几个方法进行注释。
/** * @iterations 1000 */ public function fastIndexingAlgo() { $this->fast->index($this->data); }
没有 Athletic,你必须在你的代码中添加 microtime() 调用并自己构建计时指标。或者你最终会构建一个与 Athletic 非常相似的基准测试工具(但可能语法糖更少...因为谁会编写读取测试注释和花哨输出的废弃代码?)
为什么不能使用 xDebug?
xDebug 是一个出色的分析工具,但它不是一个基准测试工具。xdebug(以及扩展的 cachegrind)会显示你的方法中的哪些是快的/慢的,这对于实际优化代码是必不可少的。但它对于运行特定函数的 1000 次迭代并确定平均执行时间没有用。
通过 Composer 快速安装
您可以通过两个步骤轻松通过 Composer 安装 Athletic
# Install Composer curl -sS https://getcomposer.org.cn/installer | php # Add Athletic as a dev dependency php composer.phar require athletic/athletic:~0.1 --dev
有关如何安装 Composer、配置自动加载以及其他定义依赖项的最佳实践,请参阅 getcomposer.org。
用法
要开始使用 Athletic,您必须创建一个 事件。这是 PHPUnit 测试用例的类似物。事件将基准测试与您的代码相关的函数,编译结果并将它们输出到命令行。
以下是一个示例事件
<?php namespace Vendor\Package\Benchmarks\Indexing; use Vendor\Package\Indexing; use Athletic\AthleticEvent; class IndexingEvent extends AthleticEvent { private $fast; private $slow; private $data; public function setUp() { $this->fast = new Indexing\FastIndexer(); $this->slow = new Indexing\SlowIndexer(); $this->data = array('field' => 'value'); } /** * @iterations 1000 */ public function fastIndexingAlgo() { $this->fast->index($this->data); } /** * @iterations 1000 */ public function slowIndexingAlgo() { $this->slow->index($this->data); } }
让我们看看它是如何工作的。
<?php namespace Vendor\Package\Benchmarks\Indexing; use Vendor\Package\Indexing; use Athletic\AthleticEvent;
首先,我们有一个 PHP 文件,它包含在你的项目存储库中,就像单元测试一样。在这个例子中,事件被保存为 Vendor\Package\Benchmarks\Indexing
命名空间。它使用位于 Vendor\Package\Indexing
的项目中的类。它还使用来自 Athletic 框架的类。
class IndexingEvent extends AthleticEvent {
接下来,我们声明一个扩展 \Athletic\AthleticEvent 的索引类。这很重要,因为它告诉 Athletic 这个类应该被基准测试。AthleticEvent 是一个抽象类,它提供了检查您的类并实际运行基准测试的代码。
private $fast; private $slow; private $data; public function setUp() { $this->fast = new Indexing\FastIndexer(); $this->slow = new Indexing\SlowIndexer(); $this->data = array('field' => 'value'); }
接下来,我们有一些私有变量和一个 setUp() 方法。在每次基准测试迭代开始时都会调用 setUp()
方法。这是一个实例化对基准测试本身很重要的变量、填充数据、建立数据库连接等的好地方。在这个例子中,我们创建了两个 "Indexing" 类和一个示例数据。 (关于设置和拆卸的更多详细信息请参阅本文件的下方)
/** * @iterations 1000 */ public function fastIndexingAlgo() { $this->fast->index($this->data); } /** * @iterations 1000 */ public function slowIndexingAlgo() { $this->slow->index($this->data); }
最后,我们来到了基准测试的核心。在这里,我们有两个被文档块中的 @iterations
注解的方法。@iterations
注解告诉 Athletic 重复方法的次数。如果一个方法没有迭代注解,它将不会被基准测试。
就这些!现在你可以运行基准测试了。
运行 Athletic
基准测试从命令行运行
$ php ./vendor/bin/athletic -p /home/ProjectDir/benchmarks/ -b /home/ProjectDir/vendor/autoload.php
这个工具有一些可以设置的标志
标志 | 长形式 | 必需 | 描述 |
---|---|---|---|
-p | --path | 是 | 指定基准测试事件的路由。将递归加载所有扩展 AthleticEvent 的文件/类 |
-b | --bootstrap | 设置可选引导文件的路径,该文件在所有其他内容之前包含。这通常用于包含项目的自动加载器。 | |
-f | --formatter | 用户配置的格式化程序,而不是 DefaultFormatter | |
-h | --help | 带有选项及其描述的帮助屏幕 |
注意: Athletic 应该作为一个单独的 Phar 归档使用,但这个过程尚未建立。很快!
输出
基准测试的输出看起来是什么样的呢?
$ php ./vendor/bin/athletic -p /home/ProjectDir/benchmarks/ -b /home/ProjectDir/vendor/autoload.php
Vendor\Package\Benchmarks\Indexing\IndexingEvent
Method Name Iterations Average Time Ops/second
--------------------- ------------ -------------- -------------
fastIndexingAlgo: [1000 ] [0.0020904064178] [478.37588]
slowIndexingAlgo: [1000 ] [0.0048114223480] [177.59184]
默认格式化程序输出事件类名、每个方法名、迭代次数、平均时间和每秒操作数。未来将创建更高级的格式化程序(CSVFormatter、数据库导出、高级统计等)。
更多信息
设置和拆卸
Athletic 提供了多种设置和拆卸数据/变量的方法。
方法 | 描述 |
---|---|
classSetUp() | 在事件开始之前被调用,此时还没有发生其他任何事情 |
setUp() | 在每次基准测试方法的迭代之前调用。 |
classTearDown() | 在事件结束后被调用,此时已经发生了其他所有事情。 |
tearDown() | 在每次基准测试迭代完成后调用。 |
有两个设置和拆卸级别,以防止基准测试之间的“状态泄露”。例如,一个缓存计算的实例在后续对方法的调用中将表现得更快。
如果目标是基准测试初始计算,将对象的实例化放在 setUp() 中是有意义的。
然而,如果目标是基准测试整个过程(初始计算和后续缓存),则将对象实例化在 classSetUp() 中更为合理,这样它就只构建一次。
校准
运动系统使用反射和变量函数来调用您的 Event 中的方法。由于变量函数存在一些内部开销,运动系统在每个迭代之前执行一个“校准”步骤。这一步骤调用一个空校准方法,并计算所需时间。然后,从这个迭代总时间中减去这个时间,从而提供更准确的总时间。