Time Complexity 101 for PHPer
PHPerのための計算量入門Ryo TomidokoroPHPerKaigi 2019/3/30@hanhan1978
View Slide
よくあるコード例から計算量を理解してみよう
例題とあるウェブサービスを運営する会社の営業社員が会員データの分析をするためのCSVファイルを作ります。全ユーザのデータをDatabaseから取得して、各種付帯情報を追加してCSVファイルを作成します。
コード例
コードの問題は何?仕様は満たしている、動作も問題ない。しかし、データの増大と共に問題を起こす可能性がある。実際に、サンプルコードの負荷試験をして、データ量と処理時間の関係を確認する。
データ件数と処理時間の関係
この問題をどのように検出する?なるべく勘や経験に頼りたくはないが、何か良い方法はあるだろうか?
問題を検出する方法
◎負荷試験人材や納期、品質向上への理解があるのであれば、本番相当以上のデータ量を用意した負荷試験を行えば、確実に検出することが可能今までのエンジニア人生で、CIに負荷試験が組み込まれているのを見たことは稀…
静的解析PHPStan, PHPMD等、試してみたが流石に計算量の問題点は検出できない。
▲経験好きなアプローチではないが、現状もっとも低コストで現実的に実行できる対策はこれになってしまう。研修や教育によって計算量に対して、意識を向けてもらうようにする。
計算量視点を持ついつものコーディングに、新しい視点として、計算量を加えて見よう。
計算量とは?
2つの計算量時間計算量(Time Complexity)プログラムの演算の回数空間計算量(Space Complexity)プログラムが利用するメモリ使用量
時間計算量の測り方
単純な掛け算関数
すべてのアルゴリズムで厳密な時間計算量を算出するのは大変です。そこで、時間計算量の世界には便利な記法があります。
O記法 (Big-O notation)計算量の目安を表す便利な記法。O記法での表現によって、そのアルゴリズムがどんな時間計算量特性を持つのかを理解できる。O(1), O(n), O(n^2), O(n*log n)括弧の中身が計算量のオーダーを表す
データ量と時間計算量特性の関係[引用] 開発新卒に捧ぐ、基本のアルゴリズムと計算量https://www.techscore.com/
アルゴリズムと計算量アルゴリズム 計算量バブルソート O(n^2)マージソート O(n * log n)バイナリーサーチ O(log n)
計算量視点で最初の例を読み返す
計算量オーダーを下げる
改善例※ $purchased_usersのkeyとvalueを入れ替えておく
改善例
処理時間を再計測
データ件数と処理時間の関係(改善後)
計算量という視点を持つことで、プログラムが潜在的にもつ問題点を見つけることが出来た。※ただし、データ量が少なければ問題ないことが多いので、無闇に計算量ばかり指摘するのはやめましょう。
in_arrayは遅いので、array_key_existsに書き換えて!悪い指摘の仕方
このプログラムが処理するデータ量が3万件です。アルゴリズムの計算量がO(N^2)なので、処理時間に懸念があります。念の為、負荷試験を追加で行ってもらって良いでしょうか?良い指摘の仕方
おまけ
配列操作関数の計算量O(1) O(n) O(n^2)array_key_existsarray_key_firstarray_key_lastarray_pusharray_poparray_combinearray_fliparray_keysarray_maparray_randarray_shiftarray_sumarray_uniquearray_valuesarsortasortin_arrayarray + arrayrangearray_fillarray_intersectarray_merge
Redisのドキュメント
参考図書数学ガール4 乱択アルゴリズム (結城 浩)みんなのコンピューターサイエンス (Wladston Ferreira Filho)アルゴリズムとデータ構造 (近藤 嘉雪)
Thanks!!@hanhan1978https://blog.hanhans.netRyo Tomidokoro