在我的应用中,我经常调用一个返回json字符串的外部api。
$url = 'api.example.com/xyz'; $blah = json_decode( file_get_contents( $url ) );
但是在某些情况下
PHP致命错误:内存中已耗尽xxx字节(尝试分配32字节)的内存大小…
我无法控制外部API,当然可以增加php的内存,但这有一些缺点。
1-无论我设置的大小,仍然可能太小。2-如果将内存大小设置为“ infinite”(无限),则可能会导致服务器被杀。
理想情况下,我想在调用json_decode(…)之前先“检查”字符串是否导致内存耗尽。
那可能吗?
如果它们设法耗尽服务器的内存,则必须获得大量的JSON响应。以下是一些指标,这些指标包含一个包含多维关联数组的1 MB文件(包含准备输入到具有不同数据类型的三个MySQL表中的数据)。
当我include和文件作为数组加载到内存中时,我的内存使用量达到9 MB。如果我使用来获取原始数据file_get_contents(),则它需要1 MB的内存。然后,PHP数组strlen()与数据的比率大约为1:9 (最初以输出var_export())。
include
file_get_contents()
strlen()
var_export()
当我运行时json_encode(),峰值内存使用不会增加。(PHP在块中分配内存,因此通常会产生一些开销,在这种情况下,足够包含JSON的字符串数据;但是它可能会使您增加一个块。)作为字符串的结果JSON数据需要670 KB。
json_encode()
当我将JSON数据加载file_get_contents到字符串中时,它需要0.75 MB的内存。当我json_decode()在其上运行时,它需要7 MB的内存。然后,对于RAM需求,我将解码的 JSON数据字节大小 与 本机PHP数组或对象 的最小比率为1:10 。
file_get_contents
json_decode()
要在解码之前对JSON数据进行测试,您可以执行以下操作:
if (strlen($my_json) * 10 > ($my_mb_memory * 1024 * 1024)) { die ('Decoding this would exhaust the server memory. Sorry!'); }
…其中$my_json是原始JSON响应,$my_mb_memory是分配的RAM,已转换为字节以与传入数据进行比较。(当然,您也可以使用intval(ini_get('memory_limit'))整数来获取内存限制。)
$my_json
$my_mb_memory
intval(ini_get('memory_limit'))
如下所述,RAM的使用也将取决于您的数据结构。相比之下,还有一些快速测试用例,因为我很好奇自己:
因此,您的实际RAM里程可能会相差很大。 还应注意,如果您绕一圈传递大量数据并进行一些操作,那么您的内存使用量可能会比json_decode()单独导致的使用量高很多(或成倍地增加,具体取决于您的代码经济性)。
要调试内存使用情况,您可以在代码中使用memory_get_usage()和/或memory_get_peak_usage()间隔很长时间来记录或输出代码不同部分中使用的内存。
memory_get_usage()
memory_get_peak_usage()