Ubuntu 14.04使用OpCache提升PHP5.5+程序性能

概述


PHP 5.5以后内建了OpCache,OpCache的加速原理是把编译后的bytecode存储在内存里面, 避免重复编译 PHP 所造成的资源浪费.Ubuntu 14.04默认自带 PHP 5.5.9,已经集成了这个功能。但是默认是不启用的。

启用


修改 php.ini 文件

在文件最后面加入:

重启服务器

效果


加速效果极端明显,强烈建议启用这个功能。

Ubuntu14.04升级到Ubuntu16.04出现错误

Ubuntu14.04升级到Ubuntu16.04出现错误,如下图所示:
from_ubuntu_14_upgrade_ubuntu_16_error
如果机器上安装了postgresql,则是由于postgresql处于升级黑名单中,因此无法升级。
一般建议手工卸载postgresql

卸载完成后继续执行升级命令

具体参考这个BUG的链接:
postgresql packages in the removal blacklist making it hard to upgrade

Ubuntu 14.04编译安装Apache 2.4.20

1.安装开发工具包

2.下载Apache 2.4.20的源代码

3.安装apr依赖库

4.安装pcre

5.解压缩代码

6.配置并编译

参考链接


Ubuntu 14.04系统WordPress 4.5升级到PHP7之后执行插件升级报错“无法定位WordPress内容目录(wp-content)”

Ubuntu 14.04系统上WordPress 4.5升级到PHP7之后执行插件升级报错,

如下图所示:WordPres_wp-content

这个是由于PHP升级之后,有些函数的支持出现了变化,导致调用失败。

目前已知的修复方法是修改wp-admin/includes/class-wp-filesystem-ssh2.php中的如下的几个函数:

修改为:

参考链接


Work around PHP7 php-ssh2 breakage

Ubuntu 14.04(64位)编译安装PHP7.0.5后编译安装libssh2-php

在使用Ubuntu 14.04(64位)源码编译安装PHP7并配置Apache2支持之后,无法直接通过命令安装libssh2-php,因此需要手工编译安装。

1.安装编译libssh2-php需要的依赖库

2.下载libssh2-php的源代码

3.解压缩文件

4.切换到目录

5.使用phpize配置插件编译环境

6.配置编译环境

7.编译并安装

执行之后,文件被安装到了/opt/php-7.0.5/lib/php/extensions/no-debug-zts-20151012目录下面。

8.配置php.ini加载插件

找到如下内容

在最下面增加

9.重启Apache2加载动态模块

gl接口耗时?

调用glclear接口,发现它耗时比较长,翻了翻stackoverflow。

Measuring the elapsed time of an OpenGL API call is mostly meaningless.

研究OpenGL接口的耗时是无意义的。

Asynchronicity

The key aspect to understand is that OpenGL is an API to pass work to a GPU.

The easiest mental model (which largely corresponds to reality) is that when you make OpenGL API calls, you queue up work that will later be submitted to the GPU. For example, if you make a glDraw*() call, picture the call building a work item that gets queued up, and at some point later will be submitted to the GPU for execution.

In other words, the API is highly asynchronous. The work you request by making API calls is not completed by the time the call returns. In most cases, it's not even submitted to the GPU for execution yet. It is only queued up, and will be submitted at some point later, mostly outside your control.

A consequence of this general approach is that the time you measure to make a glClear() call has pretty much nothing to do with how long it takes to clear the framebuffer.

Synchronization

Now that we established how the OpenGL API is asynchronous, the next concept to understand is that a certain level of synchronization is necessary.

Let's look at a workload where the overall throughput is limited by the GPU (either by GPU performance, or because the frame rate is capped by the display refresh). If we kept the whole system entirely asynchronous, and the CPU can produce GPU commands faster than the GPU can process them, we would be queuing up a gradually increasing amount of work. This is undesirable for a couple of reasons:

  • In the extreme case, the amount of queued up work would grow towards infinity, and we would run out of memory just from storing the queued up GPU commands.
  • In apps that need to respond to user input, like games, we would get increasing latency between user input and rendering.

