от Влад Краснов
Пока я писал статью сравнивая новый серверный чип Qualcomm, Centriq, с нашим текущим запасом процессоров Xeon на базе Intel Skylake, я заметил тревожный феномен.
При тестировании OpenSSL 1.1.1dev я обнаружил, что производительность шифра ChaCha20-Poly1305 не очень хорошо масштабируется. В одном потоке он работал со скоростью примерно 2,89 ГБ / с, тогда как на 24 ядрах и 48 потоках он выполнялся со скоростью чуть более 35 ГБ / с.
Сейчас это очень большое число, но хотелось бы видеть что-то ближе к 69 ГБ / с. 35 ГБ / с - это всего 1,46 ГБ / с на ядро, или примерно 50% от одноядерной производительности. AES-GCM масштабируется намного лучше, до 80% от одноядерной производительности, что понятно, потому что ЦП может поддерживать более высокую частоту в турбо-режиме на одном ядре, но не на всех ядрах.
Почему у ChaCha20-Poly1305 такое плохое масштабирование? Встречайте AVX-512. AVX-512 - это новый набор инструкций Intel, который добавляет много новых 512-битных инструкций SIMD и переводит большинство существующих до 512-битных. Проблема с такими широкими инструкциями в том, что они потребляют энергию. Большая мощность. Представьте себе одну инструкцию, которая выполняет работу 64 обычных байтовых инструкций или 8 полноценных 64-битных инструкций.
Чтобы контролировать мощность, Intel представила так называемое динамическое масштабирование частоты. Он снижает базовую частоту процессора всякий раз, когда используются инструкции AVX2 или AVX-512. Это не ново и существует с тех пор, как Haswell представила AVX2 три года назад.
Масштабирование ухудшается, когда большее количество ядер выполняет AVX-512 и когда используется умножение.
Если запускать только код AVX-512, то все хорошо. Частота ниже, но ваша общая продуктивность выше, потому что каждая инструкция выполняет больше работы.
OpenSSL 1.1.1dev реализует несколько вариантов ChaCha20-Poly1305, включая варианты AVX2 и AVX-512. BoringSSL реализует другую версию AVX2 ChaCha20-Poly1305. Тогда понятно, почему BoringSSL обеспечивает только 1,6 ГБ / с на одном ядре по сравнению с OpenSSL 2,89 ГБ / с.
Итак, как это повлияет на вас, если вы смешаете немного AVX-512 с вашей реальной рабочей нагрузкой? Мы используем процессоры Xeon Silver 4116 с базовой частотой 2,1 ГГц в конфигурации с двумя сокетами. Из рисунка, который я нашел на wikichip, кажется, что запуск AVX-512 даже на одном ядре этого процессора снизит базовую частоту до 1,8 ГГц. Запуск AVX-512 на всех ядрах снизит его до 1,4 ГГц.
А теперь представьте, что вы запускаете веб-сервер с Apache или NGINX. Кроме того, у вас есть много других услуг, выполняющих реальную важную работу. Что произойдет, если вы начнете шифровать свой трафик с помощью ChaCha20-Poly1305 с использованием AVX-512? Это вопрос, который я себе задавал.
Я скомпилировал две версии NGINX, одну с OpenSSL1.1.1dev, а другую с BoringSSL, и установил ее на наш сервер с двумя процессорами Xeon Silver 4116, всего 24 ядра.
Я настроил сервер на обслуживание HTML-страницы среднего размера и проделал с ней некоторую значимую работу. Я использовал LuaJIT для удаления разрывов строк и лишних пробелов и brotli для сжатия файла.
Затем я отслеживал количество запросов в секунду, обслуживаемых при полной нагрузке. Вот что у меня получилось:
Используя ChaCha20-Poly1305 поверх AES-128-GCM, сервер, использующий OpenSSL, обслуживает на 10% меньше запросов в секунду. А это огромное количество! Это равносильно отказу от двух ядер ни за что. Можно подумать, что это связано с тем, что ChaCha20-Poly1305 по своей сути медленнее. Но это не тот случай.
Во-первых, BoringSSL одинаково хорошо работает с AES-GCM и ChaCha20-Poly1305.
Во-вторых, даже когда только 20% запросов используют ChaCha20-Poly1305, пропускная способность сервера падает более чем на 7% и на 5,5%, когда 10% запросов составляют ChaCha20-Poly1305. Для справки, 15% запросов TLS, которые обрабатывает Cloudflare, - это ChaCha20-Poly1305.
Наконец, согласно perf
, рабочая нагрузка AVX-512 потребляет только 2,5% времени ЦП, когда все запросы относятся к ChaCha20-Poly1305, и менее 0,3% при выполнении ChaCha20-Poly1305 для 10% запросов. Независимо от того, что процессор снижает скорость, потому что это то, что он делает, когда видит, что AVX-512 работает на всех ядрах.
Трудно сказать, насколько сильно дросселируется каждое ядро в любой момент времени, но, выполнив некоторую выборку с использованием lscpu
, я обнаружил, что при выполнении openssl speed -evp chacha20-poly1305 -multi 48
бенчмарка он показывает CPU MHz: 1199.963
для OpenSSL со всеми соединениями AES-GCM, которые я получил CPU MHz: 2399.926
и для OpenSSL со всеми соединениями ChaCha20-Poly1305 я видел CPU MHz: 2184.338
, что явно на 9% медленнее.
Еще одно интересное отличие состоит в том, что ChaCha20-Poly1305 с AVX2 немного медленнее в OpenSSL, но то же самое в BoringSSL. Почему это могло быть? Причина здесь в том, что код BoringSSL не использует инструкции умножения AVX2 для Poly1305, а использует только простые операции xor, сдвига и добавления для ChaCha20, что позволяет ему работать на базовой частоте.
OpenSSL 1.1.1dev все еще находится в разработке, поэтому я подозреваю, что эта проблема еще никого не затронула. Мы перешли на BoringSSL несколько месяцев назад, и эта проблема не влияет на производительность нашего сервера.
Что нас ждет в будущем - неясно. Intel анонсировала очень крутые новые расширения ISA для будущего поколения процессоров, которые, как ожидается, еще больше улучшат криптографическую производительность. Эти расширения включают AVX512 + VAES, AVX512 + VPCLMULQDQ и AVX512IFMA. Но если к тому времени проблема масштабирования частоты не будет решена, использование этих библиотек для криптографии общего назначения принесет (гораздо) больше вреда, чем пользы.
Проблема не только в библиотеках криптографии. OpenSSL не сделал ничего плохого, пытаясь получить максимально возможную производительность, напротив, я сам написал приличное количество кода AVX-512 для OpenSSL. Наблюдаемое поведение - печальный побочный эффект. Есть много библиотек, которые используют инструкции AVX и AVX2, они, вероятно, будут обновлены до AVX-512 в какой-то момент, и пользователи вряд ли будут знать детали реализации. Если вам не требуется AVX-512 для некоторых конкретных высокопроизводительных задач, я предлагаю вам отключить выполнение AVX-512 на вашем сервере или рабочем столе, чтобы избежать случайного троттлинга AVX-512.
Первоначально опубликовано на blog.cloudflare.com 10 ноября 2017 г.