PHP 性能分析第三篇: 性能调优实战(php货币)

网友投稿 919 2022-09-23

本站部分文章、图片属于网络上可搜索到的公开信息,均用于学习和交流用途,不能代表睿象云的观点、立场或意见。我们接受网民的监督,如发现任何违法内容或侵犯了您的权益,请第一时间联系小编邮箱jiasou666@gmail.com 处理。

PHP 性能分析第三篇: 性能调优实战(php货币)

性能调优

不用运行的代码才是绝好的代码。其他只是好的代码。所以,性能调优时,最好的选择是首先确保运行尽可能少的代码。

OpCode 缓存

在上图,我们看到启用 Zend OpCache 后发生的情况。最后一行是我们的基准,也即没有启用缓存的情况。

在中间行,我们看到较小的性能提升,以及内存使用量的大幅减少。小的性能提升(很可能)来自 Zend OpCache 优化,而非 OpCode 缓存。

第一行是优化和 OpCode 缓存后结果,我们看到很大的性能提升。

现在,我们看看 APC 之前和之后的变化。如上图所示,跟 Zend OpCache 相比,随着缓存的建立,我们看到初始(中间行)请求的性能下降,在消耗时长与内存使用量方面的表现都明显下降。

接着,随之 opcode 缓存的建立,我们看到类似的性能提升。

内容缓存

内容缓存只能在几乎没有写操作时有效运行,写操作会使缓存失效,而读操作不会。

这两个插件都会创建网站的静态 HTML 副本,而不是每次收到请求时再生成页面,从而压缩响应时间。

如果你正在开发自己的应用程序,大多数框架都有缓存模块:

查询缓存

跟内容缓存一样,查询缓存在包含大量读取操作的场景是最有效的。由于少量的数据改动就会使大块的缓存区无效,尤其不能在这种情况下依赖 MySQL 查询缓存来提高性能。

查询缓存或许在生成内容缓存时对性能有提升。

现有三种类型的缓存选项,由 query_cache_type 控制设置。

设置值为 0 或 OFF 将禁用缓存设置值为 1 或 ON 将缓存除了以 SELECT SQL_NO_CACHE 开头之外的所有选择设置值为 2 或 DEMAND 只会缓存以 SELECT SQL_CACHE 开头的选择

此外,你应该将 query_cache_size 设置为非零值。将它设置为零将禁用缓存,不管 query_cache_type 是否设置。

MySQL 查询缓存的主要问题是,它是全局的。对缓存结果集构成的表格的任何更改都将导致缓存失效。在写入操作频繁的应用程序中,这将使缓存几乎无效。

查询优化

查询优化有助于生成内容缓存时提高性能,而且,在无法缓存这种最坏的情况下也有益处。

除了分析, MySQL 还有一个帮助识别慢查询的选择——慢查询日志。慢查询日志会记录所有耗时超过指定时间的查询,以及不使用索引的查询(后者为可选项)。

您可以在 my.cnf 中使用以下配置启用日志。

[mysqld]log_slow_queries =/var/log/mysql/mysql-slow.log long_query_time =1log-queries-not-using-indexes

任何查询如果慢于 long_query_time (以秒为单位),该查询就会记录到日志文件 log_slow_queries 中。默认值是10秒,最低1秒。

此外, log-queries-not-using-indexes 选项可以将任何不使用索引的查询捕获到日志中。

之后我们可以用与 MySQL 捆绑在一起的 mysqldumpslow 命令检查日志。

在 WordPress 安装时使用这些选项 ,主页加载完成并运行后得到如下数据:

$ mysqldumpslow -g "wp_" /var/log/mysql/mysql-slow.logReading mysql slow query log from /var/log/mysql/mysql-slow.logCount: 1  Time=0.00s (0s) Lock=0.00s (0s) Rows=358.0(358), user[user]@[host] SELECT option\_name, option\_value FROM wp_options WHERE autoload ='S'Count: 1 Time=0.00s (0s) Lock=0.00s (0s) Rows=41.0(41), user[user]@[host] SELECT user\_id, meta_key, meta_value FROM wp_usermeta WHERE user_id IN (N)

首先,注意所有字符串值都以 S 表示,数字则以 N 表示。你可以添加 -a 标志来显示这些值。