To avoid this, drivers use throttling mechanisms to prevent the CPU from getting too far ahead. The details of how exactly this is handled can be fairly complex. But as a simple model, it might be something like blocking the CPU when it gets more than 1-2 frames ahead of what the GPU has finished rendering. Ideally, you always want some work queued up so that the GPU never goes idle for graphics limited apps, but you want to keep the amount of queued up work as small as possible to minimize memory usage and latency.

Meaning of Your Measurement

With all this background information explained, your measurements should be much less surprising. By far the most likely scenario is that your glClear() call triggers a synchronization, and the time you measure is the time it takes the GPU to catch up sufficiently, until it makes sense to submit more work.

Note that this does not mean that all the previously submitted work needs to complete. Let's look at a sequence that is somewhat hypothetical, but realistic enough to illustrate what can happen:

  • Let's say you make the glClear() call that forms the start of rendering frame n.
  • At this time, frame n - 3 is on the display, and the GPU is busy processing rendering commands for frame n - 2.
  • The driver decides that you really should not be getting more than 2 frames ahead. Therefore, it blocks in your glClear() call until the GPU finished the rendering commands for frame n - 2.
  • It might also decide that it needs to wait until frame n - 2 is shown on the display, which means waiting for the next beam sync.
  • Now that frame n - 2 is on the display, the buffer that previously contained frame n - 3 is not used anymore. It is now ready to be used for frame n, which means that the glClear()command for frame n can now be submitted.

Note that while your glClear() call did all kinds of waiting in this scenario, which you measure as part of the elapsed time spent in the API call, none of this time was used for actually clearing the framebuffer for your frame. You were probably just sitting on some kind of semaphore (or similar synchronization mechanism), waiting for the GPU to complete previously submitted work.

Conclusion

Considering that your measurement is not directly helpful after all, what can you learn from it? Unfortunately not a whole lot.

If you do observe that your frame rate does not meet your target, e.g. because you observe stuttering, or even better because you measure the framerate over a certain time period, the only thing you know for sure is that your rendering is too slow. Going into the details of performance analysis is a topic that is much too big for this format. Just to give you a rough overview of steps you could take:

  • Measure/profile your CPU usage to verify that you are really GPU limited.
  • Use GPU profiling tools that are often available from GPU vendors.
  • Simplify your rendering, or skip parts of it, and see how the performance changes. For example, does it get faster if you simplify the geometry? You might be limited by vertex processing. Does it get faster if you reduce the framebuffer size? Or if you simplify your fragment shaders? You're probably limited by fragment processing.

 

OpenGL是GPU的API

API call是以eventloop的形式工作

但需要一定的同步工作,任务数量太多,延迟会变大,开发者又需要尽快响应用户,GPU需要跟CPU保持一定过得同步。简单的来说,如果CPU发出的绘制指令超出GPU太多(1-2帧),GPU会锁住CPU。

在这个背景下,就可以解释为什么glClear耗时了,因为它触发了一次同步。

已3个缓冲区为例,n-3在绘制,n-2在合成,The driver decides that you really should not be getting more than 2 frames ahead。glClear就会block住,直到GPU工作完。

GPU工作渲染完n-2,glClear就会提交n。

最终结论,绘制太慢导致的。

可以看看CPU消耗,看看是不是CPU被锁住了。

Ubuntu 14.04(64位)源码编译安装PHP7并配置Apache2支持

下载PHP7源代码


解压缩到当前目录


安装编译需要的依赖


安装libxml2-dev

安装gcc

安装依赖的库

安装apache2-dev,否则无法指定--with-apxs2=/usr/bin/apxs来生成libphp7.so

切换到编译目录

配置并编译


配置开启php-fpm支持,开启多线程支持--enable-maintainer-zts,否则无法使用Apache2Event MPM功能。

配置并安装PHP7


拷贝PHP7的配置文件


