Pull to refresh

Comments 56

UFO just landed and posted this here
Автор патч этот не примет, мы проходили это :)

А не описать тут — банальная лень и не желание копипейстить текст.
UFO just landed and posted this here
Хорошо, не один еще патч он мой не принял. И я пока не вижу смысла пропихивать его в upstream.
UFO just landed and posted this here
Начнем мы с вопроса ноль. Ты вообще кто? И где я могу почитать твой код?
UFO just landed and posted this here
Конечно не приймет, вы же просто выцепили аллокатор с OpenBSD и написали врапперы над его функциями для nginx…

И почему из FreeBSD, почему не jemalloc?
1) Этот аллокатор пришлось доделать

2) я не знал про jemalloc, спасибо, пойду смотреть.

У меня задача ставилась внести в nginx под linux аллокатор на mmap/munmap, я взял первый попавшийся мне аллокатор (так получилось что из openbsd)
Обязательно посмотрите jemalloc, он очень хорош, особенно насчет фрагментации памяти.

И я думаю, что лучшим выходом будет не подобным образом с помощью макросов подменять malloc и прочие функции для работы с аллокаторами, а написать обертку что-то типа ng_alloc, которая по-дефолту будет вызывать malloc и прочие стандартные функции аллокатора соответственно. И ключ компиляции, что-то типа OBSD_ALLOCATOR_ENABLED, и если он выставлен ng_alloc будет вызывать ngx_obsd_malloc. И я думаю такой пач имеет больше шансов быть принятым, так как для многих он может быть выходом.
За идею спасибо.

/me рад что есть тут еще люди, ради которых стоит сюда писать.
Реализовал. Потребление памяти осталось таким же. idle выше на obsd аллокаторе (что интересно разница между gnu libc и jemalloc по idle не заметна).

Выкладывать это отдельным постом?
Я думаю достаточно обновить топик, и выложить результаты тестов для всех аллокаторов :)
Последним я буду заниматься явно не на выходных :)

Но на глаз лучше рвет всех obsd-like, да и проще он в разы. Так что его тюнить и буду я дальше.
Посмотрел я на jmalloc. Он более сложный чем аллокатор из openbsd. Но любопытсва ради я попробую покататься и на нем ;)
Вы бы написали алокатор чего, аллокатор как и аллокатор почему
Хм, неужели в нгинксе «не хороший» менеджер памяти?
Он на freebsd/openbsd очень хороший. А вот в мире linux появляются проблемы.

Я, собственно, и сделал так, что бы он в linux стал таким же хорошим.
Вопрос для чего. На linux в libc используется ptmalloc — там суть в том, что поверх lea используется per thread heap/arena — что сильно снижает contention в условиях SMP. На сегодня это один из самых быстрых аллокаторов, которые доступны стандартно.

nginx же сам по себе под SMP практически не заточен — там дофига локинга и оптимизация под cache line также не везде есть. В nginx все события принимаются и предобрабатываются ОДНИМ (!) потоком, потом они складываются в одну очередь, которую обрабатывают обработчики — что приводит к борьбе между ними при высокой нагрузке.

Есть и другой подход, когда каждый обработчик обрабатывает только свои соединения. Таким образом решается проблема с локингом и конкуренцией — события тупо обрабатываются без локинга, т.к. они никогда не попадут в очередь соседних обработчиков.
Я хотел простой mmap-based (а не brk/sbrk) аллокатор который будет заточен под стратегию использования в памяти nginx. Причем nginx для linux, что мне интересно.

Я не совсем понимаю что вы хотели сказать этим комментарием.
developers.sun.com/solaris/articles/multiproc/multiproc.html

Суть не в методе выделения памяти, а в том, как выледенная память режется на блоки и распределяется. Сегодня практически любой нормальный сервер SMP и использовать аллокаторы и пулы не заточенные под SMP — это жесть.
У меня программа (nginx) не умеет мультипроцессорность. Вообще. Зачем мне аллокатор который умеет хорошо SMP?
Под незаточен я имел ввиду — не сильно оптимизирован, но вообще-то умеет. По крайней мере выравнивание размера структур до cache line size кое-где присутствует.

