使ったソースは以下です。
<?php /** * メモリ使用量をKB表記で返す * * @return string */ function peak_usage() { return (memory_get_peak_usage(true) / 1024).'KB'.PHP_EOL; } // 100要素数の配列を作る // 各要素には ['a', 'b', 'c'] が入る $array = []; for($i = 0; $i < 100; $i++) { $array[] = ['a', 'b', 'c']; } // もう一つ適当に配列を作る $array2 = ['x' => 'X', 'y' => 'Y']; // $array * $array2 を反復を 100 回行う // $array * $array2 の反復の中で即時 continue 2 する for($i = 0; $i < 100; $i++) { if ($i % 10 === 0) { echo php_sapi_name() === 'cli' ? peak_usage() : nl2br(peak_usage()); } foreach ($array as $key => $value) { foreach ($array2 as $key2 => $value2) { continue 2; } } }まずは、PHP 5.4 (OS X Mavericks) で確認してみます。
$ php -v PHP 5.4.24 (cli) (built: Jan 19 2014 21:32:15) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.4.0, Copyright (c) 1998-2013 Zend Technologiesブラウザからアクセス (ビルトインサーバーで実行)
512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KBコマンドラインから実行
512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KB結果に違いはありませんでした。
次に、PHP 5.5 (Vagrant x Ubuntu 13.10) で確認してみます。
$ php -v PHP 5.5.12-2+deb.sury.org~saucy+1 (cli) (built: May 12 2014 13:45:47) Copyright (c) 1997-2014 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans with Zend OPcache v7.0.4-dev, Copyright (c) 1999-2014, by Zend Technologies $ apache2 -v Server version: Apache/2.4.9 (Ubuntu) Server built: Apr 1 2014 08:58:43ブラウザからアクセスした結果 (Apacheで実行)
512KB 768KB 1280KB 1536KB 2048KB 2304KB 2816KB 3072KB 3584KB 3840KBコマンドラインから実行した結果
512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KB 512KBブラウザからアクセスした時に、かなり増えました。ちなみに "continue 2" の箇所をコメントアウトすると、ブラウザからアクセスした時も、ずっと "512KB" のままになりました。
Stack Overflowに以下の投稿が見つかり、"Zend OPcache"に関することが書かれています。
http://stackoverflow.com/questions/23231675/php-5-5-memory-leak-when-using-continue-2-inside-two-foreach-loops
2014-07-11 追記: PHP本家にも報告されていました。
https://bugs.php.net/bug.php?id=67111
再現条件は良くわかりませんが、Zend OPcacheのバグっぽいですね。
尚、foreach()している箇所をwhile()に変えたら、増加は発生せず、ずっと"512KB"となりました。応急処置するなら、この方法ですかねぇ。
reset($array); while (list($key, $value) = each($array)) { reset($array2); while (list($key2, $value2) = each($array2)) { continue 2; } }
No comments:
Post a Comment