Slide 1

Slide 1 text

PHPの配列とデータ構造 PHPerKaigi 2023 (2023/03/25)

Slide 2

Slide 2 text

meihei / 江間 洋平 所属 株式会社PR TIMES 開発本部 Backend Engineer (PHP/Python/Go) 趣味 サイクリング(クロスバイク) VTuberの配信を流して生きている SNS Twitter: https://twitter.com/app1e_s GitHub: https://github.com/meihei3 自己紹介 2

Slide 3

Slide 3 text

ゴール 「PHPの配列」というデータ構造を理解し、 「PHPの配列」の内部実装を理解する。 3

Slide 4

Slide 4 text

アジェンダ 1. データ構造とPHPの配列 2. PHPの配列で使われているデータ構造 3. PHPの配列の内部実装 4. まとめ 4

Slide 5

Slide 5 text

アジェンダ 1. データ構造とPHPの配列 2. PHPの配列で使われているデータ構造 3. PHPの配列の内部実装 4. まとめ 5

Slide 6

Slide 6 text

データ構造とは何か 6

Slide 7

Slide 7 text

データ構造とは データ構造とは、データの集まりをコンピュータプログ ラムで扱いやすいように、一定の形式で格納したもの。 特定の問題を解く手順(アルゴリズム)には、それぞれ に適したデータ構造がある。 7 引用: IT用語辞典 e-Words, https://e-words.jp/w/%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0.html

Slide 8

Slide 8 text

インターフェースと実装 ● インターフェース (interface) ○ あるデータ構造がサポートしている操作一式と、それ らの操作の意味を定義する ○ 抽象データ型とも呼ばれる ● 実装 (implementation) ○ データ構造の内部表現と、実際に操作を行うアルゴリ ズムの定義が含まれる ○ 1つのインターフェースに複数の実装があり得る 8

Slide 9

Slide 9 text

例:Queue   9

Slide 10

Slide 10 text

配列とは何か 10

Slide 11

Slide 11 text

配列とは 配列とは、同一の型のデータを メモリ上に一列に並べたもの。 右図は配列の典型的な例とし て、C言語のchar型の配列。 11

Slide 12

Slide 12 text

PHPの配列とは何か 12

Slide 13

Slide 13 text

PHPの配列の公式ドキュメント ● インターフェース:そのデータ構造が何をするのか ● 実装:データ構造がそれをそのようにやるのか 13

Slide 14

Slide 14 text

PHPの配列と真の配列を データ構造として見た時 これらはイコールの関係ではない 14

Slide 15

Slide 15 text

✅ PHPの配列は真の配列としても使う ことも出来る ❌ PHPの配列は真の配列である ❌ PHPは真の配列が使えない PHP array ≠ true array 15 ※1 ここではPHP≧7.xの説明をしています。 ※2 この図はPHPの配列(配列型)において、それを真の配列としても使えることを表しています。PHP 言語で使用可能な真の配列は、PHPの配列(配列型)以外にも存在することに留意してください。

Slide 16

Slide 16 text

PHPの配列は真の配列よりも 抽象度の高いデータ構造として理解する 16

Slide 17

Slide 17 text

データ構造:PHPの配列   17 インターフェース 実装 ● 順序付けられている ● 辞書操作が可能 ○ INSERT ○ SEARCH ○ DELETE この後解説します。 PHPの配列をデータ構造と見なしたとき、より詳細なインターフェースとは公式ドキュメントに書かれ ている配列の使用方法です。

Slide 18

Slide 18 text

アジェンダ 1. データ構造とPHPの配列 2. PHPの配列で使われているデータ構造 3. PHPの配列の内部実装 4. まとめ 18

Slide 19

Slide 19 text

PHPの配列を構成しているデータ構造 PHPの配列を理解する上で、まず理解しておく必要があ るデータ構造。(実装) ● 配列 ● 連結リスト(linked list) ● ハッシュ表(Hash tables) 19 ※ 内部実装はバージョンによって異なるので、現在のPHPでこれらすべてが使われるわけではありませ ん。詳細は後ろのページで解説します。

Slide 20

Slide 20 text

PHPの配列を構成しているデータ構造 PHPの配列を理解する上で、まず理解しておく必要があ るデータ構造。(実装) ● 配列 ● 連結リスト(linked list) ● ハッシュ表(Hash tables) 20 ※ 内部実装はバージョンによって異なるので、現在のPHPでこれらすべてが使われるわけではありませ ん。詳細は後ろのページで解説します。

Slide 21

Slide 21 text

連結リスト(linked list) 各要素がその後ろの要素へのリンク(ポインタ)を持つ データ構造。 21 例: [643, 46, 112, 1255]と並んだデータの場合

Slide 22

Slide 22 text

双方向連結リスト(doubly linked list) 各要素が前後の要素へのリンク(ポインタ)を持つデー タ構造。 22 例: [643, 46, 112, 1255]と並んだデータの場合

Slide 23

Slide 23 text

