Hey: On Mon, Sep 14, 2015 at 6:57 PM, Dmitry Stogov <dmi...@zend.com> wrote: > The effect of this patch is really exiting to keep it disabled by default... > :) > > $ perf stat -e instructions,iTLB-loads,iTLB-load-misses,cycles > sapi/cgi/php-cgi -d opcache.enable_huge_code_pages=0 -T 10000 > /var/www/html/bench/wordpress-3.6/index.php > /dev/null > > 191,778,620,621 instructions # 0.81 insns per cycle > 178,497,016 iTLB-loads > 87,351,276 iTLB-load-misses # 48.94% of all iTLB > cache hits > 238,136,402,797 cycles > > 110.221114219 seconds time elapsed > > $ perf stat -e instructions,iTLB-loads,iTLB-load-misses,cycles > sapi/cgi/php-cgi -d opcache.enable_huge_code_pages=1 -T 10000 > /var/www/html/bench/wordpress-3.6/index.php > /dev/null > > 191,780,181,536 instructions # 0.83 insns per cycle > 39,017,004 iTLB-loads > 41,631,359 iTLB-load-misses # 106.70% of all iTLB > cache hits > 231,287,491,307 cycles > > 107.742837269 seconds time elapsed > > May be we should enable this by default in RC (may be also file cache) and > make decision based on feedback? > For me, it is a safe improvement, and it shouldn't break any functions (except the perf report/anno symbols lost, which actually is a limitation by current perf tool self , maybe it could be fixed later).
and it give us a significant improvement, I'd like to see it to be enabled by default. thanks > Thanks. Dmtiry. > > > > On Mon, Sep 14, 2015 at 1:34 PM, Dmitry Stogov <dmi...@php.net> wrote: >> >> Commit: 669f0b39b184593e01e677360fd79b2b63058ca0 >> Author: Dmitry Stogov <dmi...@zend.com> Mon, 14 Sep 2015 >> 13:34:17 +0300 >> Parents: 145708b658d0a60b738dde1a942dea9032f2f54e >> Branches: master >> >> Link: >> http://git.php.net/?p=php-src.git;a=commitdiff;h=669f0b39b184593e01e677360fd79b2b63058ca0 >> >> Log: >> Added an experemental ability to move PHP code pages (PHP TEXT segment) >> into HUGE pages. >> PHP should be configured and built with --enable-huge-code-pages, OS >> should be configured to provide huge pages. >> It's possible to enable/disable this future in php.ini through >> opcache.enable_huge_code_pages=0/1. >> The feature was tested on Linux and provided 2% improvement on real-life >> apps, because of 2-3 times reduction in number of iTLB misses. >> >> Changed paths: >> M ext/opcache/ZendAccelerator.c >> M ext/opcache/ZendAccelerator.h >> M ext/opcache/config.m4 >> M ext/opcache/zend_accelerator_module.c >> >> >> Diff: >> diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c >> index 905700e..2c3d9a4 100644 >> --- a/ext/opcache/ZendAccelerator.c >> +++ b/ext/opcache/ZendAccelerator.c >> @@ -2480,6 +2480,92 @@ static void accel_gen_system_id(void) >> } >> #endif >> >> +#ifdef HAVE_HUGE_CODE_PAGES >> +# ifndef _WIN32 >> +# include <sys/mman.h> >> +# include <sys/prctl.h> >> +# ifndef MAP_ANON >> +# ifdef MAP_ANONYMOUS >> +# define MAP_ANON MAP_ANONYMOUS >> +# endif >> +# endif >> +# ifndef MAP_FAILED >> +# define MAP_FAILED ((void*)-1) >> +# endif >> +# endif >> + >> +# if defined(MAP_HUGETLB) || defined(MADV_HUGEPAGE) >> +static int accel_remap_huge_pages(void *start, size_t size, const char >> *name, size_t offset) >> +{ >> + void *ret = MAP_FAILED; >> + void *mem; >> + int fd; >> + >> + fd = open(name, O_RDONLY); >> + if (fd < 0) { >> + return -1; >> + } >> + mem = mmap(NULL, size, >> + PROT_READ, >> + MAP_PRIVATE | MAP_FILE | MAP_POPULATE, >> + fd, offset); >> + if (mem == MAP_FAILED) { >> + close(fd); >> + return -1; >> + } >> + >> +#ifdef MAP_HUGETLB >> + ret = mmap(start, size, >> + PROT_READ | PROT_WRITE | PROT_EXEC, >> + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_HUGETLB, >> + -1, 0); >> +#endif >> +#ifdef MADV_HUGEPAGE >> + if (ret == MAP_FAILED) { >> + ret = mmap(start, size, >> + PROT_READ | PROT_WRITE | PROT_EXEC, >> + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, >> + -1, 0); >> + madvise(start, size, MADV_HUGEPAGE); >> + } >> +#endif >> + if (ret == start) { >> + memcpy(start, mem, size); >> + mprotect(start, size, PROT_READ | PROT_EXEC); >> + } >> + munmap(mem, size); >> + close(fd); >> + >> + return (ret == start) ? 0 : -1; >> +} >> + >> +static void accel_move_code_to_huge_pages(void) >> +{ >> + FILE *f; >> + long unsigned int huge_page_size = 2 * 1024 * 1024; >> + >> + f = fopen("/proc/self/maps", "r"); >> + if (f) { >> + long unsigned int start, end, offset, inode; >> + char perm[5], dev[6], name[MAXPATHLEN]; >> + int ret; >> + >> + ret = fscanf(f, "%lx-%lx %4s %lx %5s %ld %s\n", &start, >> &end, perm, &offset, dev, &inode, name); >> + if (ret == 7 && perm[0] == 'r' && perm[1] == '-' && >> perm[2] == 'x' && name[0] == '/') { >> + long unsigned int seg_start = >> ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size); >> + long unsigned int seg_end = (end & >> ~(huge_page_size-1L)); >> + >> + if (seg_end > seg_start) { >> + zend_accel_error(ACCEL_LOG_DEBUG, "remap >> to huge page %lx-%lx %s \n", seg_start, seg_end, name); >> + accel_remap_huge_pages((void*)seg_start, >> seg_end - seg_start, name, offset + seg_start - start); >> + } >> + } >> + fclose(f); >> + } >> +} >> +# endif >> +#endif /* HAVE_HUGE_CODE_PAGES */ >> + >> static int accel_startup(zend_extension *extension) >> { >> zend_function *func; >> @@ -2505,6 +2591,16 @@ static int accel_startup(zend_extension *extension) >> accel_gen_system_id(); >> #endif >> >> +#ifdef HAVE_HUGE_CODE_PAGES >> + if (ZCG(accel_directives).enable_huge_code_pages && >> + (strcmp(sapi_module.name, "cli") == 0 || >> + strcmp(sapi_module.name, "cli-server") == 0 || >> + strcmp(sapi_module.name, "cgi-fcgi") == 0 || >> + strcmp(sapi_module.name, "fpm-fcgi") == 0)) { >> + accel_move_code_to_huge_pages(); >> + } >> +#endif >> + >> /* no supported SAPI found - disable acceleration and stop >> initialization */ >> if (accel_find_sapi() == FAILURE) { >> accel_startup_ok = 0; >> diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h >> index 6ce4613..da3fc66 100644 >> --- a/ext/opcache/ZendAccelerator.h >> +++ b/ext/opcache/ZendAccelerator.h >> @@ -219,6 +219,9 @@ typedef struct _zend_accel_directives { >> zend_bool file_cache_only; >> zend_bool file_cache_consistency_checks; >> #endif >> +#ifdef HAVE_HUGE_CODE_PAGES >> + zend_bool enable_huge_code_pages; >> +#endif >> } zend_accel_directives; >> >> typedef struct _zend_accel_globals { >> diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 >> index 856f24a..d8f84e2 100644 >> --- a/ext/opcache/config.m4 >> +++ b/ext/opcache/config.m4 >> @@ -8,12 +8,19 @@ PHP_ARG_ENABLE(opcache, whether to enable Zend OPcache >> support, >> PHP_ARG_ENABLE(opcache-file, whether to enable file based caching >> (experimental), >> [ --enable-opcache-file Enable file based caching], no) >> >> +PHP_ARG_ENABLE(huge-code-pages, whether to enable copying PHP CODE pages >> into HUGE PAGES (experimental), >> +[ --enable-huge-code-pages Enable copying PHP CODE pages into HUGE >> PAGES], no) >> + >> if test "$PHP_OPCACHE" != "no"; then >> >> if test "$PHP_OPCACHE_FILE" == "yes"; then >> AC_DEFINE(HAVE_OPCACHE_FILE_CACHE, 1, [Define to enable file based >> caching (experimental)]) >> fi >> >> + if test "$PHP_HUGE_CODE_PAGES" == "yes"; then >> + AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE >> pages into HUGE PAGES (experimental)]) >> + fi >> + >> AC_CHECK_FUNC(mprotect,[ >> AC_DEFINE(HAVE_MPROTECT, 1, [Define if you have mprotect() function]) >> ]) >> diff --git a/ext/opcache/zend_accelerator_module.c >> b/ext/opcache/zend_accelerator_module.c >> index eb93f59..5dfa8c1 100644 >> --- a/ext/opcache/zend_accelerator_module.c >> +++ b/ext/opcache/zend_accelerator_module.c >> @@ -309,6 +309,9 @@ ZEND_INI_BEGIN() >> STD_PHP_INI_ENTRY("opcache.file_cache_only" , "0" >> , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.file_cache_only, >> zend_accel_globals, accel_globals) >> STD_PHP_INI_ENTRY("opcache.file_cache_consistency_checks" , "1" >> , PHP_INI_SYSTEM, OnUpdateBool, >> accel_directives.file_cache_consistency_checks, zend_accel_globals, >> accel_globals) >> #endif >> +#ifdef HAVE_HUGE_CODE_PAGES >> + STD_PHP_INI_BOOLEAN("opcache.enable_huge_code_pages" , "1" >> , PHP_INI_SYSTEM, OnUpdateBool, >> accel_directives.enable_huge_code_pages, zend_accel_globals, >> accel_globals) >> +#endif >> ZEND_INI_END() >> >> static int filename_is_in_cache(zend_string *filename) >> >> >> -- >> PHP CVS Mailing List (http://www.php.net/) >> To unsubscribe, visit: http://www.php.net/unsub.php >> > -- Xinchen Hui @Laruence http://www.laruence.com/ -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php