Skip to content

Commit 9f2a262

Browse files
committed
ext/standard/filestat: omit access()/stat() system calls for cached scripts
1 parent 41da2ea commit 9f2a262

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
@@ -216,6 +216,29 @@ ZEND_ATTRIBUTE_PURE static bool check_validate_timestamps_fh(const zend_file_han
216216
return check_validate_timestamps_zstr(path);
217217
}
218218

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

ext/opcache/ZendAccelerator.h

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

331331
ZEND_ATTRIBUTE_PURE bool check_validate_timestamps_zstr(const zend_string *filename);
332332

333+
/**
334+
* Is the specified filename a cached script whose time stamp does not
335+
* need to be revalidated currently?
336+
*/
337+
ZEND_ATTRIBUTE_PURE bool is_persistent_script(const zend_string *filename);
333338

334339
void accel_shutdown(void);
335340
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>
@@ -736,6 +738,18 @@ PHPAPI void php_stat(zend_string *filename, int type, zval *return_value)
736738
const char *local = NULL;
737739
php_stream_wrapper *wrapper = NULL;
738740

741+
if ((type == FS_EXISTS || type == FS_IS_R || type == FS_IS_FILE) &&
742+
/* is an absolute path that ends with ".php" */
743+
ZSTR_LEN(filename) >= 6 &&
744+
ZSTR_VAL(filename)[0] == '/' &&
745+
memcmp(ZSTR_VAL(filename) + ZSTR_LEN(filename) - 4, ".php", 4) == 0 &&
746+
is_persistent_script(filename)) {
747+
/* this is a cached script and its time stamp does not
748+
* need revalidation - we can safely pretend it exists
749+
* and it is a regular file */
750+
RETURN_TRUE;
751+
}
752+
739753
if (IS_ACCESS_CHECK(type)) {
740754
if (!ZSTR_LEN(filename) || CHECK_NULL_PATH(ZSTR_VAL(filename), ZSTR_LEN(filename))) {
741755
if (ZSTR_LEN(filename) && !IS_EXISTS_CHECK(type)) {

0 commit comments

Comments
 (0)