Slide 1

Slide 1 text

俺の Laravel がこんなに速い わけない! 2022-06-22 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 2

Slide 2 text

はじめに Laravel は遅くて有名? Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 3

Slide 3 text

Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 4

Slide 4 text

しかし、実際に簡易ブログを作ってみると... ※ 10000 レコードの中規模想定 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 5

Slide 5 text

Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 6

Slide 6 text

充分速い! これじゃ、評判と違う Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 7

Slide 7 text

低速化 Laravel の実装や実行環境を工夫して、 評判通りに遅くしよう! ※なるべく気づかれないように遅くする技術 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 8

Slide 8 text

アプリの仕様 シンプルなブログアプリ Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 9

Slide 9 text

Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 10

Slide 10 text

データ量 posts 10000 users 1000 post_posts 33864 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 11

Slide 11 text

以後の高速化の指標 siege -t 10s -c 50 -b localhost Transaction Rate (Req/Sec) の3回平均 初期状態は 195.84 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 12

Slide 12 text

1. preload 無効化 zend_extension=opcache.so ;opcache.preload=/var/www/src/preload.php ;opcache.preload_user=www-data 効果なし (CPU バウンドじゃない) 195.39 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 13

Slide 13 text

2. opcache.jit 無効化 zend_extension=opcache.so ;opcache.jit=disable 効果なし (CPU バウンドじゃない) 199.29 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 14

Slide 14 text

3. opcache 無効化 ;zend_extension=opcache.so 抜群の効果 125.00 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 15

Slide 15 text

4. xdebug 有効化 zend_extension=xdebug 地味な一撃 101.90 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 16

Slide 16 text

ここまでの総評 気づかれずにミドルで与える打撃はこのくらい。 もっと過激な手段としては prefork の startServer 1 PHP のバージョンダウン Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 17

Slide 17 text

5. eager loading 廃止 $posts = \App\Models\Post::take(20); //->with('user') //->with('linkPosts') //->with('linkedPosts')->get(); 効果は抜群だ! 22.76 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 18

Slide 18 text

6. limit 句 廃止 $posts = \App\Models\Post::get(); return view(...)->with('posts', $posts->take(20)); mysqlnd の優秀さがわかる 12.83 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 19

Slide 19 text

7. Attribute Casting 乱用 foreach($posts as $post){ $post->created_at; $post->updated_at; $post->created_at; $post->updated_at; } Carbon の生成コストを侮るなかれ 6.5 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 20

Slide 20 text

総評 現場でありえそうなコードでも、50msec -> 1.5 sec 程度に低速化 単体アクセスも遅いが、特に並列化性能は 30 倍程度劣化 ※複雑化したコードベースでは注意しないとすぐ劣化 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 21

Slide 21 text

おまけ カリカリチューニング編 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 22

Slide 22 text

1. apcu キャッシュ apcu_store('key', $posts); メモリキャッシュ最高 865.7 (Req/Sec) Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 23

Slide 23 text

2. var_export して include $posts は stdclass で中身を置き換えた上で file_put_contents('/tmp/posts.php', '

Slide 24

Slide 24 text

3. var_export して preload 上の /tmp/posts.php を preload してしまう 1300 (Req/Sec) Laravel で 5msec の世界 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 25

Slide 25 text

これなら Isucon 勝てる? 単純比較は出来ないが、多分無理。 静的 HTML すると 8000 (Req/Sec) Nginx でやってみると 12000 (Req/Sec) Go は、この1.5 倍くらいなので、18000 と仮定すると、あと13 倍速 くすればワンチャンある。 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 26

Slide 26 text

Octane は? ソース見てないので実測だけだが、単純な高速化において swoole ベースで 、今回の 6 割くらいの性能に収まった。 レースコンディションで問題を起こさないようにするために、どこ かで同期処理が入っているのだと思う。 Laravel.shibuya Ryo Tomidokoro / @hanhan1978

Slide 27

Slide 27 text

じゃあどうしたら? Go を書け Open Swoole と 軽量フレームワークを組み合わせて同期処理を廃 すれば、チャンスはある。 Laravel.shibuya Ryo Tomidokoro / @hanhan1978