PHPの「=」は本当にコピーしているのか?

>100 Views

October 18, 25

スライド概要

profile-image

PHPをメインにサービス開発しているプログラマー

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

PHPの「=」は本当にコピーしているのか? 発表者: Kou イベント: 第6回 札幌PHP勉強会 1

2.

自己紹介 Kou 札幌市内のプログラマー Sapporo Engineer Base運営 スキル:PHP、React、Azure 2

3.

はじめに 普段は Laravel 中心で開発 言語そのものの挙動は意外と曖昧になりがち 本日はPHPの配列と文字列の「=(代入)」を軸に Copy on Write (COW) を説明 3

4.

コードで動作確認 $a = [1, 2, 3]; $b = $a; $b[0] = 99; var_dump($a); // [1, 2, 3] var_dump($b); // [99, 2, 3] の出力は [1,2,3] のまま → 「値渡し」っぽく見える でも実際は $b = $a; の時点でコピーは行われていない $a 4

5.

Copy on Write(COW) 代入時にはコピーせず、書き換えが起こったときに初めてコピーする $b = $a; の時点では同じメモリアドレスを共有 $b[0] = 99; の時点で実体を複製 5

6.

zvalとrefcountの基礎 zval (Zend value)… PHPの任意の値を表現する内部構造 主な情報 value (実体 or 参照先) type (型タグ) refcount (参照カウント) is_ref (参照共有か) PHP7で zvalは軽量構造体 にリファクタリング。 6

7.

① 配列 COW(書き込み前) $a = [1, 2, 3]; $b = $a; echo "== 書き込み前 ==\n"; xdebug_debug_zval('a'); xdebug_debug_zval('b'); 期待される表示 a: (refcount=2, is_ref=0)=array(...) b: (refcount=2, is_ref=0)=array(...) 7

8.

配列 COW (書き込み後) $b[0] = 99; // ★ここでCOW発動 echo "== 書き込み後 ==\n"; xdebug_debug_zval('a'); xdebug_debug_zval('b'); 期待表示 a: (refcount=1, is_ref=0)=array(...) b: (refcount=1, is_ref=0)=array(...) 書き込んだ瞬間に 分離(コピーが発生) 8

9.

② 参照渡しは COW を無効化 $a = [1, 2, 3]; $b =& $a; // 明示参照 xdebug_debug_zval('a'); xdebug_debug_zval('b'); 期待表示 a: (refcount=2, is_ref=1)=array(...) b: (refcount=2, is_ref=1)=array(...) 同一zvalを共有し続ける → どちらを変更しても両方に反映 「参照渡し=速い」は誤解。COW最適化を壊す場合あり 9

10.

③ 文字列のCOWとinterned string $s1 = "hello"; // リテラルは interned string になり得る $s2 = $s1; xdebug_debug_zval('s1'); xdebug_debug_zval('s2'); $s2 .= "!"; // ★ここで分離 xdebug_debug_zval('s1'); xdebug_debug_zval('s2'); 文字列も基本は COW interned string は同じ文字列リテラルを一箇所にまとめて再利用する最適化を行 う。 10

11.

まとめ PHPの配列と文字列はCopy on Writeによって、書き込んだ瞬間にだけコピーされ る。 参照( & )はCOW無効化。乱用は逆効果になる可能性がある。 11

12.

参考文献 PHP Manual: 変数の扱い / 参照 / GC Refcounting Basics https://www.php.net/manual/ja/language.variables.basics.php https://www.php.net/manual/ja/language.references.php https://www.php.net/manual/en/features.gc.refcounting-basics.php Derick Rethans: Xdebug 2.3: xdebug_debug_zval() https://derickrethans.nl/xdebug-2.3-xdebug-debug-zval.html PHP Internals Book(zval / Memory Management) https://www.phpinternalsbook.com/ Qiita: tadsan https://qiita.com/tadsan/items/0f7c20bdde119c9ce13e 12