В nginx более правильно задать другой вопрос — зачем там вообще что-то делать с malloc, если там для основных рантайм вещей используется свой код (а не системный generic use allocator)?

Если вы это все на linux делали, то результат потребления памяти вполне может быть понятен. По крайней мере нужно знать — что лежит за тем, что использовалось. В linux libc — ptmalloc на базе lea — он весьма неплох и для generic use, и для SMP, и для быстродействия.

Да за счет per cpu/thread/process куч он менее экономно относится к памяти, но за быстродействие нужно платить :)

Что касается различных slab и подобных аллокаторов, которые используют память компактно — они (по крайней мере в моих тестах) все медленнее.
Это я к тому, что в nginx:

1) пред-обработанные события складываются в очередь, которая разгребается многими воркерами
2) воркеры выполняются на разных cpu (если их много)
3) обработка последовательных событий для одного и того же соединения может таким образом выполняться не только в контекстах разных CPU но и разных процессов

В реальной жизни обычный malloc, который выделяет память только в рамках текущего процесса — к обработке соединений в nginx не имеет особого отношения.

Если есть реальное желание что-то ускорить — займитесь тем, что реально используется.

А так, если думаете, что я тут сказки рассказывают — посмотрите в коде nginx, где реально используется обычный malloc :) Судя по тому, что вы написали в статье — результаты вас удивят.
Забыл про пункт 3) написать, что работа идет таким образом с shared памятью. В связи с чем любая оптимизация системного маллока для nginx теряет смысл, в принципе.
Изначально я думал, что речь идет как раз о шаред памяти, но почитав и вникнув понял, что речь идет совсем о другом.

Как я уже написал — «аллокатор который будет заточен под стратегию использования в памяти nginx» — эта фраза с моей точки зрения бессмыссленна в отношении malloc, который в nginx используется в основном на фазе инициализации сервера для не-shared памяти.

Советую все же почитать материалы по аллокаторам и изучить современные подходы к задачам. А то глядя на выбор аллокатора на глаз на основе «на глаз лучше рвет всех obsd-like» заставляет сомневаться, что вы понимаете разницу между свойствами различных типов аллокаторов и задачами для которых они предназначены.

С чего вы взяли, например, что ptmalloc из linux хуже BSD-шного, где используется принцип локинга, который не дружит с SMP в плане маштабируемости?

А ведь масштабируемость для подобных серверов главное — не так ли?
Если говорить о BSD/Mac/Win, то хотя в BSD/Mac стандартные аллокаторы тоже не заточены под SMP, хотя и быстрее, чем на винде. На Win вообще ужос нах.
А кто и где говорит о SMP?

А на основе чего вы выбрали аллокатор для замены? Исследовали какие-либо материалы на тему? :) Почему именно это аллокатор, а не другой? Где сравнения с более современными аллокаторами?

P.S. Когда быстродействие отличается незначительно, то можно сделать выбор в сторону более компактного аллокатора, а не более быстрого — зачастую это понятия несовместимые :)

P.P.S. Еще более интересно каким образом измерялось «потребление памяти около 40 мегабайт на каждый worker процесс» в условиях copy-on-write и разделяемой памяти между процессами? :)))))
Улыбают минусы :) Чтобы не опростоволоситься матчасть изучать нужно — тогда на форумах вам никто не будет указывать на то, что вы лажу написали :)
Кстати, а какие аллокаторы, кроме памяти, вы знаете еще?
Любых обьектов или даже фабрик :)
У нас например на фирме аллокатором называется называется железячка которая процесоры выделяет разным кодекам(VoIP)
Если вы мне покажите в nginx (мы о нем говорим) аллокаторы отличные от памяти, я с вами соглашусь.
У пациента есть еще мистическая подсистема кеша и работа с объектами в папке /tmp

