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

PHP8はISUCONへの扉を開く鍵となるか / Will PHP8 Be the Key T...

PHP8はISUCONへの扉を開く鍵となるか / Will PHP8 Be the Key That Opens the Door to ISUCON?

PHP Conference Japan 2020 Re:born (2020-12-12) で登壇した資料です。

PHP8 のパフォーマンス改善が ISUCON でどこまで効くのかを、ベンチマークをもとに検証しています。

Avatar for shiro seike

shiro seike PRO

December 12, 2020

More Decks by shiro seike

Other Decks in Programming

Transcript

  1. 自己紹介 - ID - - - 清家 史郎 GitHub:seike460 Twitter:@seike460

    Work at - 株式会社 Fusic (フュージック) 技術開発本部/技術開発第一部門 - チームリーダー/エバンジェリスト/プリンシパルエンジニア Skill - PHP/Go/AWS Personal - PHPカンファレンス福岡2020 幻の実行委員長 - Fukuoka.php Organizerの一人 46fm パーソナリティ @seike460 2
  2. ISUCON10 オンライン予選の利用言語比率 ISUCON公式Blogより もちろん僕も参加しておりPHPで予選に挑戦しました。 オンライン予選 利用言語比率 利用率の全体ランキングは以下の通りです。 Go 276組 59.0%

    Ruby 81組 17.3% Python 47組 10.0% Nodejs 29組 6.2% PHP 18組 3.8% Rust 8組 1.7% Perl 7組 1.5% Elixir 1組 0.2% original-ruby 1組 我らのPHPちょっと少ない… 0.2% 6
  3. 本選出場の33チーム ISUCON公式Blogより 本戦出場で絞ると更に少ない… 意気揚々とISUCONの話をしてるくらいなので、 Go 28組 84.8% Nodejs 2組 6.1%

    Rust 1組 3.0% Ruby 1組 3.0% PHP 1組 3.0% もしかしてこれは僕たちのチームなのでは…!? 残念ながら僕たちは 46位で予選落ちでした … この結果は ISUCON-PHPに 希望の芽を残しました 7
  4. 検証コード github.com/VKCOM/kphp がベンチマークに使っている検証コードをお借りしました。 KPHP is a PHP compiler. It compiles

    a limited subset of PHP to a native binary running faster than PHP. Walk-through: benchmarking PHP vs KPHP vs C++ PHP code: quicksort algorithm このコードを利用して、純粋なPHPの速度比較を行います。 16
  5. 検証コード <?php function quickSort(array &$a, int $start = 0, int

    $last = null) { $wall = $start; $last = is_null($last) ? count($a) - 1 : $last; if ($last - $start < 1) return; switchValues($a, (int) (($start + $last) / 2), $last); for ($i = $start; $i < $last; $i++) if ($a[$i] < $a[$last]) { ┆ switchValues($a, $i, $wall); ┆ $wall++; } switchValues($a, $wall, $last); quickSort($a, $start, $wall - 1); quickSort($a, $wall + 1, $last); } function switchValues(array &$a, int $i1, int $i2) { if ($i1 !== $i2) { $temp = $a[$i1]; $a[$i1] = $a[$i2]; $a[$i2] = $temp; } } 17
  6. 検証コード function generateArr(int $size): array { $arr = []; for

    ($i = 0; $i < $size; $i++) { $arr[] = (int) (rand() / (1000000000 / $size)); } return $arr; } $size = 1000000; $arr = generateArr($size); $start = microtime(true); quickSort($arr); $duration = round((microtime(true) - $start) * 1000 * 1000) / 1000; echo "Sorted $size elements in {$duration}ms\n"; echo 'memory_get_usage ->' . round(memory_get_usage() / 1024 / 1024, 2) . 'MByte' . PHP_EOL; 18
  7. Xdebug+webgrind /** * Directory to search for trace files */

    static function xdebugOutputDir() { $dir = ini_get('xdebug.profiler_output_dir'); if ($dir=='') // Ini value not defined return realpath(Webgrind_Config::$profilerDir).'/'; return realpath($dir).'/'; } 20
  8. Xdebug 突然の死 Segmentation fault… ひとまずDebugでなんとか出来ないかgdbで見るもわからず… [Thread debugging using libthread_db enabled]

    Using host libthread_db library "/lib64/libthread_db.so.1". Core was generated by `php index.php'. Program terminated with signal SIGSEGV, Segmentation fault. #0 ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER () at /tmp/php-build/source/8.0.0/Zend/zend_vm_execute.h:1917 1917 if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { [Current thread is 1 (Thread 0x7fcae7405c80 (LWP 25999))] (gdb) bt #0 ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER () at /tmp/php-build/source/8.0.0/Zend/zend_vm_execute.h:1917 #1 0x000000000080f3ab in execute_ex (ex=0x7fcadd413300) at /tmp/php-build/source/8.0.0/Zend/zend_vm_execute.h:54545 #2 0x00007fcadce8a16e in xdebug_execute_ex (execute_data=0x7fcadd4130f0) at /tmp/php-build/source/xdebug-3.0.1/src/base/base.c:802 #3 0x000000000045a0e9 in ZEND_DO_FCALL_SPEC_OBSERVER_HANDLER () at /tmp/php-build/source/8.0.0/Zend/zend_vm_execute.h:1938 #4 0x000000000080f3ab in execute_ex (ex=0x7fcadd413300) at /tmp/php-build/source/8.0.0/Zend/zend_vm_execute.h:54545 #5 0x00007fcadce8a16e in xdebug_execute_ex (execute_data=0x7fcadd413020) at /tmp/php-build/source/xdebug-3.0.1/src/base/base.c:802 #6 0x0000000000815a00 in zend_execute (op_array=0x7fcadd473100, return_value=0x0) at /tmp/php-build/source/8.0.0/Zend/zend_vm_execute.h:58856 #7 0x00000000007b4cda in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at /tmp/php-build/source/8.0.0/Zend/zend.c:1680 #8 0x0000000000759a30 in php_execute_script (primary_file=primary_file@entry=0x7ffed1e21f10) at /tmp/php-build/source/8.0.0/main/main.c:2488 #9 0x00000000008384b9 in do_cli (argc=2, argv=0x303d1f0) at /tmp/php-build/source/8.0.0/sapi/cli/php_cli.c:949 #10 0x00000000004614bb in main (argc=2, argv=0x303d1f0) at /tmp/php-build/source/8.0.0/sapi/cli/php_cli.c:1336 22
  9. プロファイラーにて計測 - xdebug - 動作するがJIT有効化するとSegmentation fault… datadog - Segmentation fault

    - blackfire - Segmentation fault - Tideways XHProf - Segmentation fault - xhprof - Segmentation fault 泣く泣くstart時にmicrotime、endにmicrotimeを取得して計測 もし動作がうまくいってる方がいらっしゃったらぜひ共有頂きたいです󰢛 23
  10. 検証コード github.com/VKCOM/kphp がベンチマークに使っている検証コードをお借りしました。 KPHP is a PHP compiler. It compiles

    a limited subset of PHP to a native binary running faster than PHP. Walk-through: benchmarking PHP vs KPHP vs C++ PHP code: quicksort algorithm このコードを利用して、純粋なPHPの速度比較を行います。 24
  11. 結果 ▪PHP7.3.22 Sorted 1000000 elements in 1475.64ms Sorted 1000000 elements

    in 1442.352ms Sorted 1000000 elements in 1453.989ms Sorted 1000000 elements in 1545.674ms Sorted 1000000 elements in 1423.958ms memory_get_usage ->32.38MByte ▪PHP8.0.0 Sorted 1000000 elements in 1397.739ms Sorted 1000000 elements in 1349.728ms Sorted 1000000 elements in 1388.148ms Sorted 1000000 elements in 1342.53ms Sorted 1000000 elements in 1381.239ms memory_get_usage ->32.34MByte 27
  12. PHP8 JITの設定 ▪opcache.jit disable: 完全に無効にする。実行時にも有効にできません。 off: 無効にしますが、実行時に有効にできます。 tracing/on: トレーシングJIT を使う。

    function: 関数単位でJITを使う。 ▪opcache.jit_buffer_size int コンパイル済みのJITコードを保存する共有メモリの合計サイズ。 0 を指定すると、JIT が無効になります。 29
  13. 結果 ▪PHP8.0.0 + JIT Sorted 1000000 elements in 391.313ms Sorted

    1000000 elements in 403.318ms Sorted 1000000 elements in 392.878ms Sorted 1000000 elements in 428.734ms Sorted 1000000 elements in 396.696ms 爆速! 31
  14. Webアプリケーションのパフォーマンス Webアプリケーションにおけるパフォーマンス Client -> Nginx -> PHP -> Storage(RDBなど) -

    PHP -> RDBに対する処理のパフォーマンスの確認 - PHP CLI にてPostgreSQLの接続を試す 34
  15. 検証コード <?php function getUser() { $link = pg_connect("host=10.0.0.89 dbname=postgres user=postgres

    password=postgres"); $query = pg_query($link, 'select * from user'); $i = 0; while ($row = pg_fetch_row($query)) { ┆ $i++; } pg_close($link); } $j = 0; $start = microtime(true); while ($j < 1000) { getUser(); $j++; } $duration = round((microtime(true) - $start) * 1000 * 1000) / 1000; echo "pg_connect {$j} times in {$duration}ms\n"; 35
  16. 検証結果 ▪JITあり pg_connect 1000 times in 41586.372ms pg_connect 1000 times

    in 43173.084ms pg_connect 1000 times in 44172.276ms ▪JITなし pg_connect 1000 times in 45814.642m pg_connect 1000 times in 45438.385ms pg_connect 1000 times in 45806.33ms RDBの処理が支配的であるため、処理改善が非常に小さい DiskStorageなどが絡んでしまうとPHP8のJITの効果は極小化してしまう 36
  17. 言語の速度差異 Compare C++, JS, Python, Python + numba, PHP7, PHP8,

    and Golang in “Prime Number” calculation.より 44