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 full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size slide

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

    View full-size slide

  9. 例:Queue
     
    9

    View full-size slide

  10. 配列とは何か
    10

    View full-size slide

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

    View full-size slide

  12. PHPの配列とは何か
    12

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  30. 配列を作る要素
    30

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  39. 配列を作る要素
    39

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  50. 50
    Hash array

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size 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 full-size 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 full-size slide