В приципе я изначально подумал что доработана как раз система аллокатора логических ресурсов( кэш и временые обьекты, и чего тама еще бывает), а не физических(память)
Ссылку на код, пожалуйста. Я должен это почитать!
может быть имеется ввиду ncache?
если да, так он еще очень сырой — 2.3 сегфолтится через раз.
>У пациента есть еще мистическая подсистема кеша
Аллокатором (от английского to allocate – «размещать», «выделять») называется совокупность механизмов, ответственная за распределение памяти и реализующая операции выделения, освобождения и (опционально) изменения размеров ранее выделенных блоков.
Вот это совсем ни к чему

+#include <pthread.h>
+static pthread_mutex_t gen_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define _MALLOC_LOCK_INIT() {;}
+#define _MALLOC_LOCK() {pthread_mutex_lock(&gen_mutex);}
+#define _MALLOC_UNLOCK() {pthread_mutex_unlock(&gen_mutex);}

nginx однопоточен в настоящее время.
Забыл вычистить, огромное спасибо!
Зато не забыли добавить копирайты ;-)
Угу, но если посмотришь на код оригинальный этого там не было. Я это писал, ибо расчитывал использовать в другом виде. Потом только в голову пришло вкорячить в потроха nginx (да-да, изначально это грузилось через ld_preload).
Непонятно, зачем вы сделали из нового аллокатора патч для nginx.

Проще его вынести в отдельную библиотеку (см freshmeat.net/projects/libhoard/ например), ну или хотя бы LD_PRELOAD модуль.

Он смог бы ускорять точно так же php, perl много еще чего ;-)
Это ниразу не новый алокатор, это алокатор из openbsd который я заставил работать в nginx.

А не сделал я его в таком формате, по простой прчини, мне так удобнее запускать nginx ;)

Да, и задачи ускорять php, perl и прочее не было. Еще учитывать надо что это будет хорошо на той стратегии по использованию памяти, какую выбирает nginx.
Вы вводите в заблуждение людей.
В nginx есть свой pool-based аллокатор. А тот что вы добавили — так это замена системному (libc), а никак «другой аллокатор nginx».
угу, только из-за этого pool-based gnu'шный аллокатор показывает свои плохие стороны. Что я и попытался изменить.

Так же прошу обратить внимание на update.
И соответственно, в nginx ему не место, как ни крути.
Вы предлагаете хачить системный аллокатор? Или делать его через preload? Первое опасно, второе не удобно для отладки (я не уверен что он всегда будет запускаться с этм кодом, а так, этот код, в него жестово вставлен).

Далее, я покатаюсь, с недельку, на этих аллокаторах, пойму какой из них мне понравился больше, и начну их сильно хачить. И в итоге получу *очень* сильно специфичный аллокатор для nginx, который использую.
Имхо это очень логично — если не устраивает системный аллокатор, то бороться с ним, а не дописывать nginx ;-)

> второе не удобно для отладки (я не уверен что он всегда будет запускаться с этм кодом, а так, этот код, в него жестово вставлен)

Код сам не запускается, это вы его запускаете или не запускаете.

PS. Не надо изобретать велосипеды, используйте LD_PRELOAD. Тема исчерпана.
> Имхо это очень логично — если не устраивает системный аллокатор, то бороться с ним, а не дописывать nginx ;-)

> Имхо это очень логично — если не устраивает системный аллокатор, то бороться с ним, а не дописывать nginx ;-)

Лично мне удобнее поддерживать свой_системный_аллокатор внутри проекта для которого я его точу. Что бы не мешать всей остальной системе, ку?
И не мешайте системе. LD_PRELOAD это переменная окружения, которая будет там, где вы ее поставите.
Удобнее оказалось иметь свой аллокатор как кусок кода.
Sign up to leave a comment.

Articles