为 PHP 应用提速、提速、再提速!,第 1 部分: 使用操作码缓存软件提升性能和吞吐量

本文介绍如何安装、配置XCache以加速PHP应用,并通过性能测试展示了XCache带来的显著效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在很短的时间内,PHP 成为了一种非常流行的开发 Web 应用程序的程序设计语言。对初学者来说,PHP 易于安装和学习。对于有经验的开发人员而言,PHP(从 V5 开始)提供了强大的面向对象特性。PHP 开发人员拥有庞大的群体,大量的开源及商业库和工具扩展了该核心语言的功能。PHP 能迅速产生可视化结果,因此备受众人推崇。

        与其他开发 Web 应用程序的脚本语言(包括 Perl、Python 和 Ruby)相似,每次 HTTP 请求调用时,PHP 代码都会被解析和翻译为操作码(PHP 引擎直接执行的原语指令 —— 类似于汇编语言)再执行。在要求很低或可忽略的情况下,服务器看上去能立即执行这个复杂的解释过程。但是一旦处理的页面增加,解释 —— 从本质上说,重复工作 —— 就会对服务器造成很大的负担。在某些情况下,“编译” PHP 代码的时间会远远超过执行该代码所需的时间。因此,当需求增加时,您常常会自食其果,因为处理这些不断解释和动态生成的页面需要消耗更多的系统资源。

        若您对处理器和 RAM 的预算没有限制,那么就大可不必通过优化应用栈(硬件、操作系统、数据库、Web 服务器和 PHP 代码)来保证站点的可响应性。然而,由于资金通常都是最缺乏的资源,所以改善性能是必不可少的。调优意味着对系统增加内存、修改操作系统参数、加速 Web 或数据库服务器、提高代码效率或者这其中的一些组合。每一项都有其各自的作用。

不要浪费周期 —— 重复使用

        节约 CPU 周期的另一种方法是减少运行 PHP 应用程序所需的重复工作。当然,没有必要每次都把同样的 PHP 代码翻译一遍。PHP 代码被翻译成操作码后,可以把它保存起来并重复使用 —— 直到原始代码被修改。确实,缓存 —— 用于保存和重用 PHP 操作码 —— 是几种 PHP 加速器内部的机制,包括开源 Alternative PHP Cache (APC)、支持 PHP 的 Turck MMCache、XCache、eAccelerator 和商业 Zend Platform。后三类加速器能够缓存和优化字节码,这为系统提供了更多的速度提升。

        这个月,我将探究如何安装、部署和配置 XCache。XCache 相对较新,但是很多站点使用它的效果都很好。此外,XCache 易于构建、安装和配置,因为它是做为 PHP 扩展实现的。不需对 Apache 和 PHP 进行重编译。

        本文基于 XCache V1.2.0。它可为 PHP V4.3.11 至 V4.4.4、PHP V5.1.x 至 V5.2.x 以及 PHP V6 的早期版本提供可靠支持(XCache 并不支持 PHP V5.0.x)。XCache 兼容 mod_php 和 FastCGI 但并不支持 Common Gateway Interface (CGI) 和命令行 PHP 解释器。XCache 源代码能构建在许多系统上,包括 FreeBSD、Sun Solaris、Linux® 和这里所示的 Mac OS X。使用 Cygwin UNIX® 仿真环境或 Visual C,能在 Microsoft® Windows® 上构建 XCache。还可以为 Cygwin 或原生 Win32 构建 XCache。后者与 PHP 的官方 Win32 版本兼容。

        本文的演示基于 Apache V2.2.3、PHP V5.2.0、XCache V1.2.0(2006 年 10 月发布)和 Mac OS X V10.4.8 Tiger 上的 Xcode V2.4.1。硬件平台为配有 2-GHz Intel® Core Duo 处理器和 2 GB RAM 的 Apple MacBook。

