Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHPの配列とデータ構造 / PHPerKaigi 2023

meihei
March 25, 2023

PHPの配列とデータ構造 / PHPerKaigi 2023

PHPerKaigi 2023 (2023/03/25)
PHPの配列の内部実装について学びたくなった。
トークURL: https://fortee.jp/phperkaigi-2023/proposal/ec6b9d08-f32e-4071-a81b-0ccdc0fc644f

***
内容

- 基本的なデータ構造の概念について
- PHPの配列をデータ構造としてみる
- 配列の基本構造(php-src)
- PHP≦5.xの配列の内部実装
- PHP≧7.xの配列の内部実装

***
参考文献

- データ構造入門, Yoshiyuki Kusakari
- 抽象データ型(abstract data type)と抽象, 伊藤 潔
- Maps and Pairs — Programming and Data Structures 0.2 documentation
- ハッシュ法の実装と応用, 倪 永茂
- Array Data Structure
- PHP7で変わること ——言語仕様とエンジンの改善ポイント
- PHPとPythonとRubyの連想配列のデータ構造が同時期に同じ方針で性能改善されてた話
- Mastering PHP Data Structure 102 - phpDay 2012 Verona
- 9. PHP Arrays | Zend by Perforce
- [php-src読書録]その6: array
- PHPのarrayはすごいです!いろいろできます!奥深い!
- Understanding PHP's internal array implementation (PHP's Source Code for PHP Developers - Part 4)
- How big are PHP arrays (and values) really? (Hint: BIG!)
- PHP's new hashtable implementation
- PHP Internals Book
- PHP 7 Arrays : HashTables
- PHP internals 参考記事まとめ - sprawl
- 深入理解PHP7内核之HashTable - 风雪之隅
- The secret of PHP7's Performance
- PHP8底层内核源码-数组(1) - 知乎
- PHP8底层内核源码 -数组(2) - 知乎
- PHP8底层内核源码-数组(3) - 知乎
- 【PHP7源码学习】系列之数组实现 - 墨天轮
- php内核源码分析之HashTable - 代码狗
- 新・標準プログラマーズライブラリ C言語 ポインタ完全制覇, 技術評論社
- アルゴリズムイントロダクション 第3版 第1巻, 近代科学社
- みんなのデータ構造, ラムダノート
- PHPはどのように動くのか ~PHPコアから読み解く仕組みと定石, 技術評論社

meihei

March 25, 2023
Tweet

More Decks by meihei

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  6. データ構造とは何か
    6

    View Slide

  7. データ構造とは
    データ構造とは、データの集まりをコンピュータプログ
    ラムで扱いやすいように、一定の形式で格納したもの。
    特定の問題を解く手順(アルゴリズム)には、それぞれ
    に適したデータ構造がある。
    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

    View Slide

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

    View Slide

  9. 例:Queue
     
    9

    View Slide

  10. 配列とは何か
    10

    View Slide

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

    View Slide

  12. PHPの配列とは何か
    12

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. 配列を作る要素
    30

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  39. 配列を作る要素
    39

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  49.  
    49
    ハッシュ表と配列
    hash table

    View Slide

  50. 50
    Hash array

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  56. 参考文献
    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

    View Slide

  57. 参考文献
    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

    View Slide