Кэшеры байткода

fixxxer

К.О.
Партнер клуба
Мне тоже меркуриал больше нравится, но давай все же будем все делать на гитхабе, чтобы Тони мог смерджить все в свою ветку.
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
fixxxer
Часть запушил, под 5.4 компилируется, запускать боюсь :), да и не запуститься он под 5.4 :(

optimize.c - еще немного заифдефить осталось

git://github.com/Irokez8086/eaccelerator.git
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Недавно на дотдебе пробегал APC для 5.4, кто-нибудь тестил?
 

alekciy

Новичок
Касательно eAccelerator мне кажется стоило бы начать с фикса багов. Вот такой баг есть: mod_fcgid +eAccelerator + SHM. У меня сборка 0.9.6.1 для PHP 5.3.8 крутиться на debian, так там он использует mmap для скриптов и не юзает ipcs (видно по strace), но зачем то еще и 32Мб от SHM откусывает.
 

tony2001

TeaM PHPClub
Касательно eAccelerator мне кажется стоило бы начать с фикса багов. Вот такой баг есть: mod_fcgid +eAccelerator + SHM. У меня сборка 0.9.6.1 для PHP 5.3.8 крутиться на debian, так там он использует mmap для скриптов и не юзает ipcs (видно по strace), но зачем то еще и 32Мб от SHM откусывает.
Надо было просто потратить на 5 минут больше и разобраться чуток, вместо того чтобы сходу бросаться патчить configure (который генерится из config.m4 и не предназначен для человека).
На самом деле, всё более чем просто. У EA есть в configure опция:
$ ./configure --help | grep shm
--with-eaccelerator-shm-type eAccelerator shared memory type: sysvipc, mmap_anon, mmap_zero, mmap_file
тут даже и возможные значения перечислены.

Пересобираем с ./configure --with-eaccelerator-shm-type=mmap_anon и всё работает:
(phpinfo())
Shared memory type mmap_anon
 

alekciy

Новичок
Надо было просто потратить на 5 минут больше и разобраться чуток, вместо того чтобы сходу бросаться патчить configure (который генерится из config.m4 и не предназначен для человека).
На самом деле, всё более чем просто. У EA есть в configure опция:
В оригинальном EA её нет.

Пересобираем с ./configure --with-eaccelerator-shm-type=mmap_anon и всё работает:
А это наиболее предпочитаемый вариант?

У меня вот так:
Код:
# ./configure --with-php-config=/opt/php/5.3.8/bin/php-config --with-eaccelerator-shm-type=sysvipc --with-eaccelerator-sem-type=sysvipc > log.txt
# grep -i semaphores log.txt
checking for eAccelerator semaphores type... sysvipc
checking for spinlock semaphores support... yes
checking for pthread semaphores support... yes
checking for pthread rwlock semaphores support... yes
checking for posix semaphores support... no
checking for sysvipc semaphores support... no
checking for fcntl semaphores support... yes
checking for flock semaphores support... yes
checking for semaphores type...
не сработало. Как я понимаю потому что configure решил, что "sysvipc semaphores support... no". Но вместе с тем оно есть:
Код:
# php -i | grep sem
Configure Command =>  './configure'  '--prefix=/opt/php/5.3.8' '--with-config-file-path=/opt/php/5.3.8/etc/' '--with-config-file-scan-dir=/opt/php/5.3.8/etc/conf.d/' '--enable-fpm' '--with-fpm-user=php-fpm' '--with-fpm-group=php-fpm' '--enable-bcmath' '--enable-calendar' '--enable-exif' '--enable-ftp' '--with-gd' '--with-freetype-dir' '--with-jpeg-dir' '--enable-gd-native-ttf' '--enable-gd-jis-conv' '--enable-mbstring' '--enable-zip' '--with-pcre-regex' '--with-zlib' '--with-mysql' '--with-mysqli' '--with-pgsql' '--with-mcrypt' '--with-gettext' '--with-imap' '--with-kerberos' '--with-imap-ssl' '--enable-intl' '--with-openssl' '--with-pdo-mysql' '--enable-shmop' '--enable-sysvsem' '--enable-sysvshm' '--enable-sysvmsg' '--without-pear'
sysvsem
Возможно я что-то не так понимаю?
 

alekciy

Новичок
И такой вопрос. Если собрано с поддержкой sysvipc, то по идее в выводе strace долны быть видны вызовы этой подсистемы? Просто я их что-то не могу найти:
Код:
# tail -n +8 ~/ou_1 | head -n 17
18744 read(4, "\1\4\0\1\0\0\0\0", 8)    = 8
18744 setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={60, 0}}, NULL) = 0
18744 rt_sigaction(SIGPROF, {0x76cf00, [PROF], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, {0x76cf00, [PROF], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, 8) = 0
18744 rt_sigprocmask(SIG_UNBLOCK, [PROF], NULL, 8) = 0
18744 rt_sigaction(SIGSEGV, {0x7f772ba98c80, [SEGV], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, {SIG_DFL, [SEGV], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, 8) = 0
18744 rt_sigaction(SIGFPE, {0x7f772ba98c80, [FPE], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, {SIG_DFL, [FPE], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, 8) = 0
18744 rt_sigaction(SIGBUS, {0x7f772ba98c80, [BUS], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, {SIG_DFL, [BUS], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, 8) = 0
18744 rt_sigaction(SIGILL, {0x7f772ba98c80, [ILL], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, {SIG_DFL, [ILL], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, 8) = 0
18744 rt_sigaction(SIGABRT, {0x7f772ba98c80, [ABRT], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, {SIG_DFL, [ABRT], SA_RESTORER|SA_RESTART, 0x7f772ea37480}, 8) = 0
18744 open("/www/rurbox.ru/public/test.php", O_RDONLY) = 5
18744 fstat(5, {st_mode=S_IFREG|0644, st_size=4847, ...}) = 0
18744 getcwd("/www/rurbox.ru/public", 4095) = 22
18744 chdir("/www/rurbox.ru/public")    = 0
18744 setitimer(ITIMER_PROF, {it_interval={0, 0}, it_value={30, 0}}, NULL) = 0
18744 stat("/www/rurbox.ru/public/test.php", {st_mode=S_IFREG|0644, st_size=4847, ...}) = 0
18744 write(2, "EACCELERATOR hit: \"/www/rurbox.ru/public/test.php\"\n", 51) = 51
18744 close(5)                          = 0
open/close есть, но ни чего близкого к sysv не нахожу. Или все происходит через сигналы к мастер процессу (но и там вызовов я не вижу)?
 

tony2001

TeaM PHPClub
>В оригинальном EA её нет.
хм. да, действительно.

>А это наиболее предпочитаемый вариант?
я лично не вижу особой разницы.

>не сработало.
подробности в config.log
 

alekciy

Новичок
>я лично не вижу особой разницы.
При sysv видна инфа по используемой памяти через ipcs -m, в случае с mmap такое получить не выйдет. Кроме того, как я понимаю в mmap работает ленивый вариант загрузки: "нужны Х данные - ой, данных в ОЗУ нет, лезем на диск" в том время как shm у нас всегда в озу и просто аттачиться к адресное пространство процесса. Если не ошибаюсь shm будет вытеснено на диск только в одном случае - свопинг системы, но в штатном режиме система свопить и не должна.

>подробности в config.log
А что там нужно искать? Я grep-ал лог, и там просто пишется, что "sysvipc semaphores support... no"

Код:
# grep -i sem config.log
  $ ./configure --with-php-config=/opt/php/5.3.8/bin/php-config --with-eaccelerator-shm-type=sysvipc --with-eaccelerator-sem-type=sysvipc
configure:4462: checking whether to include eAccelerator disassembler
configure:4581: checking for eAccelerator semaphores type
configure:5106: checking whether union semun is defined in sys/sem.h
|   #include <sys/sem.h>
|   union semun arg;
|   semctl(0, 0, 0, arg);
| #define MM_SEM_NONE
configure:5402: checking for spinlock semaphores support
configure:5429: checking for pthread semaphores support
configure:5454: checking for pthread rwlock semaphores support
configure:5479: checking for posix semaphores support
/tmp/mm.sem.WIfgtn: No such file or directory
| #define MM_SEM_POSIX
| #define MM_TEST_SEM
configure:5505: checking for sysvipc semaphores support
| #define MM_SEM_IPC
| #define MM_TEST_SEM
configure:5541: checking for fcntl semaphores support
configure:5566: checking for flock semaphores support
configure:5636: checking for semaphores type
configure:5645: error: Semaphores type 'sysvipc' is not available
CONFIGURE_COMMAND=' '\''./configure'\''  '\''--with-php-config=/opt/php/5.3.8/bin/php-config'\'' '\''--with-eaccelerator-shm-type=sysvipc'\'' '\''--with-eaccelerator-sem-type=sysvipc'\'''
CONFIGURE_OPTIONS=' '\''--with-php-config=/opt/php/5.3.8/bin/php-config'\'' '\''--with-eaccelerator-shm-type=sysvipc'\'' '\''--with-eaccelerator-sem-type=sysvipc'\'''
и это при том, что:
Код:
# php -m | grep sys
sysvmsg
sysvsem
sysvshm
т.е. из php с самафорами работать получается.

Возникал еще такой вариант источника проблемы - не заданные userid. Но я задавал опцию --with-eaccelerator-userid=0 (и с обычными user id в духе 2000) и тоже валиться.

Вообще изучение лога наталкивает на мысль, что дело не в том, что не обнаруживается sysv sem, а в том, что валятся тесты при проверке API:

Код:
configure:5106: checking whether union semun is defined in sys/sem.h
configure:5126: cc -c -g -O2  conftest.c >&5
conftest.c: In function 'main':
conftest.c:37:15: error: storage size of 'arg' isn't known
configure:5126: $? = 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME ""
| #define PACKAGE_TARNAME ""
| #define PACKAGE_VERSION ""
| #define PACKAGE_STRING ""
| #define PACKAGE_BUGREPORT ""
| #define PACKAGE_URL ""
| #define HAVE_MPROTECT 1
| #define WITH_EACCELERATOR_CRASH_DETECTION 1
| #define WITH_EACCELERATOR_OPTIMIZER 1
| #define COMPILE_DL_EACCELERATOR 1
| #define HAVE_EACCELERATOR 1
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_LIMITS_H 1
| #define HAVE_SYS_PARAM_H 1
| #define HAVE_SCHED_H 1
| /* end confdefs.h.  */
|
|   #include <sys/types.h>
|   #include <sys/ipc.h>
|   #include <sys/sem.h>
|
| int
| main ()
| {
|
|   union semun arg;
|   semctl(0, 0, 0, arg);
|
|   ;
|   return 0;
| }
configure:5135: result: no
...
configure:5505: checking for sysvipc semaphores support
configure:5517: cc -o conftest -g -O2   conftest.c  >&5
In file included from conftest.c:33:0:
/root/install/php-5.3.8/ext/tony2001-eaccelerator/mm.c: In function 'mm_init_lock':
/root/install/php-5.3.8/ext/tony2001-eaccelerator/mm.c:428:22: error: 'EA_USERID' undeclared (first use in this function)
/root/install/php-5.3.8/ext/tony2001-eaccelerator/mm.c:428:22: note: each undeclared identifier is reported only once for each function it appears in
configure:5517: $? = 1
configure: program exited with status 1
configure: failed program was:
| /* confdefs.h */
| #define PACKAGE_NAME ""
| #define PACKAGE_TARNAME ""
| #define PACKAGE_VERSION ""
| #define PACKAGE_STRING ""
| #define PACKAGE_BUGREPORT ""
| #define PACKAGE_URL ""
| #define HAVE_MPROTECT 1
| #define WITH_EACCELERATOR_CRASH_DETECTION 1
| #define WITH_EACCELERATOR_OPTIMIZER 1
| #define COMPILE_DL_EACCELERATOR 1
| #define HAVE_EACCELERATOR 1
| #define STDC_HEADERS 1
| #define HAVE_SYS_TYPES_H 1
| #define HAVE_SYS_STAT_H 1
| #define HAVE_STDLIB_H 1
| #define HAVE_STRING_H 1
| #define HAVE_MEMORY_H 1
| #define HAVE_STRINGS_H 1
| #define HAVE_INTTYPES_H 1
| #define HAVE_STDINT_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_UNISTD_H 1
| #define HAVE_LIMITS_H 1
| #define HAVE_SYS_PARAM_H 1
| #define HAVE_SCHED_H 1
| #define HAVE_BUILTIN_ATOMIC 1
| #define MM_SHM_IPC 1
| #define EAC_SHM_TYPE "sysvipc"
| /* end confdefs.h.  */
| #define MM_SEM_IPC
| #define MM_TEST_SEM
| #include "/root/install/php-5.3.8/ext/tony2001-eaccelerator/mm.c"
|
configure:5527: result: no
Как я понимаю несмотря за явно переданный user id через опция configury он "'EA_USERID' undeclared" внутри mm_init_lock() в mm.c.
 

alekciy

Новичок
Не работает, если --with-eaccelerator-userid=0 и опции для configure не заключены в кавычки. Для других случаев configure дорабатывает корректно и без заключения в кавычки:
Код:
./configure "--with-php-config=/opt/php/5.3.8/bin/php-config --with-eaccelerator-shm-type=sysvipc --with-eaccelerator-sem-type=sysvipc --with-eaccelerator-userid=0"
но тогда make не работает.

А для чего вообще задавать отдельного юзера с случае с семафорами? Для shm этого же не требуется. Собрал не с root юзером, права при этом выставляются в 600. Поэтому рабочие процессы запущенные из под другого юзера (т.е. не того, что был указан в --with-eaccelerator-userid) откэшить скрипты уже не могут. В лог ругается в духе "WARNING: [pool ] child 8140 said into stderr: "EACCELERATOR can't cache:". Если пересобрать без --with-eaccelerator-sem-type=sysvipc (дефолтно rwlock получается), то начинает работать и для других воркеров. В принципе и с rwlock работает шустро. Меня больше другой волнует. Если используется "Shared memory type: sysvipc", то я же по идее должен в strace видеть вызовы shm? Но я их там не нахожу. Возможно ли, что при этом используется какой-то другой, не ipcs, механизм?

P.S. Ipcs меня привлекает тем, что он быстр, а размер выделенного сегмента виден, на выделенный сегмент можно накладывать права доступа, ограничивать на уровне ОС его размер, по нему можно даже получить статистику когда он был создан и время последнего обращения. Работа с ним даже из PHP скрипта быстрее (в том смысле что часть логики получения данных в самом скрипте), чем с тем же memcached слушащий unix socket и вариант работы через extension (Version: 2.2.6 ), раза в 4. Поэтому мне shm видится очень заманчивым местом складирования байткода.
 

tony2001

TeaM PHPClub
Да, 0 не работает, а должен?
Надо ли PHP запускать из-под рута?

>опции для configure не заключены в кавычки.
Вот это не понял - ты о чем?

>А для чего вообще задавать отдельного юзера с случае с семафорами?
Поищи в mm.c строку EA_USERID.
В man semctl есть много текста про это.

>Собрал не с root юзером, права при этом выставляются в 600. Поэтому рабочие процессы запущенные из под другого юзера откэшить скрипты уже не могут.

В этом ведь и есть весь смысл пермишенов.
Должно быть как-то по-другому?

>В принципе и с rwlock работает шустро.

Я его добавлял именно потому, что все остальные локи у меня тормозили нещадно.
Да и вообще - зачем лочить кэш эксклюзивно ВСЁ ВРЕМЯ, если ты в него пишешь активно только первые несколько часов, а потом совсем редко?
Это замедляет чтение, т.е. именно то, что мы пытаемся ускорить, и read-write lock как раз это решает.

>на выделенный сегмент можно накладывать права доступа,

Эээ.. на строку выше ты жаловался, что тебя права не устраивают.
 

fixxxer

К.О.
Партнер клуба
alekciy, мне кажется, ты в своих рассуждениях путаешь две разные вещи - shared memory и semaphores
 

alekciy

Новичок
>Надо ли PHP запускать из-под рута?
Рабочий процесс нет, не нужно. Я думал, что это как-то с мастер процессом свяазано. Вижу, что ошибался.
Видимо стоит пояснить контекст. PHP работает как php-fpm. При этом каждый пул запущен с правами разных юзеров. Мастер процесс понятное дело работает от root раскидывая запросы по воркерам. Теперь собираем EA c with-eaccelerator-userid и получаем, что работать нормально может только один из пулов. Возможно я что-то проглядел, но я не вижу, каким образом можно в такой ситуации задать для каждого пула юзера от которого будет работать EA. Вариант запуска для каждого юзера своего мастер процесса со своей сборкой EA мне видится бессмысленым, убивающим саму идею fpm пулов.

>Вот это не понял - ты о чем?
А я в посте выше привел как запускался configure, опции там в кавычки упакованы.

>Должно быть как-то по-другому?
Ну мне видится это так. Запускается мастер-процесс, смотрит в конфиг и для каждого пула в ipc создает в памяти сегмент заданного размера и семафоры, ставить для них owner и требуемые permission заданные для этого пула. Запоминает для каждого пула shmid и semid. Когда приходит запрос, то мастер-процесс вычисляет, какому воркеру его отдать в него же он передает shmid и semid. Рабочий процесс аттачится к памяти и самафорам, начинает отработку запроса. Мне схема видится логично, но возможно я что-то и упустил из виду? Просто если бы так работало, то можно было бы: контролировать выделяемый размер shm для каждого пула и не допустить пожирание ресурсов одним юзером, поскольку доступ к сегментам контролируется ОСью, то залезть в чужой сегмент (созданный для другого пула) просто не получится если там выставлено 600 (в перспективе же можно было бы иметь сегменты в которые могли бы лазить разные пулы в режиме read-only при выставлении там 640 прав или 644).
Собственно из самого PHP я с ipc для данных так и работаю, но хочется подобное и для кэширования байткода. К сожалению С знаю не так хорошо, что бы замахнуться на допилку сишного ext-на.
 

alekciy

Новичок
alekciy, мне кажется, ты в своих рассуждениях путаешь две разные вещи - shared memory и semaphores
Нет, не путаю. Я достаточно хорошо представляю разницу. Формулирую возможно не везде точно или перепрыгиваю местами с одного на другое. Но точно не путаю. Инфа 146%-ая!
 

ScDewt

Новичок
Прошу знающих eAccelerator прояснить ситуацию - некоторые настройки eAccelerator вызвали у меня ступор при вопросе:

где/кем будут храниться сессии при установленном eaccelerator и memcached при указании в php.ini -> session.save_handler = memcached и session.save_path = "tcp://localhost:11211"? Т.е. в memcached они будут или все таки eAccelerator их присвоит себе?

Вроде бы в php.ini явно указали что использовать для хранения сессий и путь куда лазить, но вот настройки в eAccelerator:
eaccelerator.cache_dir

This directory is used for the disk cache. eAccelerator stores precompiled code, session data, content and user entries here. The same data can be stored in shared memory (for quicker access). The default value is "/tmp/eaccelerator".
а так же
eaccelerator.keys | session | content

These settings control the places eAccelerator may cache user content. Possible values are......
....eaccelerator.keys = "shm_and_disk" eaccelerator.sessions = "shm_and_disk" eaccelerator.content = "shm_and_disk"
чего то сбивают меня с толку. Может я не правильно понимаю "sessions" в контексте eAccelerator - может это совсем другие сессионые данные? Если есть ссылки для чтения - поделитесь, а то с гугл со мной не дружит по этому вопросу и выдает одни и те же настройки.
 

MiksIr

miksir@home:~$
Это указывает, где eaccelerator будет хранить данные (в памяти или/и на диске в указанной директории), _если_ его сделают хранителем этих сессий.
 

alekciy

Новичок
tony2001
В логах постоянно висят сообщения формата:
Код:
[11-Sep-2012 02:04:40] WARNING: [pool site2] child 8577 said into stderr: "EACCELERATOR hit: "/www/site2/wp-includes/plugin.php""
как я понимаю задуманный информировать о том, что было попадание в кэш. Но почему тогда обозначено как WARNING и почему в stderr... Так специально задумано? Просто сильно это лог мусорит и хочет это отключить.
 
Сверху