本文为原创,转载请注明:http://www.cnblogs.com/gistao/
背景
我们在aws上部署了hhvm,高峰段发现cpu idle降的比较低,只有10-20%,而使用php-fpm的另外一台机器的cpu idle在40-60%,这与hhvm的性能明显不符。
hhvm的cpu截图
分析
使用gperftools和xhprof工具分析函数的CPU耗时分布
gperf截图
xhprof截图
分析发现_addSysInfo函数内竟然调用了一个exec函数,触发了多线程下fork的坑。不过hhvm也已经提供了相应的避免方法:轻进程
HHVM的轻进程
背景
hhvm支持exec函数对应的底层调用是popen,此函数通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程
由于hhvm是多线程的,为了避免fork引起的大量内存copy带来的开销,hhvm设计了轻进程模式,轻进程也就是只有一个线程的意思
设计思路
1.在hhvm启动的时候,此时只有一个线程即主线程,就fork出配置项LightProcessCount个子进程
2.当php脚本执行exec的时候,hhvm主进程不会执行fork
3.hhvm会根据当前worker的线程id %LightProcessCount 得到相应的”子进程标识“,“子进程标识”用于和先前fork出的子进程打交道
4.“子进程标识”传递命令到对应的子进程,继而在子进程里完成exec相应的功能
5.注意每个”子进程标识“有一把锁,如果锁未释放,则当前worker线程会阻塞
6.在子进程完成exec之前,当前worker线程会阻塞
配置
Server {
# Light process has very little forking cost, because they are pre-forked
# Recommend to turn it on for faster shell command execution.
#LightProcessFilePrefix = ./lightprocess
#LightProcessCount =
}
LightProcessCount默认是0,hhvm根据此值建立相应数量的轻进程,如需要,建议和ThreadCount保持以致
LightProcessFilePrefix用于子进程和主进程的通信,即Unix domain socket
例子
配置如下
Server {
#LightProcessFilePrefix = ./light_process
#LightProcessCount =
}
hhvm启动后,会启动10个轻进程
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
gistao 0.0 0.0 ? Ss : : hhvm-HHVM-2.2/hphp/hhvm/hhvm -vServer.LightProcessFilePrefix=./light_process -vServer.LightProcessCount= -m server -vEval.Jit=true -p
同时,在当前运行目录下生成
srwxr-xr-x gistao hhvm Jan : light_process.10470.0
srwxr-xr-x gistao hhvm Jan : light_process.10470.1
srwxr-xr-x gistao hhvm Jan : light_process.10470.2
srwxr-xr-x gistao hhvm Jan : light_process.10470.3
srwxr-xr-x gistao hhvm Jan : light_process.10470.4
srwxr-xr-x gistao hhvm Jan : light_process.10470.5
srwxr-xr-x gistao hhvm Jan : light_process.10470.6
srwxr-xr-x gistao hhvm Jan : light_process.10470.7
srwxr-xr-x gistao hhvm Jan : light_process.10470.8
srwxr-xr-x gistao hhvm Jan : light_process.10470.9