php-fpm7.1 mmap/munmap (очень) низкая производительность в виртуализированных системах (огромная страница)

Мой процесс php-fpm сталкивается с проблемами производительности в Ubuntu 14.04 LTS (сервер Nginx, база данных MariaDB).

strace -f $(pidof php-fpm7.1 | sed 's/\([0-9]*\)/\-p \1/g')

Дал мне

<... epoll_wait resumed> {}, 1, 1000) = 0
[pid 32533] epoll_wait(8, {}, 1, 103)   = 0
[pid 32533] epoll_wait(8,  <unfinished ...>
[pid 32535] mmap(NULL, 2097152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd933fdd000
[pid 32535] munmap(0x7fd933fdd000, 2097152) = 0
[pid 32535] mmap(NULL, 4190208, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd933dde000
[pid 32535] munmap(0x7fd933dde000, 139264) = 0
[pid 32535] munmap(0x7fd934000000, 1953792) = 0
[pid 32535] madvise(0x7fd933e00000, 2097152, MADV_HUGEPAGE) = 0
[pid 32533] <... epoll_wait resumed> {}, 1, 897) = 0
[pid 32533] epoll_wait(8, {}, 1, 1000)  = 0
[pid 32533] epoll_wait(8, {}, 1, 1000)  = 0
[pid 32533] epoll_wait(8,  <unfinished ...>
[pid 32535] mmap(NULL, 2097152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd933c00000
[pid 32535] madvise(0x7fd933c00000, 2097152, MADV_HUGEPAGE) = 0
[pid 32533] <... epoll_wait resumed> {}, 1, 1000) = 0
[pid 32533] epoll_wait(8, {}, 1, 1000)  = 0
[pid 32533] epoll_wait(8, {}, 1, 1000)  = 0
[pid 32533] epoll_wait(8, {}, 1, 1000)  = 0
[pid 32533] epoll_wait(8,  <unfinished ...>
[pid 32535] mmap(NULL, 2097152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd933a00000
[pid 32535] madvise(0x7fd933a00000, 2097152, MADV_HUGEPAGE) = 0
[pid 32533] <... epoll_wait resumed> {}, 1, 1000) = 0
[pid 32533] epoll_wait(8,  <unfinished ...>
[pid 32535] open("/usr/share/zoneinfo/UTC", O_RDONLY) = 7
[pid 32535] fstat(7, {st_mode=S_IFREG|0644, st_size=118, ...}) = 0
[pid 32535] read(7, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20) = 20
[pid 32535] lseek(7, 0, SEEK_SET)       = 0
[pid 32535] mmap(NULL, 118, PROT_READ, MAP_SHARED, 7, 0) = 0x7fd946835000
[pid 32535] close(7)                    = 0
[pid 32535] munmap(0x7fd946835000, 118) = 0
[pid 32535] pwrite(5, "_sf2_attributes|a:2:{s:14:\"_secu"..., 979, 0) = 979
[pid 32535] close(5)                    = 0
[pid 32535] mmap(NULL, 2097152, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd933200000
[pid 32535] madvise(0x7fd933200000, 2097152, MADV_HUGEPAGE) = 0

Я пробовал с php-fpm7.0, PHPMod7.1, но те же проблемы.

CPU загружен до 100% на запросах с небольшим объемом данных.

Конфигурации являются стандартными.

На дублированном экземпляре php5.6-fpm работает хорошо.

Изменить: возможно связанный скрипт PHP продолжает выполнять mmap/munmap

Изменить: я пытался включить огромные страницы https://wiki.debian.org/Hugepages. cat /proc/meminfo | grep Huge дал мне

AnonHugePages:    108544 kB
HugePages_Total:     512
HugePages_Free:      497
HugePages_Rsvd:       50
HugePages_Surp:        0
Hugepagesize:       2048 kB

но все та же проблема.

Редактировать: я пытался включить/отключить OPCache, также установить opcache.huge_code_pages=0, безрезультатно. На http://php.net/ нет документации об огромных страницах.


person Etienne Gautier    schedule 10.07.2017    source источник
comment
Теперь происходит на Ubuntu 16.04 LTS.   -  person Etienne Gautier    schedule 05.09.2017
comment
Какой гипервизор используется?   -  person Wassim Dhif    schedule 06.09.2017
comment
Знаете ли вы, вызывает ли PHP mmap()/munmap() напрямую или через malloc()/free()? Если это через malloc()/free(), вы можете попробовать установить переменную среды M_MMAP_THRESHOLD на эквивалент чего-то вроде 4 МБ или 8 МБ, чтобы процесс использовал обычную память кучи для выделений 2 МБ, которые вы видите. Подробнее см. справочную страницу mallopt().   -  person Andrew Henle    schedule 06.09.2017
comment
@WassimDhif ESXI   -  person Etienne Gautier    schedule 06.09.2017
comment
@AndrewHenle Спасибо, я попробую, но я уверен, что он использует mmap/munmap() напрямую.   -  person Etienne Gautier    schedule 06.09.2017
comment
См. developers-club.com/posts/270685   -  person Etienne Gautier    schedule 06.09.2017
comment
@EtienneGautier Имейте в виду, что код developers-club.com/posts/270685 довольно плохой. Среди других проблем он приводит void * к unsigned long, чтобы попытаться выровнять полученный указатель. void * не обязательно соответствует long. Например, связанный код не будет работать в 64-битной Windows, что вряд ли является необычной платформой. См. en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models   -  person Andrew Henle    schedule 06.09.2017
comment
Вы правы, спасибо за информацию.   -  person Etienne Gautier    schedule 06.09.2017


Ответы (3)


Я не уверен на 100%, сталкиваемся ли мы здесь с одной и той же проблемой, но это самое близкое, что я смог найти в своем поиске переполнения стека для моей проблемы.

Мои выводы были на виртуальной машине со следующими характеристиками.

ЦП: 16

ОЗУ: 16 ГБ

ОС: Ubuntu 16.04.4 LTS

Контейнеры: LXD с файловой системой ZFS с использованием блочных устройств.

Версия PHP: 7.1

Я запускаю несколько контейнеров LXD под управлением MariaDB, Nginx и PHP-FPM 7.1. Это были среды разработки, поэтому я только траффик попадал на сервер. Работающее приложение было построено с использованием фреймворка Symfony.

Я заметил очень медленное время загрузки страницы. Я постоянно ждал более минуты, пока страница загружалась в режиме разработки. Я также не тратил много времени на подтверждение этого, но сценарии CLI также казались довольно медленными. Я пытался настроить все виды настроек PHP (кеши realpath, включение/выключение opcache/различные настройки и т. д.), но ничего не сработало.

Я мог постоянно отслеживать один из процессов PHP-FPM и видеть один системный вызов, который казался медленным. Все остальные вызовы пролетали незаметно, но он много раз застревал на следующем вызове на протяжении всего жизненного цикла процесса.

madvise(0x7f4dcca00000, 2097152, MADV_HUGEPAGE) = 0

Короче говоря, я смог радикально изменить производительность этого приложения, отключив THP. Я выполнил следующие команды на хосте LXD, и время загрузки страницы изменилось как день и ночь.

sysctl -w vm.nr_hugepages=0
echo never > /sys/kernel/mm/transparent_hugepage/enabled

Я знаю, что Redis рекомендует отключать THP из-за проблем с производительностью, связанных с копированием при записи. Я также знаю, что файловые системы ZFS также копируют при записи, так что, возможно, эта проблема связана?

person William Byrne    schedule 04.04.2018
comment
Я знал это! Я не мог один столкнуться с этой проблемой, она слишком велика. К сожалению, я больше не работаю в этой среде, боюсь, у меня нет времени воспроизвести это поведение. Кстати, приложение также было создано с помощью Symfony. - person Etienne Gautier; 08.04.2018
comment
То же самое здесь, ZFS, LXC и Symfony. Кроме того, у вас есть большая база данных и работающее java-приложение, требующее памяти. Подтверждено в Linux 4.9 и 4.19. потребовалось около 1 недели, чтобы появиться после перезагрузки. - person bhelm; 08.01.2019

Какое значение выбрано в скобках, когда вы делаете

cat /sys/kernel/mm/transparent_hugepage/enabled 

Убедитесь, что это либо madvise (поскольку mmaps явно запрашивают прозрачные огромные страницы с помощью MADV_HUGEPAGE), либо всегда.

Следующим шагом будет проверка того, не слишком ли занято ваше ядро ​​сжатием страниц (THP должен найти непрерывный кусок памяти размером 2 МБ для огромной страницы, что может быть затруднительно, если физическая память фрагментирована). Посмотрите на цифры:

cat /proc/vmstat |grep compact

До и после вашего бега. Они выросли?

Следующим шагом будет поймать часть ядра стека вашего процесса:

cat /proc/YOUR_PROCESS_PID/stack

Другие полезные команды:

cat /proc/buddyinfo

чтобы увидеть фрагментацию физической памяти. Найдите два последних столбца. Это свободные участки памяти размером 2 МБ и 4 МБ. Еще один :

cat /proc/pagetypeinfo

и ищите неподвижные блоки страниц.

person Jacek Tomaka    schedule 29.10.2017
comment
Спасибо за ответ, я пока не могу проводить тесты в реальной жизни, но я дам вам знать, когда смогу. - person Etienne Gautier; 20.11.2017

У меня сработало отключение поддержки прозрачных огромных страниц на хосте:

echo never > /sys/kernel/mm/transparent_hugepage/enabled

В моем случае проблема возникла при запуске композитора в контейнере LXD на бэкенде ZFS.

person user13097    schedule 31.12.2018