ハッシュ表(Hash tables) 広範囲に及ぶキーのうち、実際に格納されるキーが少数 の場合に適したデータ構造。 キーからハッシュ関数を用いて算出したハッシュ値とい う整数を配列の添字として使う。 ハッシュ値は衝突することがある。その解決方法として チェイン法がある。 23 ※ ハッシュ値が衝突した場合の解決方法はチェイン法以外にもある。しかしPHPの配列ではチェイン法 を使っているので、本発表ではチェイン法だけを説明している。

Slide 24

Slide 24 text

ハッシュ表(Hash tables) 24 例: [“user_id”=>643, “count”=>46, “company_id”=>112, “release_id”=>1255] とkey/valueとなるデータの場合

Slide 25

Slide 25 text

PHPの配列はバージョン によって配列の実装が異なる 25

Slide 26

Slide 26 text

PHPのバージョンと配列の実装 ● PHP ≦ 5.x ○ ハッシュ表と双方向リストを合わせた構造 ○ 常にハッシュ表を使った連想配列 ● PHP ≧ 7.x ○ ハッシュ表と配列を合わせた構造 ○ キーが0からの添字になっていればハッシュ表は使わ れず、配列となる 26

Slide 27

Slide 27 text

PHP ≦ 5.x の配列 あああ  27 インターフェース 実装 ● 順序付けられている ● 辞書操作が可能 ○ INSERT ○ SEARCH ○ DELETE 以下2つのデータ構造を組み合わせ た実装 ● 双方向連結リスト ● ハッシュ表 実際のデータは双方向連結リストか ら参照されている

Slide 28

Slide 28 text

PHP ≧ 7.x の配列   28 インターフェース 実装 ● 順序付けられている ● 辞書操作が可能 ○ INSERT ○ SEARCH ○ DELETE 以下2つのデータ構造を組み合わせ た実装 ● 配列 ● ハッシュ表 実際のデータは配列上に並べられて いる

Slide 29

Slide 29 text

アジェンダ 1. データ構造とPHPの配列 2. PHPの配列で使われているデータ構造 3. PHPの配列の内部実装 4. まとめ 29

Slide 30

Slide 30 text

配列を作る要素 30

Slide 31

Slide 31 text

Zval構造体 PHPの1つの値を表現する構造体。詳しい解説は省略。 31

Slide 32

Slide 32 text

Bucket構造体(PHP ≦ 5.x) PHPの配列の1つの要素は Bucket という構造体であ り、値(zval)はそこから参照される。 32

Slide 33

Slide 33 text

PHP ≦ 5.x の配列の内部実装 33

Slide 34

Slide 34 text

サンプルの配列 $arr = [ “user_id” => 643, “count” => 46, “company_id” => 112, “release_id” => 1255, ]; 34

Slide 35

Slide 35 text

PHP ≦ 5.x の配列 双方向連結リストを使って順序付けを実装 35 例: [“user_id”=>643, “count”=>46, “company_id”=>112, “release_id”=>1255] となる配列の場合

Slide 36

Slide 36 text

PHP ≦ 5.x の配列 ハッシュ表を使って SEARCH (key=>value)を実装 36 例: [“user_id”=>643, “count”=>46, “company_id”=>112, “release_id”=>1255] となる配列の場合

Slide 37

Slide 37 text

PHP ≧ 7.x の配列の内部実装 37

Slide 38

Slide 38 text

● Packed array ○ 配列のキーが0からの昇順の整数の場合、自動的にこ のデータ構造になる。 ○ キーをそのまま内部の配列の添字とするので、ハッ シュ表を使わない。 ● Hash array ○ Packed arrayの条件に満たない場合、このデータ構造 になる。 2つのデータ構造の実装方法 38 ※ 厳密にはPacked arrayの定義では、キーがTableSizeを下回っている必要がある。

Slide 39

Slide 39 text

配列を作る要素 39

Slide 40

Slide 40 text

PHP ≧ 7.xで変更があったが、詳しい解説は省略。 Zval構造体 40

Slide 41

Slide 41 text

PHP ≧ 7.x になると Bucket に直接値(zval)がセットさ れるように。 Bucket構造体(PHP ≧ 7.x) 41

Slide 42

Slide 42 text

Bucketはメモリ上に並べられる。配列へ追加される順に 並ぶので、順序付けを保証。 42 PHP ≧ 7.x の配列の実装基礎

Slide 43

Slide 43 text

● Packed array ○ 配列のキーが0からの昇順の整数の場合、自動的にこ のデータ構造になる。 ○ キーをそのまま内部の配列の添字とするので、ハッ シュ表を使わない。 ● Hash array ○ Packed arrayの条件に満たない場合、このデータ構造 になる。 2つのデータ構造の実装方法 43 ※ 厳密にはPacked arrayの定義では、キーがTableSizeを下回っている必要がある。

Slide 44

Slide 44 text

サンプルの配列(Packed array) $arr = [ 643, 46, 112, 1255, ]; 44

Slide 45

Slide 45 text

45 例: [643, 46, 112, 1255] となる配列の場合 Packed array (PHP ≦ 8.1)

Slide 46

Slide 46 text

46 Use more compact representation for packed arrays. #7491 https://github.com/php/php-src/pull/7491 Packed array (PHP ≧ 8.2)

