Skip to content

Commit 73ceaa5

Browse files
committed
ext/standard/filestat: omit access()/stat() system calls for cached scripts
1 parent 5637c4d commit 73ceaa5

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,29 @@ ZEND_ATTRIBUTE_PURE static bool check_validate_timestamps_fh(const zend_file_han
215215
return check_validate_timestamps_zstr(path);
216216
}
217217

218+
bool is_persistent_script(const zend_string *filename)
219+
{
220+
if (!IS_ABSOLUTE_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename)))
221+
return false;
222+
223+
zend_string *key = normalize_path(filename);
224+
const zend_persistent_script *const persistent_script = zend_accel_hash_find(&ZCSG(hash), key);
225+
zend_string_efree(key);
226+
if (persistent_script == NULL || persistent_script->corrupted)
227+
return false;
228+
229+
if (persistent_script->timestamp == 0)
230+
/* preloaded, no validation */
231+
return true;
232+
233+
if (check_validate_timestamps_zstr(filename) &&
234+
(ZCG(accel_directives).revalidate_freq == 0 ||
235+
persistent_script->dynamic_members.revalidate < ZCG(request_time)))
236+
return false;
237+
238+
return true;
239+
}
240+
218241
/* O+ overrides PHP chdir() function and remembers the current working directory
219242
* in ZCG(cwd) and ZCG(cwd_len). Later accel_getcwd() can use stored value and
220243
* avoid getcwd() call.

ext/opcache/ZendAccelerator.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,11 @@ BEGIN_EXTERN_C()
325325

326326
ZEND_ATTRIBUTE_PURE bool check_validate_timestamps_zstr(const zend_string *filename);
327327

328+
/**
329+
* Is the specified filename a cached script whose time stamp does not
330+
* need to be revalidated currently?
331+
*/
332+
ZEND_ATTRIBUTE_PURE bool is_persistent_script(const zend_string *filename);
328333

329334
void accel_shutdown(void);
330335
zend_result accel_activate(INIT_FUNC_ARGS);

ext/standard/filestat.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "fopen_wrappers.h"
1919
#include "php_globals.h"
2020

21+
#include "ext/opcache/ZendAccelerator.h" // for is_persistent_script()
22+
2123
#include <stdlib.h>
2224
#include <sys/stat.h>
2325
#include <string.h>
@@ -712,6 +714,18 @@ PHPAPI void php_stat(zend_string *filename, int type, zval *return_value)
712714
const char *local = NULL;
713715
php_stream_wrapper *wrapper = NULL;
714716

717+
if ((type == FS_EXISTS || type == FS_IS_R || type == FS_IS_FILE) &&
718+
/* is an absolute path that ends with ".php" */
719+
ZSTR_LEN(filename) >= 6 &&
720+
ZSTR_VAL(filename)[0] == '/' &&
721+
memcmp(ZSTR_VAL(filename) + ZSTR_LEN(filename) - 4, ".php", 4) == 0 &&
722+
is_persistent_script(filename)) {
723+
/* this is a cached script and its time stamp does not
724+
* need revalidation - we can safely pretend it exists
725+
* and it is a regular file */
726+
RETURN_TRUE;
727+
}
728+
715729
if (IS_ACCESS_CHECK(type)) {
716730
if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) {
717731
if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) {

0 commit comments

Comments
 (0)