使用 memory_limit 限制 PHP 进程的内存使用

更新日期: 2017-03-01 阅读次数: 8918 分类: PHP

memory_limit 顾名思义,即限制 PHP 进程对于内存的使用。例如:

magento2 的系统要求里有关于 PHP memory_limit 的限制,不能低于 512M。(默认值为 128M, 如果不更改,会导致 magento 的后台处理逻辑无法正常执行)

看一下 PHP 官网的解释

This sets the maximum amount of memory in bytes that a script is allowed to allocate. This helps prevent poorly written scripts for eating up all available memory on a server. Note that to have no memory limit, set this directive to -1.

需要注意的是,memory_limit 的值越高,即单个 PHP 进程占用的内存越多,系统能够并发处理的请求越少。例如,一个 2G 内存的机器

  • memory_limit 设为 128M, 则同时最多能处理 16 个请求
  • memory_limit 设为 256M, 则同时最多能处理 8 个请求
  • memory_limit 设为 512M, 则同时最多能处理 4 个请求

memory_limit 的值是越大越好么?

当然不是,memory_limit 主要是为了防止程序 bug, 或者死循环占用大量的内存,导致系统宕机。在引入大量三方插件,或者代码时,进行内存限制就非常有必要了。

memory_limit 会使每个 PHP process 都占用固定的内存?

还是仅仅为分配内存的上限?测试一下

思路,memory_limit 设置为 10M, PHP 请求中初始化一个 2M/20M 的字符串,看看系统进程中内存的占用情况。

Nginx 配置

server {
        listen 8093;

        root /home/zhongwei/work/test/memory_limit/;
        index index.php index.html index.htm;

        server_name localhost;

        location / {
                # try_files $uri $uri/ =404;
                try_files $uri $uri/ /index.php?q=$uri&$args;
        }

        location ~ \.php$ {
		include snippets/fastcgi-php.conf;
		fastcgi_param PHP_VALUE "memory_limit = 10M";
		fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }
}

PHP 测试文件

<?php

$char_count = 2;
$M = 1024 * 1024;

echo sprintf("Current memory_limit value is: %s.", ini_get('memory_limit'));
echo sprintf('<br/>Amount of memory allocated to PHP: %0.3fM.', memory_get_usage() / $M);
$s = str_repeat("a", $M * $char_count);
//sleep(30);
echo sprintf('<br/>Amount of memory allocated to PHP: %0.3fM.', memory_get_usage() / $M);
echo sprintf('<br/>Total memory allocated from system: %0.3fM.', memory_get_usage($real_usage=true) / $M);
echo '<br/>success';

测试结果

$char_count 为 2 时,即初始化一个占用内存 2M 的字符串,输出结果为

Current memory_limit value is: 10M.
Amount of memory allocated to PHP: 0.344M.
Amount of memory allocated to PHP: 2.348M.
Total memory allocated from system: 4.004M.
success

$char_count 为 20 时,即初始化一个占用内存 20M 的字符串,输出结果为

Current memory_limit value is: 10M.
Amount of memory allocated to PHP: 0.346M.

注意,HTTP 状态码为 500, 也就是说执行到字符串初始化的时候,PHP 进程被系统干掉了。

看一下 Nginx error.log 中记录的日志信息

2017/03/01 10:41:23 [error] 6903#6903: *39 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Allowed memory size of 10485760 bytes exhausted (tried to allocate 20971552 bytes) in /home/zhongwei/work/test/memory_limit/index.php on line 8
PHP message: PHP Stack trace:
PHP message: PHP   1. {main}() /home/zhongwei/work/test/memory_limit/index.php:0
PHP message: PHP   2. str_repeat() /home/zhongwei/work/test/memory_limit/index.php:8" while reading response header from upstream, client: 127.0.0.1, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://unix:/run/php/php7.0-fpm.sock:", host: "localhost:8093"

实际测试结果说明,memory_limit 只是限制了每个 PHP 进程的内存占用上限,而不是为每个进程分配了固定的内存。所以,并不会因为 memory_limit 设置越大,导致并发数出现降低。

memory_limit 的默认值为多少

  • PHP 5.2 之前为 8M
  • PHP 5.2 为 16M
  • PHP 5.2 之后的版本为 128M

参考

领取阿里云/腾讯云服务器优惠券

关于作者

我是来自山东烟台的一名开发者,喜欢瞎折腾,顺便记记笔记。有敢兴趣的话题,欢迎加微信 zhongwei 聊聊。 白天写程序,晚上哄熊孩子,可能回复有点慢,见谅。 查看更多联系方式

相关文章

爱评论不评论

近期节日

2020年04月11日 世界帕金森病日
2020年04月19日 谷雨
2020年04月21日 复活节
2020年04月22日 世界地球日
2020年04月23日 世界读书日
2020年04月26日 知识产权日
2020年04月30日 佛诞
2020年04月30日 全国交通安全反思日
2020年05月01日 国际劳动节
2020年05月04日 五四青年节
2020年05月05日 立夏
2020年05月08日 世界红十字日
查看更多节日