Hello,
These days I've been working on some tasks to reduce I/O system calls
(lstat64, stat64, open and so on) of PHP for some reasons and
as the result of it, I noticed that with the APC + very small two
pathes we can suppress most of realpath() calls (although currently
I'm not sure this is the correct method or not...):
http://eth.jp/php-cvs-20040506-delayed-fopen.patch.txt
(patch against current 4.3 tree, because APC is not yet fully
compatible with PHP 5)
http://eth.jp/apc-2.0.3-delayed-fopen.patch.txt
(patch against APC-2.0.3, current CVS-HEAD is somehow unstable...)
So please try and review if you're curious about suppressing
realpath() calls:)
Usage:
1) apply patches to current 4.3 tree, and APC-2.0.3
2) buidconf and configure PHP as always with --enable-delayed-fopen
option
3) build and install PHP and APC as always
4) add "delayed_fopen=1" entry to your php.ini
And details are as follows:
As the recent thread and some other threads show (which listed below),
PHP requires quite a few I/O system calls especially when large number
of scripts are include_once()ed. And these are not ignorable
for the websites with more than 1 million hits per hour although it
has nothing to do with small sites.
[Performance Consideration of 1 class per file]
http://marc.theaimsgroup.com/?l=php-dev&m=108279256414391&w=2
[Performance degradation]
http://www.phpbuilder.com/lists/php-developer-list/2003022/0226.php
The main concern here is the lstat64() by realpath(), and open() by
searching for include_paths (when many include_paths are set).
I think suppressing open() (which will result in ENOENT) is not so
easy (because we need some other new caching system for
include_paths), but perhaps we can easily reduce realpath() for
included scritpts with APC, because APC does not use an opned file
handle when cache hits.
So, my patch skips zend_open() until open_file_scanning() is called
inside zend_compile_file() when include_once() or require_once() is
called, so that zend_open() is not called when the target script is
cached in APC. As a result of this, we can reduce most of realpath()
calls by include_once() and required_once().
These patches are not yet verified well so comments are welcome!
Best regards,
Masaki Fujimoto
[EMAIL PROTECTED]
diff -ru APC-2.0.3.bak/apc_main.c APC-2.0.3/apc_main.c
--- APC-2.0.3.bak/apc_main.c Fri Mar 26 03:53:43 2004
+++ APC-2.0.3/apc_main.c Thu May 6 20:10:12 2004
@@ -166,6 +166,11 @@
/* search for the file in the cache */
cache_entry = apc_cache_find(APCG(cache), key);
if (cache_entry != NULL) {
+#if DELAYED_FOPEN
+ if (h->opened_path == NULL) {
+ h->opened_path = estrdup(cache_entry->filename);
+ }
+#endif /* DELAYED_FOPEN */
zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
apc_stack_push(APCG(cache_stack), cache_entry);
return cached_compile(TSRMLS_C);
Index: Zend/Zend.m4
===================================================================
RCS file: /repository/Zend/Attic/Zend.m4,v
retrieving revision 1.35.2.6
diff -u -r1.35.2.6 Zend.m4
--- Zend/Zend.m4 7 Oct 2003 22:49:27 -0000 1.35.2.6
+++ Zend/Zend.m4 6 May 2004 13:02:06 -0000
@@ -143,6 +143,14 @@
ZEND_MEMORY_LIMIT=no
])
+AC_ARG_ENABLE(delayed-fopen,
+[ --enable-delayed-fopen Delay fopen for include_once/require_once
+ until compilcation.], [
+ ZEND_DELAYED_FOPEN=$enableval
+],[
+ ZEND_DELAYED_FOPEN=no
+])
+
AC_ARG_ENABLE(zend-multibyte,
[ --enable-zend-multibyte Compile with zend multibyte support. ], [
ZEND_MULTIBYTE=$enableval
@@ -159,6 +167,9 @@
AC_MSG_CHECKING(whether to enable a memory limit)
AC_MSG_RESULT($ZEND_MEMORY_LIMIT)
+AC_MSG_CHECKING(whether to enable delayed fopen)
+AC_MSG_RESULT($ZEND_DELAYED_FOPEN)
+
AC_MSG_CHECKING(whether to enable Zend debugging)
AC_MSG_RESULT($ZEND_DEBUG)
@@ -191,6 +202,12 @@
AC_DEFINE(MEMORY_LIMIT, 0, [Memory limit])
fi
+if test "$ZEND_DELAYED_FOPEN" = "yes"; then
+ AC_DEFINE(DELAYED_FOPEN, 1, [Delayed fopen])
+else
+ AC_DEFINE(DELAYED_FOPEN, 0, [Delayed fopen])
+fi
+
if test "$ZEND_MULTIBYTE" = "yes"; then
AC_DEFINE(ZEND_MULTIBYTE, 1, [ ])
fi
Index: Zend/zend_execute.c
===================================================================
RCS file: /repository/Zend/Attic/zend_execute.c,v
retrieving revision 1.316.2.34
diff -u -r1.316.2.34 zend_execute.c
--- Zend/zend_execute.c 1 Apr 2004 22:05:38 -0000 1.316.2.34
+++ Zend/zend_execute.c 6 May 2004 13:02:07 -0000
@@ -2137,6 +2137,25 @@
int dummy = 1;
zend_file_handle
file_handle = {0};
+#if DELAYED_FOPEN
+ if (EG(delayed_fopen))
{
+
file_handle.type = ZEND_HANDLE_FILENAME;
+
file_handle.filename = inc_filename->value.str.val;
+
file_handle.free_filename = 0;
+ new_op_array =
zend_compile_file(&file_handle,
(EX(opline)->op2.u.constant.value.lval==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE)
TSRMLS_CC);
+ if
(!file_handle.opened_path) {
+
file_handle.opened_path = estrndup(inc_filename->value.str.val,
inc_filename->value.str.len);
+ }
+ if
(zend_hash_add(&EG(included_files), file_handle.opened_path,
strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) {
+ /*
nothing to do in this case */
+ } else {
+ /*
free ops */
+
destroy_op_array(new_op_array);
+
efree(new_op_array);
+
new_op_array = NULL;
+ }
+ } else
+#endif /* DELAYD_FOPEN */
if
(zend_open(inc_filename->value.str.val, &file_handle) == SUCCESS
&&
ZEND_IS_VALID_FILE_HANDLE(&file_handle)) {
Index: Zend/zend_globals.h
===================================================================
RCS file: /repository/Zend/Attic/zend_globals.h,v
retrieving revision 1.93.2.4
diff -u -r1.93.2.4 zend_globals.h
--- Zend/zend_globals.h 31 May 2003 01:37:43 -0000 1.93.2.4
+++ Zend/zend_globals.h 6 May 2004 13:02:07 -0000
@@ -211,6 +211,10 @@
char float_separator[1];
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
+
+#if DELAYED_FOPEN
+ zend_bool delayed_fopen;
+#endif /* DELAYED_FOPEN */
};
Index: main/main.c
===================================================================
RCS file: /repository/php-src/main/main.c,v
retrieving revision 1.512.2.53
diff -u -r1.512.2.53 main.c
--- main/main.c 9 Feb 2004 04:05:56 -0000 1.512.2.53
+++ main/main.c 6 May 2004 13:02:07 -0000
@@ -160,6 +160,20 @@
/* }}} */
#endif
+#if DELAYED_FOPEN
+/* {{{ PHP_INI_MH
+ */
+static PHP_INI_MH(OnChangeDelayedFopen)
+{
+ if (new_value) {
+ EG(delayed_fopen) = zend_atoi(new_value, new_value_length);
+ } else {
+ EG(delayed_fopen) = 0;
+ }
+ return SUCCESS;
+}
+/* }}} */
+#endif /* DELAYED_FOPEN */
/* {{{ php_disable_functions
*/
@@ -354,6 +368,9 @@
#if MEMORY_LIMIT
PHP_INI_ENTRY("memory_limit", "8M",
PHP_INI_ALL, OnChangeMemoryLimit)
#endif
+#if DELAYED_FOPEN
+ PHP_INI_ENTRY("delayed_fopen", "0",
PHP_INI_ALL, OnChangeDelayedFopen)
+#endif /* DELAYED_FOPEN */
PHP_INI_ENTRY("precision", "14",
PHP_INI_ALL, OnSetPrecision)
PHP_INI_ENTRY("sendmail_from", NULL,
PHP_INI_ALL, NULL)
PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM,
NULL)
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php