PHPのstat()関数のキャッシュ/キャッシュクリアに戸惑った

環境

PHP 7.013

stat()は内容をキャッシュします

stat()関数は内容をキャッシュします。下記のコードの2つのechoは同じatimeを出力します。

<?php
touch('./touch.txt');
echo stat('./touch.txt')['atime'] . "\n";
sleep(2);
touch('./touch.txt');
echo stat('./touch.txt')['atime'] . "\n";

公式ドキュメントにもその旨記載されています。

https://www.php.net/manual/ja/function.clearstatcache.php

statやlstat、 またはその他の関数(後述)を使用すると、PHPはパフォーマンス向上のために それらの関数の戻り値をキャッシュします。

キャッシュの削除にはclearstatcache()関数

キャッシュを明示的に削除したい場合はclearstatcache()関数を使用します。

とはいえtouch()でもキャッシュクリアしてほしいよね普通

もしもstat()が内容をキャッシュすることを知らなくとも、touch()関数を使用した場合はさすがにキャッシュをクリアしてほしいと思うはずです。

なぜならtouchコマンドってそういうものだからです。

結論から言いますと、touch()関数でstatのキャッシュはクリアされる場合とされない場合があります。

対象ファイルが'file://'で始まる場合、touch()関数はstatのキャッシュをクリアします。

冒頭のスニペットを書き換えると以下のようになります。(引用https://qiita.com/hnw/items/3af76d3d7ec2cf52fff8#comment-eacb1be2cf022d511900

<?php
$filename = 'file:///tmp/touch.txt';
touch($filename);
echo stat($filename)['atime'] . "\n";
sleep(2);
touch($filename);
echo stat($filename)['atime'] . "\n";

PHPソースコードの該当箇所を示します。

github.com

参考文献URL一覧

https://www.php.net/manual/ja/function.stat.php

https://www.php.net/manual/ja/function.clearstatcache.php

PHPがstatシステムコールの結果をキャッシュしている件 - Qiita

https://github.com/php/php-src/blob/master/ext/standard/filestat.c#L660