构建 XCache 的基本步骤

        在开始之前,首先确保 PHP 正常安装并核实 phpize 是否位于 shell 的 PATH 下。同时,还需要一个 C 编译器,例如 GNU Compiler Collection (GCC),和一组包含 makem4 的开发工具。在 Mac OS X 上,免费的 Xcode 软件开发环境提供了必需的构建工具。

        完成以下操作步骤,在 Mac OS X 上构建、部署 XCache 并对其进行性能检测。在其他平台上构建 XCache 与之类似。如果使用 Linux,则其发行版可能已经包含了 XCache 或者已经将其以预先打包好的格式提供给您。

增加 Mac OS X 的共享内存

        首先增加 Mac OS X 上留出的共享内存总量。要实现这一目的,需创建(或编辑)文件 /etc/sysctl.conf 并创建如下条目:


清单 1. 增加 Mac OS X 上留出的共享内存总量

kern.sysv.shmmax=33554432
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=8192

         这些设置把共享内存总量增加到了 32 MB。如还需进一步扩展共享内存,可以把 kern.sysv.shmall 设定为 kern.sysv.shmmax 除以硬件页面大小。使用 sysctl hw.pagesize 能获得硬件页面大小。例如,假设需要 128 MB 的共享内存,那么设定 kern.sysv.shmmax=134217728 并设定 kern.sysv.shmall=32768

重启 Mac OS X 使修改生效。重启后,检验新设置是否生效,键入:

sysctl -a | grep kern.sysv

通过源代码构建 XCache

接下来,通过源代码构建 XCache。从 http://xcache.lighttpd.net 处下载源代码。下载完后解压代码,并转换到 .tar 文件创建的新目录。


清单 2. 通过源代码构建 XCache

$ cd /tmp
$ wget http://210.51.190.228/pub/XCache/Releases/xcache-1.2.0.tar.gz
$ tar xzf xcache-1.2.0.tar.gz
$ cd xcache

运行 phpize 为编译 XCache 做准备。


清单 3. 运行 phpize

$ phpize
Configuring for:
PHP Api Version:         20020918
Zend Module Api No:      20020429
Zend Extension Api No:   20050606

运行 configure,创建适合于原生操作系统的 makefile。


清单 4. 运行 configure 创建 makefile

$ ./configure --enable-xcache --enable-xcache-coverager
checking build system type... i686-apple-darwin8.8.1
checking host system type... i686-apple-darwin8.8.1
...
creating libtool
configure: creating ./config.status
config.status: creating config.h

此处,--enable-xcache 选项包含 XCache 支持,--enable-xcache-coverager 选项包含用于测量加速器功效的附加特性。要启用操作码优化,添加 --enable-xcache-optimizer

当然,下一步将使用 make 命令行构建和安装代码。运行 make,然后作为 root 用户运行 make install


清单 5. 利用 make 构建和安装代码

$ make
...
cp ./xcache.so /Users/strike/tmp/xcache/modules/xcache.so
Build complete.

$ sudo make install
Installing shared extensions: /usr/lib/php/extensions/no-debug-non-zts-20020429/


如果上述两项操作顺利完成,那么 XCache 将位于 /usr/lib/php/extensions/no-debug-non-zts-20020429/xcache.so。(路径 /usr/lib/php/extensions/no-debug-non-zts-20020429 反映了正在使用的 API 版本和用于构建 PHP 的编译选项。如果启用了试用的 Zend Thread Safety 特性,则 "no-debug" 应为 "debug","non-zts" 应为 "zts"。)

修改 php.ini 文件

        因为安装了扩展,所以必需修改 php.ini 文件,使之包含 XCache 扩展并对其进行配置。打开文件 /private/etc/php.ini,在其中添加如下代码行:


清单 6. 为 XCache 扩展修改 php.ini 文件

[xcache-common]
zend_extension      = /usr/lib/php/extensions/no-debug-non-zts-20020429/xcache.so

[xcache.admin]
; Change xcache.admin.user to your preferred login name
xcache.admin.user   = "admin"

; Change xcache.admin.pass to the MD5 fingerprint of your password
; Use md5 -s "your_secret_password" to find the fingerprint
xcache.admin.pass   = "0ad72f3f352fcd8acdf266bafd0ac48d"

