PHP7.4+CI4.19内存耗尽错误,调整php.ini后仍未解决
PHP7.4 + CodeIgniter4.19 读取小文件触发内存耗尽问题解决
问题现象
读取一个小于14MB的GeoJSON文件时,触发以下内存耗尽错误:
Fatal error: Allowed memory size of 157286400 bytes exhausted (tried to allocate 20480 bytes) in /var/www/example.com/development.example.com/app_dir/vendor/codeigniter4/framework/system/Common.php on line 395
以及:
Fatal error: Allowed memory size of 157286400 bytes exhausted (tried to allocate 20480 bytes) in /var/www/example.com/development.example.com/app_dir/vendor/codeigniter4/framework/system/Debug/Exceptions.php on line 154
当前已做配置
已修改php.ini并重启Apache2,配置如下:
memory_limit = 150M post_max_size = 150M
相关业务代码
public function ski_index() { helper("filesystem"); // Read the JSON file $json = file_get_contents(WRITEPATH.'/ski/raw_data/ski_areas.geojson'); // Decode the JSON file to an array $array_data = json_decode($json,true); // for the view $this->data['array_data'] = $array_data; // $new_array will collected filtered ski resorts by country $new_array = array(); $j=1; foreach ($array_data['features'] as $value){ // if isset and filter by country if (isset($value['properties']['location']['iso3166_1Alpha2']) && $value['properties']['location']['iso3166_1Alpha2'] == 'JP'){ array_push($new_array, $value); $j++; } } // reconstruct by putting the array into FeatureCollection $reassemble_data = array ('type'=>'FeatureCollection', 'features'=>$new_array); // convert it back to json/geojson $this->data['new_array'] = json_encode($reassemble_data); //write out to new file $file_content = $this->data['new_array']; if (!write_file(WRITEPATH."/ski/filtered_data/japan_ski_resorts.geojson", $file_content)){ echo "Error - cannot write to path"; } else { echo "Success - written to file"; } return view('/Admin/Ski/ski_index', $this->data ); }
解决方法
- 验证配置是否生效:在代码开头添加
echo ini_get('memory_limit'); exit;,确认当前PHP进程实际使用的内存限制是否为150M。如果不是,排查是否修改了错误的php.ini文件(CLI和Web环境可能用不同配置)。 - 临时提升内存限制:在方法开头添加
ini_set('memory_limit', '256M');,绕过配置文件限制,快速验证是否是内存配额不足导致的问题。 - 移除不必要的内存占用:如果视图不需要原始的
$array_data,直接删除$this->data['array_data'] = $array_data;这行代码,避免将整个大数组保留在内存中。 - 及时释放无用变量:在完成数组过滤后,添加
unset($json, $array_data);,手动释放不再使用的变量内存。 - 流式处理JSON(推荐):不要一次性读取整个文件到内存,使用PHP的
JsonReader类流式解析JSON,逐行处理Feature数据,避免加载完整的大数组。示例代码片段:$reader = new \JsonReader(); $reader->open(WRITEPATH.'/ski/raw_data/ski_areas.geojson'); $new_array = []; while ($reader->read()) { if ($reader->name === 'features' && $reader->type === \JsonReader::ARRAY) { while ($reader->read()) { if ($reader->type === \JsonReader::OBJECT) { $feature = $reader->value; if (isset($feature['properties']['location']['iso3166_1Alpha2']) && $feature['properties']['location']['iso3166_1Alpha2'] === 'JP') { $new_array[] = $feature; } } } break; } } $reader->close(); $reassemble_data = ['type' => 'FeatureCollection', 'features' => $new_array]; - 检查调试模式影响:如果开启了CodeIgniter调试模式,框架会保留更多错误日志和堆栈信息,额外占用内存。可临时修改
.env中的CI_ENVIRONMENT = production关闭调试模式测试。
内容的提问来源于stack exchange,提问作者spreaderman
相关产品推荐
相关产品推荐

