#17 PHPを書いていたはずが、ずっとCを読んでいた

ドキュメントを読んでも納得できないとき、あなたはどこまで潜りますか? 今回はリスナーのポヨヨンさんから届いた「PHP が C 言語のラッパーであるという話を詳しく知りたい」というお便りに、catatsuy が自身の経験を総動員して答えるお便り回です。

`fopen()`のモード文字がPHPのstream実装で`open()`へ渡すフラグに変換され、OSへ処理が委ねられる仕組みをCのソースコードで確かめるところから始まります。さらに、Webアプリケーションの根幹なのにCで実装されていて読み解くのが難しいPHPのセッションやRedis拡張にも触れながら、「マルチプロセスではメモリを共有できないはずなのに」を飛び越えてくるAPCuと共有メモリセグメントの正体へ。ISUCON本のわずか数行を書くために、APCuのC実装を数時間かけて読んだ経験も振り返ります。

後半では、PHP 5.6から7への移行期にmemcache拡張からmemcached拡張へ乗り換えたところ、同じmemcachedサーバーに保存した値を正しく読めなくなった実運用トラブルを紹介します。memcachedのflagsはサーバーが解釈しないクライアント向けの領域であり、二つの拡張がそれぞれ異なる型情報や圧縮情報を記録していました。どちらも仕様に沿って実装されているのに、ライブラリを交換すると互換性問題が表面化する。その原因を突き止めるため、またCのコードへ潜っていきます。

最後は、AIを使ったコードリーディングと、普段使うライブラリの実装まで同じ言語のまま降りやすいGoとの違いにも話が広がります。

言語の内部実装に興味がある人にぜひ聞いてほしい回です。

## 関連リンク

- PHP: https://www.php.net/

- PHPの通常ファイル用stream実装(plain_wrapper.c): https://github.com/php/php-src/blob/271f689482c8efdaa8b2b5ac11e8172c25335bdd/main/streams/plain_wrapper.c

- PHPのセッション実装(ext/session): https://github.com/php/php-src/tree/271f689482c8efdaa8b2b5ac11e8172c25335bdd/ext/session

- APCu: https://pecl.php.net/package/APCu

- APCu(GitHubリポジトリ): https://github.com/krakjoe/apcu

- memcached: https://memcached.org/

- memcached protocol: https://github.com/memcached/memcached/blob/master/doc/protocol.txt

- PECL memcache: https://pecl.php.net/package/memcache

- php-memcached(PHP の memcached 拡張): https://github.com/php-memcached-dev/php-memcached

- phpredis(PHPのRedis拡張): https://github.com/phpredis/phpredis

- Redis: https://redis.io/

- gomemcache(bradfitz 作の Go 用 memcached クライアント): https://github.com/bradfitz/gomemcache

- gorilla/sessions(Go のセッションライブラリ): https://github.com/gorilla/sessions

- Go: https://go.dev/

- 達人が教えるWebパフォーマンスチューニング(ISUCON本): https://gihyo.jp/book/2022/978-4-297-12846-3

─────────────

YouTube: https://youtu.be/3BVO99h3Iqo

Web: https://yaoyorozu-oss.henteko07.com/

X: https://x.com/yaoyorozu_oss