今天小伙伴在群里问了这么一个问题:
![1a4804d320518d5a7b15d6584aa191e4.png](https://i-blog.csdnimg.cn/blog_migrate/0ccdb6ade251ec7b4f43c964528652d4.png)
![4d3fada3e765a1c7e5b210d08700b5f6.png](https://i-blog.csdnimg.cn/blog_migrate/dd6a3e43bd3aba4c1723bd7dbaf6335b.png)
![7727762854a2fc7b9a5a3a9ae04727f1.png](https://i-blog.csdnimg.cn/blog_migrate/22d7bb056775d1048f127d146a912025.png)
![2309d564268c5de74c811d426bcda333.png](https://i-blog.csdnimg.cn/blog_migrate/2a4e0ac9ace7a95d5757a68510b1a753.png)
出现这种情况就是因为内存不足, PHP
程序直接退出了,报错大概如下:
![7b7f021336c6cc0e0b0e826505cb518c.png](https://i-blog.csdnimg.cn/blog_migrate/84fd271cbb3bd716c606da5bafd26903.jpeg)
上图的意思就是说,我们能使用的内存最大是8M,但是处理这个图片还需要额外的41bytes,就会导致内存不足,这是一个很严重的错误。在对图片进行操作前需要将图片的所有信息读入内存中,同时还会使用另一部分内存同于处理计算并缓存输出,所以内存大小的使用还是和图片的大小有关。
PHP
中图片的处理都是使用了 GD
库,这个库提供了很多方法让 PHP
可以更方便地对图片进行操作,支持的图片格式如下:
![76bcfbf2500ff7a502525a58807f2573.png](https://i-blog.csdnimg.cn/blog_migrate/d784beeb11b3283bf4ff1b1b61c39337.jpeg)
回到一开始的问题,那个小伙伴需要处理高分辨的图片,图片大小必然很大,所以就会出现内存不够的情况,解决方法还是有很多的。
1. 设置图片最大可上传的大小
前端上传前可以先检测下大小,如果超过最大值直接就不请求接口,同时为安全起见,后端接收到请求后也要检测大小,防止程序异常退出。
2. 压缩图片
3. 关闭 memory_limit
群里的小伙伴最后使用了一种 简单粗暴的方式 解决了该问题,直接在PHP中关闭 memory_limit
:
set_time_limit(0);
@ini_set('memory_limit','-1');
这样虽然解决了问题,但不优雅也不安全,同样在 php.ini
配置文件中将 memory_limit
的值设置很大也能解决:
memory_limit = 256M
PHP代码中也可以这样设置:
ini_set('memory_limit', '256M');
上面我们将 memory_limit
参数固定了,这就带来一个弊端,因为大多数情况下不需要这么大的内存,有点浪费资源,最好的做法就是根据需要来设置 memory_limit
,我写了一个如下方法可供参考:
public function setMemoryLimit($filename){
// 控制执行时间
set_time_limit(50);
$maxMemoryUsage = 256M;
$width = 0;
$height = 0;
$size = ini_get('memory_limit');
// 获取图片大小
list($width, $height) = getimagesize($filename);
// 计算需要的内存,并转换成'M'单位
// 4 因为png图片一个像素有4字节
// 1.5 是一个调整因子,因为memory_limit不是那么精确
// 详细可以查看: http://php.net/imagecreatefromjpeg#76968
$size = $size + floor(($width * $height * 4 * 1.5 + 1048576) / 1048576);
if ($size > $maxMemoryUsage){
$size = $maxMemoryUsage;
}
// 更新
ini_set('memory_limit',$size.'M');
}
最后说一下,网上说 GD
库是比较耗内存的,但我这里没有做过测试。Github上有个 C
的项目叫 libvips/libvips
:
![0e3885af7fd894e05b12f3990f69b5c7.png](https://i-blog.csdnimg.cn/blog_migrate/6128b0231dd311fcc44d3dd5a08be2aa.jpeg)
![4d94437ed742c7f971e73c05ad412bbe.png](https://i-blog.csdnimg.cn/blog_migrate/747cd0fb13d84d8efdc1b047f0393606.jpeg)
可以在不占用很多内存的情况下提高图片处理的速度,这是地址:https://github.com/libvips/libvips,有时间可以学习下。
以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家 ,需要请戳这里链接 或 者关注咱们下面的知乎专栏PHP架构师圈子zhuanlan.zhihu.com
![ad8ea6afbb3fa7b813aa119d707ff0ab.png](https://i-blog.csdnimg.cn/blog_migrate/1666408763ee7b8573099bd8fae7be8c.jpeg)