设置PHP7的配置文件php.ini


PHP7已经默认加载opcache.so了,因此不需要声明zend_extension=opcache.so.

启用Apache2PHP7模块


启用Apache2Event模块


参考链接


ubuntu 14.04上源码编译安装php7
How to install PHP 7 as PHP-FPM & FastCGI for ISPConfig 3 on Debian 8 (Jessie)

Ubuntu 12.04升级到Ubuntu 14.04导致Apache2从2.2升级到2.4.10版本PHP服务器的重新修正

现象


服务器已经根据Ubuntu 12.04下安装配置Worker工作模式的Apache 支持PHP设置成了Worker模式,但是当系统从Ubuntu 12.04升级到Ubuntu 14.04导致Apache22.2升级到2.4.10版本后,而MPM模块被还原为prefork模式,导致大量的Apache2进程被创建出来,时间稍微一长,系统出现大量的OOM记录,直到系统最后宕机。

Ubuntu 14.04下查看所有可用的MPM模块,命令如下:

查看当前正在使用的MPM模块,命令如下:

可以看到,目前正在使用的模块就是prefork模块。

使用apachectl -V | grep -i mpm可以更加清晰的打印出当前使用的模块

注意,在Ubuntu 14.04下执行apache2 -l命令与Ubuntu 12.04下面的输出结果是不同的,Ubuntu 14.04下如果使用prefork模块输出的信息如下:

默认情况下Ubuntu 14.04中的PHP默认是没有线程安全支持,如果使用mpm_event支持的话,会提示如下信息:

修复方式


1.重新安装系统升级过程中可能会被移除的PHP-FPM模块

2.关闭Apache2内建的PHP支持,开启Apache2的FastCGI,PHP5-FPM支持

3.修改PHP5-FPM的配置文件

找到

修改为:

注意,上面修改了四处地方,listen,listen.owner,listen.group,listen.mode
注意,如果提示如下错误:

则说明listen.owner,listen.group,listen.mode这三行没有打开。
4.重启PHP5-FPM服务

5.切换Apache2Event-MPM模式

6.启用Apache2cache,expire,gzip模块,加强服务器性能

7.卸载libapache2-mod-php5,否则每次这个模块更新之后,都会导致apache2被自动切换到mpm_prefork模式

8.调整配置文件

Apache 2.4.10的配置文件如果按照Apache 2.2的配置文件的话,是没办法启用PHP-FPM的,Apache 2.4.10版本使用SetHandler的方式支持PHP-FPM是改动最少的一种方式了。

找到

调整为如下:

同理,调整HTTPS的配置文件。

9.重启Apache2服务

参考链接


WORDPRESS 4.5 后台/登录页面强制HTTPS

这段时间貌似服务器经常被人攻击,由于服务器已经支持HTTPS登陆,而全站SSL加密又不是那么迫切,遂考虑后台SSL加密,强制HTTPS。
设置方法如下:
修改wp-config.php

之前(貌似放在后面也可以),加

就能使得后台强制加密了;
而加入一行

就可以使登录页面强制加密了。

Ubuntu 14.04 关闭PHP服务器上返回的X-Powered-By信息

最近在分析网站性能的时候,发现服务器返回了"X-Powered-By"字段,这个字段中携带了PHP的版本号,系统的版本号。如下图:
X-Powered-By

而出于安全考虑,这两个信息是不应该被返回给客户端的。

Ubuntu 14.04下服务器禁止返回"X-Powered-By"的设置如下:
对于使用Apache2内置PHP的服务器,则需要修改Apache2对应目录下的配置文件

对于使用PHP-FPM调度的服务器,则需要同时修改PHP-FPM,FastCGI对应目录下的配置文件

找到

把其中的expose_php = On调整为:expose_php = Off,调整后的结果如下:

接下来,重启Apache2

重启PHP-FPM,如果配置了的话。

再次请求服务器后,发现"X-Powered-By"已经不会再返回了。

X-Powered-By-Off