[xcache]
; Change xcache.size to tune the size of the opcode cache
xcache.size         = 24M
xcache.shm_scheme   = "mmap"
xcache.count        = 2
xcache.slots        = 8K
xcache.ttl          = 0
xcache.gc_interval  = 0

; Change xcache.var_size to adjust the size of variable cache
xcache.var_size     = 8M
xcache.var_count    = 1
xcache.var_slots    = 8K
xcache.var_ttl      = 0
xcache.var_maxttl   = 0
xcache.var_gc_interval =     300
xcache.test         = Off
xcache.readonly_protection = On
xcache.mmap_path    = "/tmp/xcache"
xcache.coredump_directory =   ""
xcache.cacher       = On
xcache.stat         = On
xcache.optimizer    = Off

[xcache.coverager]
xcache.coverager    = On
xcache.coveragedump_directory = ""

注意:为了简明起见,此处省略了一些注释。要了解每个参数的含义,请参阅 XCache 源代码中 xcache.ini 文件设置的例子。

操作码和变量缓存的大小是 32 MB,这是 /etc/rc 留出的最大值。对于 Mac OS X,xcache.mmap_path 必须为文件名。因为 PHP 代码将在 MacBook 上运行,所以 xcache.count 应设为 2,表示 MacBook 中 CPU 的数量。要访问 XCache 统计信息页面,需改变 xcache.admin.pass 设置。运行:

$ md5 -s "password"

此处 password 为您的密码。把输出复制给 xcache.admin.pass。例如,若需将密码设定为 op3nsesam3,可以运行:

$ md5 -s "op3nsesam3"
MD5 ("op3nsesam3") = cd959ac3debe8f587546a3fa353b3268

然后把 cd959ac3debe8f587546a3fa353b3268 复制给 xcache.admin.pass

重启 Web 服务器

设置好 XCache 后,重启 Apache Web 服务器。对于大多数系统,可以以 root 用户的身份使用 apachectl restart 进行重启。

$ sudo apachectl restart
/usr/sbin/apachectl restart: httpd restarted

创建程序以调用 phpinfo()

检验 XCache 是否已启用,需创建一个小型 PHP 程序用于调用 phpinfo() 并在 Web 浏览器中打开那个文件。这样就能看到类似下图的 XCache 版面。


图 1. phpinfo() 方法给出了 XCache 设置

phpinfo() 方法给出了 XCache 设置



监控 XCache

要监控 XCache,需安装 XCache 源代码的 admin 目录中的管理页面。把整个 admin 目录复制到 Apache 文档根目录下。通常来说,Mac OS X 中的文档根目录为 /Library/WebServer/Documents。

$ cp -pr admin /Library/WebServer/Documents

复制完成后,使用 sudo apachectl restart 重启 Web 服务器。用浏览器打开 http://localhost/admin,检验管理面板是否工作正常。请参阅类似图 2 的面板。


图 2. XCache Administration 面板

XCache Administration 面板



测试应用程序

选择一个或两个应用程序进行测试。您可以使用自己的代码或者,如果想要更复杂一点,使用大型的 PHP 应用程序,例如 phpMyAdmin 或者 Serendipity

运行性能检测

Apache HTTP Web 服务器提供了一个叫做 ab 的工具,即 Apache HTTP 服务器性能检测(benchmark)工具的缩写。ab 用于为 PHP 页面自动化处理大量的请求。phpMyAdmin 应用程序将会是一个很好的选择,因为它很可能已经安装到您的系统上了。

ab 工具易于使用:只需提供给它一个重复数和一个 URL。ab 工具对这个 URL 提交若干次请求并返回统计信息。由于 XCache 已启用,所以第一个性能检测显示了加速后的性能。

在运行 ab 之前,用浏览器导航到 http://localhost/phpmyadmin/。访问这个 PHP 页面一次,便会加载用来将此页呈现到缓存内的所有 PHP 代码。此时,运行如下的性能检测,重复 100000 次。


清单 7. phpMyAdmin 的性能检测

$ ab -n 100000 http://localhost/phpmyadmin
...
Concurrency Level:      1
Time taken for tests:   14.597 seconds
Complete requests:      100000
Failed requests:        98262
   (Connect: 49131, Length: 49131, Exceptions: 0)
