от Влад Краснов

Пока я писал статью сравнивая новый серверный чип 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 г.