nginx-1.2.5
Maxim Dounin
mdounin at mdounin.ru
Thu Nov 15 14:19:05 UTC 2012
Hello!
On Thu, Nov 15, 2012 at 01:54:44PM +0400, Anton Yuzhaninov wrote:
> On 11/14/12 21:44, Maxim Dounin wrote:
> >Но, честно говоря, я так подозреваю, что даже цифры выше - это,
> >скорее всего, далеко не просто стоимость инструкций, а результат
> >выбрасывания нужных данных из кеша процессоров из-за обновления
> >счётчика (читай: cache line flush'ился, и route entry при других к
> >ней обращениях приходилось перегружать из памяти). В этом месте
> >nginx поступает как правильно, и счётчики держит отдельно от
> >всего, да ещё и с отступом в cache line между ними.
>
> Сама по себе операция изменения счетчика, разумеется очень дешевая.
> Весь эффект, из за необходимости синхронизации кэшей CPU.
> После того, как счетчик инкрементирован он сначала попадает только в
> локальный кэш CPU. Если потом код работающий на другом CPU захочет
> инкрементировать этот же счетчик, он должен будет подождать, пока
> первый CPU запишет эти данные в main memory, и потом прочитть их
> оттуда. Для того, чтобы узнать сосотяние кэша (нужно ли ждать и
> сколько ждать) используются разные протоколы для обеспечения cache
> coherency, но почти все плохо масштабируются с увеличенимем числа
> кэшей. В итоге при достаточно большом числе процессоров и ядер даже
> простой инкремент общего на много CPU счетчика может стать узким
> местом.
Это понятно. Но я как бы о том, что в конкретном случае route
entry - скорее всего эффект не от самих изменений, а из-за cache
trashing других данных в результате этих изменений. Т.е. из-за
того, что счётчик находится в той же линии кеша, что и другие
полезные данные.
Наблюдать contention на обновлении отдельностоящего счётчика -
куда как сложнее. Сейчас погонял тесты на своём ноутбуке: tight
loop обновления счётчика при увеличении количества потоков от
одного до 4-х (== количество thread'ов в процессоре) становится в
6 раз медленнее, но и это "медленнее" - это 50 миллионов
обновлений счётчика в секунду на поток, без всякой оптимизации.
Если тебе вдруг будет не лень повторить тот эксперимент с
форвардингом, на который ты ссылался, можно попробовать вместо
того, чтобы убирать обновление счётчика - отодвинуть его в
отдельный cache line, сделав вокруг него padding в cache line
size. Если я правильно понимаю - на выходе должны получиться
практически те же самые 2 процента, что и просто от его убирания.
> В случае nginx наверно измеримого эффекта не будет - счетчики
> инкрементируются относительно редко, на один http запрос выполняется
> много разной работы.
С этого я и начал. :)
> Но теоретически будет немного быстрее, если каждый воркер будет
> писать в свою облать памяти, а скалдываться все эти счетчики будут
> только для чтения статистики (т. е. относительно редко).
Теоретически - да, а на практике - чтобы заниматься подобными
оптимизациями, неплохо бы сначала иметь измеримый эффект.
--
Maxim Dounin
http://nginx.com/support.html
Подробная информация о списке рассылки nginx-ru