You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:09:48