コードをコピーします コードは次のとおりです:
function binsearch(&$arr, $key, $value)
{
$low = 0;
$high = count($arr); $low < ;= $high) {
$mid = Floor($low + ($high - $low) / 2);
$item = $arr[$mid][$key]; = $value ) {
return $mid;
} else if ($value > $item) {
$low = $mid + 1; else {
$high = $mid - 1; return false;
}
ここでは、整数のオーバーフローを防ぐために、$mid は最初に減算してから加算することによって計算されます。複雑にするつもりはありませんでした。
テストには次のコードを使用しました:
コードをコピー
コードは次のとおりです:
$data = array(); for ($i = 0; $i { $data[] = array("sq" => $i * 2);
}
var_dump($data, "sq", 10000)); binsearch を実行すると、常に約0.2秒かかります。理論的には、100 万のデータを最大 20 回循環できます。どうしてこんなに遅いのでしょうか?
後でメモリを監視したところ、データ配列が 230M のメモリを占有していることがわかりました。 binsearch を実行すると、60K のメモリが占有されました。ただし、理論的には、binsearch
はそれほど多くのメモリを消費しないはずです。なぜなら、参照を使用しており、データ構造をまったく変更していないからだと思います。
その後、参照パラメータを削除したところ、参照に多くの CPU リソースが消費されたようで 0.0002 秒しかかかりませんでした。
PHP は内部的にコピーオンライトの原則に従います。実際、この参照は冗長です。
しかし、参照を追加すると速度が低下するのはなぜでしょうか?今日はこの問題に焦点を当てます。真実を理解した後は、誰もが引用符の使い方を知る必要があります。
binsearch を呼び出す前に $a = &$data を直接設定すると、この参照の速度が非常に速くなります。この問題は参照自体が原因ではないようです。
この質問は実際には、zend エンジンが PHP 変数をどのように管理するかに関するものです。
最初に次の質問を見てください:
コードをコピーします
コードは次のとおりです:
function Demon(&$a, &$b) { $a =& $b;
$a = 1;
$b = 3; print $a;>はい、2です。でも、最初は3だと思いました。 それでは、上記の問題をどのように説明すればよいでしょうか? 実際、関数のパラメータ参照は次のように動作します。
コードをコピーします
コードは次のとおりです:
$a1 = &$tmp = $tmp;
ここで、参照は実際には一時変数です。このとき、$tmp には参照属性がありますが、$a 変数には参照属性がありません。
Zend エンジンのメモリ管理方法によれば、内部的には zval で表すことができず、この zval を強制的に分離する必要があります。
この理解方法を使用すると、上記の問題は解決されます。関数内では関数外の基準特性は変更されません。これは、PHP
が calltime_by_ref の使用をサポートせず、上記の非効率的なコピー方法を選択する理由でもあります。
次の分析は、パラメーターを渡すときにコピーが実際に発生することを証明することもできます。
binsearch関数の内部。
$data[0] = 1;
このようにして、$data が配置されている zval のコピーが作成されます。メモリ使用量は60Kです。関数呼び出しや参照と全く同じです。
なぜ 230M も増えないのかと疑問に思う人もいるかもしれません。これが PHP の優れた点です。配列 Key は zval ポインターに対応します。 (内部的にはハッシュテーブルです)
したがって、これらのポインターを一度コピーするだけで、データをコピーする必要はありません。ただし、100 万の PHP ハッシュ テーブルは実際には 50M のメモリを占有します。なぜ60Kしかないのですか? binsearch 関数の外で、
コードをコピーします。 コードは次のとおりです。
案の定、メモリが 60K 増加しました。おそらく、PHP のメモリ管理メカニズムに関連していると思われます。
これですべてが明らかになりました!今日、私はそれを理解するまでに数時間考えましたが、あえてそれを自分の中に留めておくつもりはありませんでした。
関数内の参照は、パラメータを便利に渡すためのものではなく、関数が複数の戻り値を持つことができることを理解するためのものであるため、不必要な詳細を追加しないことが最善です。
実際、リファレンスを使用するとパフォーマンスが低下します。
http://www.bkjia.com/PHPjc/321529.htmlwww.bkjia.comtruehttp://www.bkjia.com/PHPjc/321529.html技術記事次のようにコードをコピーします: function binsearch( $high = count($arr); while ($low = $high) { $mid = Floor($low + ($high - $low) / 2); $item = $ arr [$mid][$key] if ($item == $value) {...