No.5ベストアンサー
- 回答日時:
参照が速くない大きな理由の一つは、
$a =& $b;
$c = $a; // ここで値のコピーが発生と思われる
と同じことが、組み込み関数をコールするところで起こってしまうため、
参照の意味が無くなることが多いことだと思います。
提示していただいたベンチマークのコードだと、
is_array, implodeのところで$dataがコピーされていると思います。
関数をコールする都度これが起こると思われるので、
それが速度低下の大きな原因だと思います。
やはり「参照渡しそのものが遅い」わけではないと思います。
ただ、上の理由から、余程注意しないと、「参照渡しを使うと全体として遅くなる」
という結果を招くことは確かだと思います。
また、場合によってはガベコレの影響も大きいようなので、
ベンチマークの時は注意する必要があると思います。
(下のサンプルのガベコレのところを変えるだけで随分違います)
下は本当に差が出るサンプルです。
<?php
// 配列 $array に $data をプッシュしたものを返す関数
function pushed($array, $data)
{
// ここで$arrayを操作するため、
// 実際に$arrayのデータをコピーする必要が生じる。
// ここをコメントアウトすれば、
// $arrayが値渡しであっても、
// $arrayの中身のコピーは起こらない。
$array []= $data;
return $array;
}
// 配列 $array に $data をプッシュする関数
function push(&$array, $data)
{
$array []= $data;
}
$n = 10;
$time = 0;
for ($i = 0; $i < $n; $i++) {
$dat = range(0,99999);
$res = null; // GCの時間を除外するため、ここでGCを起こす
$t = microtime(true);
$res = pushed($dat, null);
$time += microtime(true) - $t;
}
echo "V={$time}\n";
$time = 0;
for ($i = 0; $i < $n; $i++) {
$dat = range(0,99999);
$t = microtime(true);
push($dat, null);
$time += microtime(true) - $t;
}
echo "R={$time}\n";
?>
No.4
- 回答日時:
ベンチマークに使ったコードを実際に見せていただければ、もっと詳しいことが分かると思います。
この回答への補足
function Ufun_implode_recursive ($istr, $data) {
if (is_array ($data)) {
while (list ($key,) = each ($data)) {
$data[$key] = Ufun_implode_recursive ($istr, $data[$key]);
}
$data = implode ($istr, $data);
}
return $data;
}
と
function Ufun_implode_recursive ($istr, &$data) {
if (is_array ($data)) {
while (list ($key,) = each ($data)) {
Ufun_implode_recursive ($istr, $data[$key]);
}
$data = implode ($istr, $data);
}
}
です。
他の2つに関しましては余り意味が無いので既に破棄しています。
No.3
- 回答日時:
状況にもよるかと思いますが、
PHPの場合の参照の場合、参照カウンタがそれぞれ作られて、参照されている数の管理をしています。
なので、その分のオーバーヘッドがあって、単純なint のコピーで済む場合より遅い場合があるのかも知れません。
No.2
- 回答日時:
私の実感だと、やはり参照渡しの方が速いと思います。
恐らく、PHPで実際にコピー操作が起こるのは、本当にそれが必要になったとき、だと思います。
つまり、$a = $b; も $a =& $b; とやったとも、処理は殆ど同じで、前者であっても実際のデータのコピーは起こらないのだと思います。
(ソースコードレベルで言うと、どちらもzvalue_value共用体のシャローコピーでしかないということ)
データのディープコピーが起こるのは、
その後に例えば、$a .= 'B'; とかしたときなど、本当に $a の実体が必要になったとき、だと思います。
このあたりの事情がベンチマークを狂わせているのではないかと思います。
実際に代入されている値を変更するような動作を大量に行っても
参照渡しのほうが遅いのでベンチマークが翻弄されているだけではないと思います。
誤差と見る事も出来ないわけではない大きさではないですが
挙動の違うロジックで同様の結果が出た為誤差では無いのではないかと思うのです。
No.1
- 回答日時:
それが真実かどうかはべつとして
そういう風につくられているからでしょう。
ベンチマークをとれば実証はできますが、
ソースを追っかけて検証することはかなり難しく
それをプログラム的に説明されても、理解できるとは
思いませんが・・・。
(逆にそれが理解できるならご自身で検証してください)
また結果としてその命題が真実であっても、その
点がボトルネックになるプログラムを書くこと自体がない
でしょうし、もし書くことがあってそれが致命的で
あっても傾向がわかっているなら対処のしようもあるので、
なにも問題がないかと。
ありがとうございます。
http://rio.st/archives/2003/12/php_tips_2.html
の記事が事実なのか検証の為に
関数が再帰的に呼び出しその時の引数を参照渡しで渡すものと値渡しで渡すもの
for文で変数を配列に参照渡しでコピーするもの値渡しでコピーするもの
要素数10*10*10の3次元配列をimplodeで結合し全ての要素を結合する際に参照渡しで行うものと値渡しで行うもの
を作成し実際にベンチマークを行いました。
Solaris 10+Apache2.0.52+PHP4.3.2
Fedora Core 5(Kernel 2.6.17)+Apache 2.2.3+PHP 5.1.4
Windows XP+Apache 2.2.3+PHP 5.1.4
以上の環境での100回の結果を大きい方と小さい方から20個計40個を除去し
残り60個の平均が参照渡しの方が約2~5%遅かった為に疑問に思った次第です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- PHP php 入力画面から確認表示画面へ情報の受け渡しについて。 1 2023/06/07 18:00
- C言語・C++・C# 関数ポインタの高速化のメリット 7 2023/05/05 20:15
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- ホワイトデー ホワイトデーのお返しで渡すの15日にしようと思います。15日に渡すのには理由があって、その日一緒に帰 2 2023/03/07 16:12
- Excel(エクセル) こんにちは。ExcelのVLOOKUP関数のことで教えてください。 2 2022/05/07 11:33
- Visual Basic(VBA) マクロについて教えてください。 4 2023/06/06 09:06
- 法学 債務者がその所有する抵当不動産を第三者に客観的価値を下回る価格で譲渡した場合でも、当該不動産の客観的 3 2023/07/18 13:52
- 友達・仲間 友達に3年前誕生日プレゼントをもらい 2年前誕生日プレゼントを渡そうと お返しをしたいタイミングでコ 2 2022/06/18 21:47
- Visual Basic(VBA) 別ブックの列同士の値が一致したときの処理 1 2022/09/03 08:27
- 超常現象・オカルト 都合の悪い現象って頻度が多くないですか? 私の例だと、 ●好きな人からのLINEの返事が遅くてモヤモ 3 2023/06/14 18:58
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
php で1から100までの素数の表...
-
ファイルの書き込みについて教...
-
PHPのmin関数、「1」以上の数値...
-
C言語 最大値と最小値を求めて...
-
VC++2010で配列に文字列を使用...
-
リストの配列の一部を、別のと...
-
Perlで重複行を削除したい
-
配列を返す関数から、一つの要...
-
多次元配列を2次元の連想配列で...
-
連想配列で値が空だったら、要...
-
PHPは何故値渡しより参照渡しの...
-
C言語の配列をPush(追加)する...
-
verilogで、配列の一部をタスク...
-
PHPとMySQLで100万件のデータを...
-
読み(あ行~わ行)ごとに分け...
-
行列
-
Delphiで別unitで宣言した「TAr...
-
配列の添え字が小数だとどうなる?
-
重複確認
-
file_existsでファイル名の部分...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラミングのPythonのnoteb...
-
C言語の配列をPush(追加)する...
-
php で1から100までの素数の表...
-
STLのvectorで作った配列をメン...
-
スカラーのベクトル微分
-
行列
-
Perlで重複行を削除したい
-
配列の要素(value)に、変数を...
-
特定の文からメールアドレスの...
-
forとかで連番の変数を一気に格...
-
C言語 最大値と最小値を求めて...
-
PHPでユニークIDを作る
-
CArrayの要素としてCStringArra...
-
fgetc関数について
-
読み(あ行~わ行)ごとに分け...
-
Pager::factory()の使い方がわ...
-
verilogで、配列の一部をタスク...
-
mallocで char *型の配列を確...
-
連想配列で値が空だったら、要...
-
c言語 単位行列
おすすめ情報