О бенчмарках

2017-09-17 • edited 2021-02-06

О бенчмарках

В данной заметке мы обсудим наболевшую тему бенчмарков для различных языков программирования.

Содержание

Введение

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

1. О бенчмарках

На мой взгляд бенчмарки можно разделить на 2 большие группы: внутриязычные и межязычные. Первые позволяют продемонстрировать особенности языка и подсказать наиболее оптимальный вариант решения задачи, положенной в основу бенчмарка. Второй тип тестов помогает подчеркнуть различия между языками и дает представление о том, что похожие на вид конструкции могут вести себя по-разному в зависимости от того на каком языке они написаны.

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

Постановка задачи

В этой статье мы подробно рассмотрим 2 бенчмарка, корректность которых вызывает большие вопросы. Приведенные далее результаты представляют собой среднее потребление ресурсов в течении 100 прогонов. Для замеров в Python использовались функции memory_usage из модуля memory_profiler и perf_counter из модуля time.

1. Поиск простых чисел от Ivan Zahariev

Данный бенчмарк, посвящённый сравнению времени работы алгоритма поиска простых чисел, обладает некоторыми особенностями:

  • Несмотря на то, что рассматривается один и тот же алгоритм, реализации его в различных языках заметно различаются.
  • Алгоритмы оперируют самыми базовыми конструкциями языков и не используются стандартные библиотеки, а сами реализации не учитывают специфику работы конкретных языков.
  • Метод замера времени работы весьма ненадёжен и также не учитывает особенности среды исполнения тестируемых языков.

Результат данного теста:

ЯзыкВремя работы
PHP76.624
Python18.077

Итого по результатам исследования Ivan Zahariev выходит, что PHP7 обгоняет Python в 2.73 раза! Однако реализация Python алгоритма не соответствует общепризнанным практикам, попробуем повторить тот же эксперимент, но с использованием лучшей реализации алгоритма поиска простых чисел.

fef

ТестВремя работы (с)Потребляемая память (МБ)
PHP7 (Ivan Zahariev)0.386102-
Python (Ivan Zahariev)1.37092230.768
Python (RWH)0.343201139.353
Python (RWH numpy)0.013078347.793

Таким образом всего лишь использовав другую реализацию на чистом Python мы получили, что предложенная Ivan Zahariev начинает отставать, а если воспользоваться алгоритмом, использующим numpy(общепризнанная библиотека Python для численных расчетов) то и вовсе Python начинает обгонять PHP7 в 29.5 раз! Однако не стоит ориентироваться на данный результат при выборе инструмента для работы - это просто цифры. Конечно, в численных расчётах хорошая реализация на Python существенно быстрее реализации на PHP7, но и для него существуют свои ниши.

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

2. Подсчёт спектральной нормы от benchmarkgame

Данный бенчмарк страдает теми же проблемами, что и прошлый, но и привносит несколько своих:

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

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

Результат данного теста:

ЯзыкВремя работы
PHP737.94
Python188.83

Пока что PHP7 обгоняет Python в 5 раз! Но вот как изменится картина, если использовать язык согласно принятым в нём практиках

spectral

ТестВремя работы (с)Потребляемая память (МБ)
PHP7 (benchmarkgame)8.964616-
Python (benchmarkgame)51.515929.1393
Python (NumpySpectralNorm)0.40539278.843

После замены реализации алгоритма на реализацию, использующую numpy, мы получили ускорение в 127(!) раз относительно бенчмарка, используемого на главной странице benchmarkgame. Если же сравнивать с реализацией на PHP7 то здесь Python быстрее в 22 раза. Снова повторюсь, что на синтетические тесты нельзя опираться при выборе инструмента.

Примечания

  • Использованный в проекте код доступен в github репозитории

  • В тестах использовался Python 3.6.2 и PHP 7.1.9.

  • В тестах PHP7 не проводились никакие изменения - код алгоритмов взят из обсуждаемых в статье бенчмарках. Если есть предложения по оптимизации этих алгоритмов, то их можно оформить в виде pull реквеста в github репозиторий . В этом случае статья будет обновлена, а контрибуторы упомянуты.

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

  • Мне не удалось замерить реальное потребление памяти в PHP7, доработки приветствуются.

Ссылки

[1]: Поиск простых чисел от Ivan Zahariev

[2]: Подсчёт спектральной нормы от benchmarkgame

бенчмаркphp7Python
License: MIT

Трассировка лучей на Rust. Часть 0. Начало.

Расширение LVM разделов

comments powered by Disqus