在我的应用程序中,我经常调用一个返回json字符串的外部api.
$url = 'api.example.com/xyz';
$blah = json_decode( file_get_contents( $url ) );
Run Code Online (Sandbox Code Playgroud)
但在某些情况下,我得到了
PHP致命错误:允许的内存大小xxx字节耗尽(试图分配32个字节)...
我无法控制外部API,当然我可以增加php的内存,但这有一些缺点.
1-无论我设定的尺寸如何,仍然可能太少.2-如果我将内存大小设置为"无限",那么我可能会冒着杀死我的服务器的风险.
理想情况下,我想在调用json_decode(...)之前"检查"该字符串会导致内存耗尽.
那可能吗?
如果他们设法耗尽服务器的内存,你必须得到一些大规模的JSON响应.以下是一些包含多维关联数组的1 MB文件的度量标准(包含为进入具有不同数据类型的三个MySQL表而准备的数据).
当我include和文件作为数组加载到内存中时,我的内存使用量变为9 MB.如果我获得原始数据file_get_contents(),则需要1 MB内存.然后,PHP数组strlen()与数据的比率大约为1:9 (最初输出为var_export()).
当我运行时json_encode(),峰值内存使用量不会增加.(PHP以块的形式分配内存,因此通常会有一些开销,在这种情况下足以包含JSON的字符串数据;但它可能会使您更多地阻塞一个块.)生成的JSON数据作为字符串需要670 KB.
当我将JSON数据加载file_get_contents到字符串中时,它需要0.75 MB的内存.当我运行json_decode()它时,它需要7 MB的内存.然后我会因子为1:10的最小比率JSON-数据bytesize解码以天然PHP阵列或对象为RAM的要求.
要在解码之前对JSON数据运行测试,您可以执行以下操作:
if (strlen($my_json) * 10 > ($my_mb_memory * 1024 * 1024)) {
die ('Decoding this would exhaust the server memory. Sorry!');
}
Run Code Online (Sandbox Code Playgroud)
... $my_json原始JSON响应在哪里,$my_mb_memory是您分配的RAM,它被转换为字节以与传入数据进行比较.(当然,您也可以使用intval(ini_get('memory_limit'))内存限制作为整数.)
如下所述,RAM的使用还取决于您的数据结构.相比之下,一些更快的测试用例因为我很好奇自己:
所以你的实际内存里程可能会有很大差异.另外要注意的是,如果你在圈子中传递大量数据并做一些这样的事情,你的内存使用量可能会比json_decode()单独产生的更多(或指数级,取决于你的代码经济性).
要调试内存使用情况,您可以在代码中使用memory_get_usage()和/或memory_get_peak_usage()以主要间隔记录或输出代码不同部分中使用的内存.
如果 JSON 文件太大,您可以使用基于事件的 JSON 解析器(如https://github.com/salsify/jsonstreamingparser )处理任意大小的 JSON 文件,而不是简单地退出。一次只会将一小部分对象/数组加载到内存中。
如果您对 JSON 文件有任何影响,请请求或更改它以JSON Lines格式重新格式化,以便可以使用任何普通 JSON 解析器逐行处理。
| 归档时间: |
|
| 查看次数: |
10939 次 |
| 最近记录: |