Slide 47

Slide 47 text

● Packed array ○ 配列のキーが0からの昇順の整数の場合、自動的にこ のデータ構造になる。 ○ キーをそのまま内部の配列の添字とするので、ハッ シュ表を使わない。 ● Hash array ○ Packed arrayの条件に満たない場合、このデータ構造 になる。 2つのデータ構造の実装方法 47 ※ 厳密にはPacked arrayの定義では、キーがTableSizeを下回っている必要がある。

Slide 48

Slide 48 text

  48 ハッシュ表と配列 TableSizeが8なので、`hash(x) mod 8` をしている data array 動的に配列を生成しているが、効率化のため2の冪乗でサイズを確保している。

Slide 49

Slide 49 text

  49 ハッシュ表と配列 hash table

Slide 50

Slide 50 text

50 Hash array

Slide 51

Slide 51 text

51 Hash array(簡易図) 備考: なぜPHPの配列の内部構造で使われるハッシュテーブルは、OR演算子でビットマスク を計算しているのか? https://zenn.dev/meihei/articles/e5aa05a0e6c82e

Slide 52

Slide 52 text

52 Hash array(簡易図) 備考: なぜPHPの配列の内部構造で使われるハッシュテーブルは、OR演算子でビットマスク を計算しているのか? https://zenn.dev/meihei/articles/e5aa05a0e6c82e

Slide 53

Slide 53 text

アジェンダ 1. データ構造とPHPの配列 2. PHPの配列で使われているデータ構造 3. PHPの配列の内部実装(PHP ≦ 5.x) 4. まとめ 53

Slide 54

Slide 54 text

PHPの配列は「PHPの配列」というデータ構造として理 解する。 内部実装は PHP ≦ 5.x と PHP ≧ 7.x で大きく異なり、 7.0 以降は真の配列を使うようになった 現在使われている PHP では”Packed array”と”Hash array”が使われており、PHP 8.2 で Packed array は 更に簡潔なデータ構造になった。 まとめ 54

Slide 55

Slide 55 text

エンジニア採用サイト エンジニア採用資料 開発者ブログ  PR TIMES 採用情報 検索 私たちと一緒に 「未来の変化」 をつくっていく仲間を募集しています。 We Are Hiring!

Slide 56

Slide 56 text

参考文献 1. http://www.akita-pu.ac.jp/system/elect/ins/kusakari/japanese/teaching/SoftTech/2005/note/9/index.html 2. http://lise-sophia.net/kktm/Essay/abstract.htm 3. https://eecs280staff.github.io/notes/21_Maps_Auto_Range-BasedForLoops.html 4. https://uuair.repo.nii.ac.jp/?action=pages_view_main&active_action=repository_view_main_item_detail& item_id=12205&item_no=1&page_id=13&block_id=58 5. https://www.geeksforgeeks.org/array-data-structure/ 6. https://www.slideshare.net/hnw/phpcon-kansai20150530 7. https://hnw.hatenablog.com/entry/2021/01/10/162018 8. https://www.slideshare.net/patrick.allaert/mastering-php-data-structure-102-php-day-2012 9. https://www.zend.com/resources/php-extensions/php-arrays 10. https://blog.freedom-man.com/php_src_6 11. https://qiita.com/tadsan/items/3c61c8e5db24862c86c8 12. https://www.npopov.com/2012/03/28/Understanding-PHPs-internal-array-implementation.html 13. https://www.npopov.com/2011/12/12/How-big-are-PHP-arrays-really-Hint-BIG.html 14. https://www.npopov.com/2014/12/22/PHPs-new-hashtable-implementation.html 15. https://www.phpinternalsbook.com/index.html 56

Slide 57

Slide 57 text

参考文献 16. http://blog.jpauli.tech/2016-04-08-hashtables-html/ 17. https://sprawl.hatenablog.jp/entry/2015/05/18/185416 18. https://www.laruence.com/2020/02/25/3182.html 19. https://www.slideshare.net/laruence/the-secret-of-php7s-performance 20. https://zhuanlan.zhihu.com/p/358022436 21. https://zhuanlan.zhihu.com/p/358354087 22. https://zhuanlan.zhihu.com/p/360952022 23. https://www.modb.pro/db/77661 24. https://fantiq.github.io/2019/05/26/php%E5%86%85%E6%A0%B8%E6%BA%90%E7%A0%81%E5%88%86 %E6%9E%90%E4%B9%8BHashTable/ 25. 新・標準プログラマーズライブラリ C言語 ポインタ完全制覇, 技術評論社, https://gihyo.jp/book/2017/978-4-7741-9381-6 26. アルゴリズムイントロダクション 第3版 第1巻, 近代科学社, https://www.kindaikagaku.co.jp/book_list/detail/9784764904064/ 27. みんなのデータ構造, ラムダノート, https://www.lambdanote.com/products/opendatastructures 28. PHPはどのように動くのか ~PHPコアから読み解く仕組みと定石, 技術評論 社,https://gihyo.jp/book/2015/978-4-7741-7642-0 57