Broken pipe errors:     0
Non-2xx responses:      50869
Total transferred:      25739714 bytes
HTML transferred:       12005084 bytes
Requests per second:    6850.72 [#/sec] (mean)
Time per request:       0.15 [ms] (mean)
Time per request:       0.15 [ms] (mean, across all concurrent requests)
Transfer rate:          1763.36 [Kbytes/sec] received

有用的统计信息包括每秒的请求数和完成所有测试的总时间。对于前者,值越大越好;对于后者,值越小越好。

现在,在 php.ini 文件中禁用 XCache,然后再一次运行性能检测,如清单 8 所示。可以注释掉对 XCache 扩展的引用,或者关闭所有的 XCache 特性。再次运行性能检测之前,需重启 Apache。


清单 8. 禁用 XCache 时的 phpMyAdmin 性能检测

$ sudo apachectl restart
$ ab -n 100000 http://localhost/phpmyadmin
Concurrency Level:      1
Time taken for tests:   17.771 seconds
Complete requests:      100000
Failed requests:        98256
   (Connect: 49128, Length: 49128, Exceptions: 0)
Broken pipe errors:     0
Non-2xx responses:      50872
Total transferred:      25741232 bytes
HTML transferred:       12005792 bytes
Requests per second:    5627.15 [#/sec] (mean)
Time per request:       0.18 [ms] (mean)
Time per request:       0.18 [ms] (mean, across all concurrent requests)
Transfer rate:          1448.50 [Kbytes/sec] received

此处,XCache 禁用之后,每秒的请求数有所下降,表示 Apache 服务器处理每个请求需更长的时间。运行整套测试所需的时间也因此增加了。

尽管这只是一个简单的性能检测 —— phpMyAdmin 连接数据库的功能被禁用了,这样能限制单独解释 PHP 的处理时间 —— 并且不是非常科学,但它确实向我们演示了使用 XCache 能够完成哪些任务。对于微小的投入(欣慰地是,PHP 或 Apache 不需重编译),XCache 能产生一个相对较大的回报。代码越复杂,可能的受益也越大。

若想了解 XCache 是如何有效地运行的,请访问 http://localhost/xadmin 并单击 List PHP。您能看到缓存中的 PHP 文件列表,连同 cache hit、操作码的代码大小、源文件的字节大小,等等。图 3 显示了 XCache 专门为 XAMPP 栈包构建时的结果。


图 3. XCache 管理页面反映了缓存的状态和内容

XCache 管理页面反映了缓存的状态和内容



前面已经提及,XCache 是许多加速器中的一种。在强大的 Zend 软件中还有许多免费的开源替代方案和一个商业化产品可选。每种 PHP 加速器都有自己的系统需求,所以应主要根据现有的或预期的配置以及应用程序的特性选择合适的加速器。从中推荐一种很难,但是安装编译器缓存是我建议您务必要做的。

大量的调优选择

除了缓存之外,还有许多其他途径可以加速应用程序。可以通过删除 PHP 引擎的一些很深奥的特性来简化它。例如,若不需使用 TCP/IP V6 (IPv6) 网络,便可在构建 PHP 时禁用该属性。通过在 PHP 源代码树的顶部输入 ./configure --help 可以参阅 PHP 配置选项的完整列表。无论选择哪一个配置选项,都应该将:

--enable-inline-optimization --disable-debug

添加到最终的配置命令。前一选项使 PHP 有可能更快地执行(不需使用类似 Zend Engine 的软件进行额外的操作码优化);后一选项取消了 PHP 的调试模式,只有当需要解决 PHP 应用服务器本身的问题时才需开启该模式。

当然,正如一些 C 应用程序,我们能利用 C 编译器构建更佳的可执行程序。如果把 PHP 作为 Linux 或 FreeBSD 上的 Apache Dynamic Shared Object (DSO) 在 x86 处理器上运行,需考虑在 CFLAGS(存储 C 编译器选项的环境变量)中添加 -prefer-non-pic 选项。non-pic 会使用位置独立的代码构建 PHP 并能提供 10% 的性能提升。还可以使用 CFLAGS 中的 -march 确定处理器的类型,例如 -march=opteron 表示处理器类型为 AMD Opteron。

提升速度的另一个途径是操作码优化。此处,Zend Engine 之类的软件会优化编译过程中产生的操作码,这理论上会减少代码执行的工作总量。

缓存和优化都是透明的,并不需额外的编程。要应用一些优化操作,执行结构分析,或检查代码在哪花费了时间。重复的工作既不经济又运算缓慢,这显然会产生瓶颈。通过代码优化弥补周期的不足是很有价值的 —— 但是在结构分析之前不要尝试进行任何优化。


展望未来

在接下来的几个月我将再次讨论优化,会谈及调试、快速正文搜索、交替 Web 服务器等内容。同时,还将研究一个或多个 PHP 加速器和操作码优化器。实现 10% 到 200% 的性能提升只需几个小时的优化和修补。想像一下您的机器利用这些空闲的周期能做多少事情吧!

 
<think>我们正在讨论如何优化ModBus RTU通信的实时性能。ModBus RTU是一种基于串行通信(如RS-485)的协议,广泛应用于工业自动化领域。实时性能优化通常涉及减少通信延迟、提高数据吞吐量增强通信可靠性。 主要优化方向: 1. 通信参数优化:调整串口参数(波特率、数据位、停止位、奇偶校验)以提高传输速率。 2. 数据帧优化:减少数据帧长度,合并多个请求,使用更紧凑的数据表示。 3. 协议优化:调整轮询策略,使用事件触发或中断方式,减少不必要的轮询。 4. 硬件优化使用更高性能的硬件(如更快的处理器,更高速的串口模块)优化电路设计(如终端电阻匹配)。 5. 网络拓扑优化:减少从站数量,缩短通信距离,使用中继器等。 具体措施: ### 1. 提高波特率 提高波特率是最直接的加速方法。常见的波特率有9600、19200、38400、57600、115200等。在通信线路质量允许的情况下,尽量选择高波特率。例如,将波特率从9600提高到115200,理论上速度提升12倍。但要注意,提高波特率会降低抗干扰能力,因此需要确保线路质量(如使用屏蔽双绞线,正确接地)。 波特率计算公式: $$ \text{传输时间} = \frac{\text{数据帧位数}}{\text{波特率}} $$ 其中,数据帧位数包括起始位、数据位、校验位停止位。例如,一个典型的ModBus RTU帧(8数据位,无校验,1停止位)有1起始位+8数据位+1停止位=10位。若波特率为115200,则每位的传输时间为$1/115200$秒,一个10位帧的传输时间约为86.8μs。 ### 2. 优化数据帧 - **减少数据帧长度**:只请求必要的数据。例如,避免使用功能码01(读线圈状态)读取整个寄存器,而只读取需要的部分。 - **合并多个请求**:使用功能码23(读写多个寄存器)在一个请求中完成读写操作,减少交互次数。 - **使用紧凑的数据表示**:例如,使用功能码16(写多个寄存器)时,尽量连续写入多个寄存器,而不是分多次写入。 一个ModBus RTU帧的结构如下(以请求为例): ``` [地址][功能码][数据][CRC校验] ``` 其中,地址1字节,功能码1字节,数据长度可变,CRC校验2字节。因此,最小帧长度为4字节(如读单个寄存器)。 ### 3. 调整轮询策略 - **优化轮询顺序**:根据实时性要求,对高优先级的数据进行更频繁的轮询。 - **使用事件触发**:如果从站支持,可以在数据变化时主动上报(但ModBus RTU标准是主从模式,从站不能主动发送,因此需要扩展协议或使用ModBus TCP)。 - **减少轮询间隔**:但需注意不要过度增加主站负担。 ### 4. 硬件优化 - 使用更高性能的微控制器,提高处理速度。 - 确保RS-485接口电路设计合理,包括终端电阻(通常为120Ω)匹配,避免信号反射。 - 使用质量好的线缆,并限制通信距离(RS-485标准通信距离最长为1200米,但实际应用中高波特率下距离会缩短)。 ### 5. 网络拓扑优化 - 减少从站数量:如果从站过多,可以考虑分段管理,使用多个主站或网关。 - 缩短通信距离:尽量将主站放置在靠近从站群中心的位置。 ### 6. 错误处理与重传机制优化 - 合理设置超时时间:避免因等待超时过长而影响实时性。 - 限制重传次数:避免在通信故障时无限制重试。 ### 示例:计算波特率提升带来的效果 假设原波特率为9600bps,帧长度为10字节(80位,加上起始、停止等,实际传输位数约为10位/字节,即100位)。则传输一帧需要的时间为: $$ T_1 = \frac{100}{9600} \approx 10.4 \text{ms} $$ 若提升115200bps,则: $$ T_2 = \frac{100}{115200} \approx 0.868 \text{ms} $$ 传输时间大幅降低。 但是,实际通信中还包括处理时间、线路延迟等。因此,综合优化才能达到最佳效果。 注意:在提高波特率的同时,必须确保整个通信链路的设备(包括所有从站)都支持相同的波特率设置。 §§相关问题§§ 1. 如何测试ModBus RTU通信的实时性能? 2. ModBus RTU协议中,如何实现从站主动上报数据? 3. 在长距离通信中,如何保证高波特率下的通信可靠性? 4. ModBus RTU与ModBus TCP在实时性上有何差异?</think>### 优化 ModBus RTU 实时通信性能的方法 #### 1. **提升物理层传输效率** - **提高波特率**:在抗干扰能力允许范围内,将波特率从 9600bps 提升115200bps 或更高,可减少单帧传输时间[^1]。 传输时间计算: $$ T_{\text{frame}} = \frac{(8N_{\text{byte}} + 11) \times 10^6}{\text{Baud Rate}} \ \mu\text{s} $$ ($N_{\text{byte}}$为字节数,11为帧头/校验位) - **优化线缆与拓扑**: - 使用屏蔽双绞线(如 CAT6),长度 ≤ 1000 米 - 总线两端添加 120Ω 终端电阻 - 采用星型拓扑避免信号反射 #### 2. **协议层优化** - **帧结构压缩**: - 缩短从站地址(7位寻址模式) - 使用紧凑数据格式(如将浮点数转为整型) - **批处理请求**: ```python # 传统单点读取 vs 批量读取 read_single(addr=40001) # 耗时 T1 read_multiple(addr=40001, count=10) # 耗时 T1+ε << 10×T1 ``` - **调整超时参数**: - 响应超时 $T_{\text{resp}}$ 设为 1.5×理论最大帧传输时间 - 帧间隔 $T_{\text{idle}} \geq 3.5T_{\text{char}}$($T_{\text{char}}$为字符时间) #### 3. **主站调度策略** - **优先级轮询**: ```mermaid graph TD A[主站] --> B{数据分类} B -->|高实时性| C[10ms轮询] B -->|普通数据| D[100ms轮询] B -->|事件数据| E[从站触发上报] ``` - **非阻塞通信**: 使用 DMA 传输减少 CPU 占用,中断响应时间 ≤ 50μs #### 4. **从站优化** - **预缓存数据**:从站预先读取 I/O 状态,减少请求响应延迟 - **事件驱动上报**(需协议扩展): - 定义异常报告功能码(如 0x2B) - 从站主动发送异常数据帧 #### 5. **错误处理增强** - **动态重试机制**: - 首次失败:延时 $T_{\text{retry1}} = 5\text{ms}$ 重发 - 二次失败:延时 $T_{\text{retry2}} = 20\text{ms}$ 重发 - **CRC 校验加速**:使用查表法替代实时计算,提速 4-8 倍 #### 6. **性能测试指标** | 参数 | 优化前 | 优化目标 | |---------------|----------|------------| | 单帧延时 | 20-100ms | < 5ms | | 总线利用率 | 30-40% | > 70% | | 抖动(Jitter) | ±15ms | < ±2ms | > **实施建议**:先通过示波器分析实际通信波形(如帧间隔时间),再针对性调整参数[^2]。工业环境下推荐波特率 115200bps + 事件上报扩展方案。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值