接下来,请注意,这两个查询均耗时 0.00 s,这意味着他们的耗时在 1 秒的阈值以下,且没有使用索引。

在 MySQL 控制台 使用 EXPLAIN,可以检查性能下降的原因:

mysql> EXPLAIN SELECT option_name, option_value FROM wp_options WHERE autoload = 'S'\G    *************************** 1. row ***************************               id: 1      select_type: SIMPLE            table: wp_options             type: ALL    possible_keys: NULL              key: NULL          key_len: NULL              ref: NULL             rows: 433            Extra: Using where

此处,我们看到 possible_keys 是 NULL,从而确认未使用索引。

代码优化

通常只有当你不再受到 PHP 本身限制(通过使用 OpCode 缓存),缓存了尽可能多的内容,优化了查询之后,才可以开始调整代码。

代码和查询优化带来足够的性能提升才能创建其他缓存;代码在最糟糕的环境(没有缓存)下性能越高,应用就越稳定,重建缓存的速度也就越快。

让我们看看如何(潜在地)优化我们的 WordPress 安装。

令我惊讶的是,列表中的第一项 不是 MySQL (事实上 mysql_query() 是第四),而是 apply_filter() 函数。

WordPress 代码库的特点是,通过基于事件的过滤系统执行多种数据转换,执行次序按照数据经内核、插件添加或回调的顺序。

apply_filter() 函数是这些回调应用的地方。

这很有趣,因为实际上我不使用任何翻译。我(并怀疑大多数用户)在使用 WordPress 软件时都设置为本土语言:英语。

在这里,我们看到两间有趣的事。首先,在父函数中,有一个被调用了773次:__()。

查看该函数的源代码后,我们发现它是 translate() 的包装器。

根据经验法则,函数调用代价昂贵,应该尽量避免。现在我们总是调用 __() 而不是 translate() ,我们应该把别名改为 translate() 来保持向后兼容性,而 __() 则不再调用非必要的函数。

然而,实际上,这种改变不会带来多大的差异,只是微观的优化罢了——但它的确提高了代码可读性,简化了调用图。

现在,深入该函数,我们看到有 3 个 函数或方法被调用,每个 778 次:

get_translations_for_domain()NOOP_Translations::translate()apply_filters()

按照包容性实际运行时间降序排列,我们看到 apply_filter() 是目前为止耗时最长的调用。

查看代码:

translate( $text ), $text, $domain );    }    ?>

这段代码的作用是检索一个翻译对象,然后将 $translations->translate() 的结果传给 apply_filter() 。我们发现 $translations 是 NOOP_Translations 类的一个实例。

仅根据名称(NOOP),再经代码中的注释证实,我们发现翻译器实际上没有任何动作!

因此,也许我们完全可以避免这种代码!

通过在代码上进行小规模调试,我们看到当前使用的是默认的域,我们可以修改代码以忽略翻译器:

translate( $text ), $text, $domain );    }    ?>

这次运行的确更快!但是,快多少?为什么?

我们发现,函数调用的次数减少了3% ,包容性实际运行时间减少 9% ,包容性CPU时间减少12%!

之后,可以按调用次数降序排列细节页,这证实(如同我们的预期) get_translations_for_domain() 和 NOOP_Translations::translate() 函数的调用次数减少。同样,可以确认没有预料之外的变化发生。

30 分钟的工作带来9 - 12% 的性能提升,这非常可喜。这就意味着真实世界的性能收益,即便是在应用了 opcache 之后。

现在我们可以对其函数重复这个过程,直到找不到更多优化点。

其他工具

除了出色的 XHProf/XHGui,还有一些很好的工具。

uprofiler

XHProf.io

Xdebug

Webgrind 无法提供 KCachegrind 的那些特性,但它是一个 PHP Web 应用程序,在任何环境都易于安装。

若搭配 KCachegrind ,你可以轻易探索并发现性能问题。(事实上,这是我最喜欢的剖析工具!)

结语

分析和性能调优是非常复杂的工程。有了对的工具,并理解如何善用这些工具,我们可以很大程度地提高代码质量——即使是对我们不熟悉的代码库。

花时间去探索和学习这些工具是绝对值得的。

上一篇:DIY Ruby CPU 分析 Part II(第一狂少)
下一篇:如何优化 Java 性能?(如何优化征信)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~