我们经常说,对于一个 IO 密集型的应用过来说,语言不是性能的瓶颈,IO 的操作才是性能的瓶颈。我们常常看的也是一个接口请求需要多长时间、一次数据库查询需要多少时间,我们很少去测试一行代码、一个方法调用、一次实例化需要多长时间。
因为我们的项目中,我们大规模的使用了反射 API,我就好奇在 PHP 中一次反射需要多长时间。于是,我们来写代码来测试一下:
class Test {} $startTime = microtime(true); new ReflectionClass(Test::class); $endTime = microtime(true); var_dump(($endTime - $startTime) * 1000);
这不是一次很严谨的基准测试,所以我就不执行一万、百万次了,就执行一次。结果是 0.0040531158447265625 毫秒。是不是非常快,那么是不是说我们在项目中可以随意使用反射 API 了呢?反正,相比一次数据库查询动辄几十几百甚至几秒来说,这简直不值一提。
我们再来看下面这段代码的测试:
include 'vendor/autoload.php'; $startTime = microtime(true); new ReflectionClass(Bean::class); $endTime = microtime(true); var_dump(($endTime - $startTime) * 1000);
你猜同样是构建 ReflectionClass ,区别只是我加入了 Composer 的 Autoload 机制而已。打印的结果竟然是: 0.9691715240478516, 将近 1 毫秒,天啊!这是为什么呢?因为 PHP 的自动加载机制,在每实例化一个类的时候都会触发文件系统中去根据路径查找文件,也就是说可能会有一次 IO 操作。所以,本质上,这不是反射 API 慢,而是自动加载机制慢,是 IO 操作慢,不信你可以把代码换一下,输出的结果也是类似的:
include 'vendor/autoload.php'; $startTime = microtime(true); (new Bean); $endTime = microtime(true); var_dump(($endTime - $startTime) * 1000);
所以,在进行 PHP 项目部署的时候要做好优化工作,不然你的接口从语言层面来说就会慢几十毫秒…… 下面是一些基础的优化:
composer dump-autoload --optimize composer install --no-dev --prefer-dist --prefer-stable php artisan optimize