В последнее время горячо обсуждается вопрос о том, является ли Rust быстрее, чем C ++, который заменяет предыдущее обсуждение того, является ли C ++ быстрее, чем C, а иногда даже упоминается Java.

Что такое производительность?

Очевидно: насколько быстро выполняется конкретный фрагмент кода. И в случае микробенчмарка это действительно то, на что мы смотрим. Сколько циклов ЦП требуется для выполнения идеально оптимизированной версии нашего крошечного изолированного фрагмента кода?

Но как только мы хоть немного уменьшим масштаб, нам нужно осознать сделанные предположения. Например, можем ли мы предоставить данные нашему микрооптимизированному фрагменту кода, чтобы он работал даже удаленно на полной скорости, или окружающий код замедлит его? Даже если нас интересует исключительно задержка (или мкВт), а не пропускная способность, мы, вероятно, находимся в многопоточной, многопроцессорной или даже многопоточной среде, которая может полностью доминировать в нашей задержке.

Последняя часть, в которой микротест языков дает сбой, - это просто качество компиляторов и виртуальных машин. При сравнении скомпилированных и большинства JIT-языков на микроуровне единственная разница будет заключаться в дополнительных «проверках», принудительно внесенных в код. Например, проверки границ (массивы, целые числа) повлекут за собой штраф во время выполнения, но код без этих проверок не является эквивалентным кодом. В результате существует множество примеров кода JavaScript, который JIT компилирует в оптимальный двоичный файл, такой же, как в C ++.

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

Как быстро вы можете писать быстрый код?

Или, другими словами, если вы напишете отлично читаемый высокоуровневый код, насколько быстрым будет этот код. Более того, сколько кода, критичного к производительности, вам нужно написать самому? Вы также можете представить себе это как разделение ваших общих усилий на «начальное кодирование» и «оптимизацию».

В этом контексте мы начинаем видеть дифференциацию. Языки сценариев внезапно создают барьер. Быстрый код должен содержаться в предварительно скомпилированных модулях и, как правило, написан на C.

Однако скриптовые языки - не единственные, которые создают препятствия. Вот некоторые другие функции, которые влекут за собой штрафы во время выполнения, которые нельзя полностью оптимизировать:

  • неизменяемые данные в функциональных языках
  • функции безопасности, требующие проверки во время выполнения
  • автоматическое управление памятью

Качество доступных инструментов также оказывает огромное влияние на легкость написания быстрого кода. Например, для скомпилированных языков PGO обычно приводит к повышению производительности на 20%.

Но давайте не будем забывать и о другой стороне уравнения. Итак, мы можем рассуждать о том, насколько быстр код, который мы пишем, но насколько быстро мы пишем этот код?

Альтернативные стоимость

В бизнесе все - деньги, и хотя может быть непросто сформулировать альтернативную стоимость ваших инженеров, вам следует подумать об этом. Чем вы более продуктивны, тем выше разница между базовыми затратами (сколько вам стоит удержать этого сотрудника) и альтернативными издержками (сколько ценности приносит этот сотрудник).

Это делает обсуждение того, насколько быстро мы пишем быстрый код, очень сложным, потому что это превращается в динамическую проблему. Решение об оптимизации исходит от двух основных триггеров:

  • экономия от уменьшения объема ресурсов стоит потратить X дней альтернативных издержек
  • продукт не соответствует SLA, что препятствует предоставлению новых функций

Это означает, что вы легко можете оказаться в ситуации, когда написание всего кода на языке сценариев никогда не вызовет ни одну из этих ситуаций. Возможность экономии ресурсов может не проявиться, если продукт быстро развивается. Несоблюдение SLA может быть решено проще и дешевле за счет увеличения объема ресурсов.

Архитектура повышает производительность.

На микроуровне распознавание паттернов плохой производительности стало частью базовых навыков программирования. Например, знание того, когда использовать хэш-карты или бинарный поиск, было передано разработчикам программного обеспечения через такие веб-сайты, как LeetCode, которые стали необходимыми для получения работы.

Распознать одни и те же закономерности в архитектуре гораздо сложнее:

  • более высокий уровень шума затрудняет рассуждение о производительности
  • разделение ответственности естественным образом ведет к неэффективности, но может быть необходимостью
  • понимание подробных характеристик производительности сторонних компонентов является сложной задачей

Но в то же время архитектура превзойдет любое улучшение производительности на микроуровне. Например, предположим, что вы обрабатываете входные данные несколько раз и можете либо улучшить скорость обработки, либо обработать входные данные только один раз. В этом случае вы говорите об ускорении на 5–10% за счет микрооптимизации, но, вероятно, на 80% или даже больше ускорения за счет полного удаления дублированной работы.

Все это становится экспоненциально более сложным, если вы развертываете свое программное обеспечение в Интернете и вам необходимо динамическое масштабирование.

Так имеет ли значение производительность языка?

У вас будут компоненты в вашей кодовой базе, которые вы можете и должны оптимизировать до их пределов. Например, синтаксический анализ и проверка входных данных, базовые числовые функции, такие как шифрование и хеширование, любой математический код для конкретной предметной области (AI, графика…). Но вы пишете это сами или перекладываете эту головную боль на библиотеку?

И что еще более важно, сколько времени вы тратите на кодирование реализации пропорционально всему остальному? В моих проектах на кодирование приходится от 0,5% до 10% от общего времени. Так что на мета-уровне меня меньше всего беспокоит эффективность кодирования.

Более того, на уровне компании, особенно если ваша компания небольшая, возможность легко найти таланты для определенного языка должна преобладать над любыми другими соображениями.

Если вы не занимаетесь торговлей с малой задержкой, в этом случае ничего не имеет значения, поскольку один сэкономленный цикл ЦП может обернуться абсурдной суммой денег.

Спасибо за чтение

Спасибо, что прочитали эту статью. Вам понравилось?

Также публикую видео на YouTube. у вас есть вопросы? Напишите мне в Twitter или LinkedIn.