Как стать автором
Обновить

Комментарии 47

Ммм, мне кажется или ввиду наличия Print/Write в циклах это тест скорости стандартного io?

НЛО прилетело и опубликовало эту надпись здесь

Да, помимо прямого выполнения, в JVM имеет место быть профайлер ). Конечно, он не успевает отработать на 'коротком' тесте.

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

Не, этот тест эффективности отладочных и неоптимизированных версий. Автору стоит попробовать хотя бы включить оптимизацию rustc -C opt_level=3 ./main_primes.rs и он будет приятно удивлён.

Конечно. Но кто сказал, что стандартный ввод/вывод должен в десятки раз отличаться в разных языках?

Если что, это камень и в сторону C++ iostream

Вы правы, что наличие Print/Write имеет влияние и его надо убрать, но на сравнительные результаты не влияет. Дополнил статью.

Каждый раз когда вижу такие статьи на хабре понимаю, что надо всё таки дописать мою статью "Почему ваш кросс-языковой бенчмарк вам врёт". У меня там отличный пример есть, где можно на двух "совершенно одинаковых алгоритмах" получить Java сколь угодно быстрее чем Rust :)

Фантастично то, что люди получив измерения вообще не пытаются даже понять почему они такие числа получили. Вот у человека получается что Rust в 10 раз медленнее, чем Java. И ничего в голове не щелкает, человек публикует статью. Насколько странным должен получиться результат, что бы человек начал искать проблему в своем тесте? В 100 раз должен Rust проиграть Java, в 1000? :) А если бы Java на числодробилки бы оказалась медленнее, там наверное пока в миллион раз её не обгонят никто даже и не почешется, что делает что-то не так :)

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

Спасибо, почему то я не удивлён)

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь

Вы абсолютно правы, сборка с оптимизацией в корне меняет дело. Дополнил статью.

Попробовал лазарь. С выводом: 7 секунд, без: 1.5. Так что да. В таком варианте смысла в тестах мне кажется мало. Лучше вывод 'по ходу' отключить.

Вы бы ключи -C debuginfo=0 -C opt-level=3 при вызове rustc добавили...

По умолчанию Rust компилирует без оптимизаций, надо как минимум делать так:

rustc -C opt-level=3 rust/src/main_horse.rs

Вот документация на эту тему https://docs.rust-embedded.org/book/unsorted/speed-vs-size.html

соотвественно результат у меня на ноутбуке (macbook pro):
rust без оптимизаций:
Attempts: 3, duration: Some(36.852092s)

Executed in   36.86 secs    fish           external

   usr time   36.43 secs    0.16 millis   36.43 secs

   sys time    0.20 secs    1.94 millis    0.20 secs

rust с оптимизациями (-C opt-level=3):

Attempts: 3, duration: Some(1.103816s)

Executed in    1.30 secs      fish           external

   usr time  990.80 millis    0.11 millis  990.69 millis

   sys time  113.74 millis    2.05 millis  111.69 millis

java:

Attempts: 3, duration: 2.868 sec

Executed in    3.06 secs    fish           external

   usr time    5.00 secs    0.13 millis    5.00 secs

   sys time    0.41 secs    1.99 millis    0.41 secs

Да, тест с оптимизацией работает на порядок быстрее. Дополнил статью.

Это настолько неграмотная статья, что похожа на троллинг.

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

И уберите тест на IO, если хотите увидеть результаты на CPU, а не оптимизаций вывода в stdout

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

Вот так просто на коленке взяли и слабали компилятор C? Что ж, верю-верю.

Компилятор C и транслятор Pascal -> C (для дальнейшей компиляции) это совсем разные вещи по сложности), тем более, если нужно не универсальное решение, а для своего кода, в котором вполне могут не использоваться все возможности языка.
У нас в компании вполне себе живет транслятор PHP -> JS для реализации гибкой валидации полей на стороне пользователя, ничего сложного в нем нет.

У нас на 4ом курсе университета была курсовая по написанию транслятора с одного языка в другой. Если оба языка относятся к одной парадигме, имеют схожие языковые конструкции и нужно поддержать только ограниченный набор возможностей, то после изучения необходимого теор. минимума и стандартных иструментов типа bison и flex эта задача становится не сложной.

Не компилятор, а транслятор же.
Если не ставить себе цель «транслировать любой код на FP в адекватный код на Си», то задача решается сравнительно не сложно, в чём вы можете убедиться самостоятельно, если попробуете.

Фактически неудачный пример статьи для спецолимпиады :)

Автору надо было в НАЧАЛЕ статьи признаться в своей слабой компетенции в части ЯП (кроме "любимого") и предложить аудитории "развенчать" его потуги, т.е. предложить свои варианты решения.

Очевидно же, что данный код больше всего времени тратит на вывод. Уж логичнее было всё запихать в массив или строку, а потом уже вывести за раз. Автор бы ещё инкрементально вывод в файл запихал. А уж про оптимизацию забыть при проверке на скорость - это фейл.

Да никто новичка не пинает, в комментариях довольно продробно и доброжелательно объяснили, что тут не так (и даже определённое количество плюсов поставили и своя польза от статьи тоже есть). Вообще написание статей новичками вполне имеет смысл, потому что у профи взгляд зачастую "замыливается" и многие вещи, очевидные для них, и остающиеся за кадром, совершенно нетривиальны для новичков, но если новичок делает какие-либо выводы, то они должны быть железобетонно непробиваемы, хотя бы в той области, в которой уже разобрался. В данном случае имело смысл расчехлить Си, сделать буквально пару тестов сравнения Раста и Си, затем пойти в "вопросы и ответы" и спросить "почему все твердят, что Раст сравним по производительности с Си, а вот мои тесты этого не показывают?" и всё встало бы на свои места. Затем погонять Раст с разными опциями оптимизации, заглянуть в листинги ассемблера и получилась бы хорошая статья. Кстати, основное преимущество Раста, на мой взгляд даже не столько в эффективности кода, сколько в том, что там можно достаточно легко и безопасно параллелить вычисления. А для новичков Раст, по моему мнению и правда, не очень подходит, именно потому, что "планка вхождения" в подавляющем большинстве туториалов чуть выше, чем в "учебных" языках.

Отличная доброжелательность. -17 кармы и -49 за статью =)

Остальное, сорри, мусор. Идеология заимствования и единоличного владения противоречит параллелизации. Это один из главных гвоздей в гробик раста, ИМХО конечно. Сэд бат тру.

Идеология заимствования и единоличного владения противоречит параллелизации
Почему так? В идеологии раста как раз заявляется, что если объектом или группой владеет какой-то определённый поток, то синхронизация не требуется, а значит, на неё не надо тратиться при распараллеливании.

Капитан Очевидность?

Даже внутри потока так, как раз проблема в разделении

И в чём проблема? Разные потоки будут владеть разными объектами. И следить за этим будет компилятор, а не ошибающийся кожаный мешок.

А другие языки как с этим справляются, у которых нет гвоздей в гробу?
НЛО прилетело и опубликовало эту надпись здесь

У Python есть специальная версия, которая использует JIT называется PyPy. Если вы хотите открыть роман "Война и Мир" и подсчитать сколько слов используется в романе и сколько раз они повторяются, то лучше всего для этого подойдёт PyPy. Он довольно быстро справляется с подобной задачей. А если если использовать оригинальный Python, то на полчаса придётся отойти от компьютера.

Основное преимущество языков вроде Java и C# в том, что код скомпилированный в debug режиме по скорости мало отличается от кода скомпилированного в release. Причина в том что для JIT библиотеки классов и рантайм библиотеки всегда используются Release. В тех же плюсах рантайм библиотеки для release и debug - разные

Такое себе преимущество. Это значит, рантайм библиотеки всегда выполняют дебажные проверки и выключить их нельзя. Хотя, для Enterprise языков, пожалуй, это хорошо. Программы на прод выкладывают в конфиге Release и там будет совершенно не лишним, если в рантайме останутся проверки.

Основное преимущество языков вроде Java и C# в том, что код скомпилированный в debug режиме по скорости мало отличается от кода скомпилированного в release.

Неправда, как минимум для C#. В debug он даже не инлайнит (или инлайнит крайне редко), параметры передаёт через стек и вообще кучу всего не пытается оптимизировать, а в release - инлайнит и оптимизирует. В https://sharplab.io/ легко примеры набрать, посмотрите. Если у вас не видно разницы, то у вас не CPU-bound задача. И бывают баги рантайма, специфичные для release или debug. И всё равно C# кучу возможных оптимизаций не делает (по сравнению с C/C++/llvm), особенно это качается оптимизаций, которые могут нарушить call stack (оптимизация хвостовой рекурсии, например, не делается) - иначе при исключениях потом движок не может сказать, где и что случилось.

Для Java ситуация ещё сложнее.

Всё о чем вы говорите мало влияет на скорость пользовательского кода. Просто потому что никто никогда в здравом уме не делает ни на C# ни на Java задачи требующие серьёзных вычислений. Большая часть вычислений веб-приложений происходит внутри библиотек ASP.NET и Kestrel. Для графического интерфейса в DirectX и их обертках (WPF и WinUI). CPU-bound задачи на C# никто не делает (нужно сделать библиотеку на С++ из которой вытащить функции с нормальными именами и использовать её в C# проекте).

Оптимизации для большинства задач оказывают не такое влияние как многопоточность или SIMD-инструкции. Например я однажды делал графический интерфейс для АЦП. Часть кода преобразующая данные благодаря SSE работала в 6-7 раз быстрее чем написанная на C#. При этом всё на C# могло работать в любой конфигурации что Release что Debug. Если у вас программа на C# сильно замедляется в Debug - это значит что вам нужно оптимизировать hot path чтобы такого не случалось.

Просто потому что никто никогда в здравом уме не делает ни на C# ни на Java задачи требующие серьёзных вычислений.

Это настолько противоречит моему опыту, что я не знаю, как спорить. В банках и в других фин. организациях основная часть хайлоада на jvm. Некоторое количество есть на .net, еще меньшее, но всё еще обнаружимое количество есть на всякой node/js. Следовые количества остального: go, cpp, python и дальше по списку. Немало ресурсов, конечно, съедают "готовые" системы (СУБД, MQ, kafka, мемкеши всякие), но значительная часть вычислений (сожранных процессоров) именно на jvm и .net.

Мы пробовали один из микросервисов в варианте Debug на где-то около тысячи RPS запускать когда искали утечку памяти на .NET Core 2.1 и 2.2 (её так и не нашли, а переход на 3.1 её волшебным образом убрал). Для этого мы просто в кубере удвоили количество инстансов на всякий случай. И не было никакой ощутимой просадки по выполнению запросов. Разница наверно была, но меньше времени выполнения сетевых запросов, например, обращения к SQL Server. Т.е. на .NET Core 2.1 версия собранная в Debug режиме не особо-то и медленнее чем в Release.

Сравнивать карьерный самосвал, УАЗ и Феррари - это сильный ход!

Намек на Upd3. У меня на некоторых тестах, код сгенеренный Дельфи и Lazarus для x64 был вдвое быстрее, нежели собранный ими же под x32.

Старые компиляторы просто перестали развивать.

Я проверял на актуальных версиях Delphi 10.3 и FPC 3.x

НЛО прилетело и опубликовало эту надпись здесь

Как все просто то оказывается =)

С - компиляторы, например, подобной зависимостью не страдают.

Это конкретно дельфийский компилятор так развивается - по стандартам x64 положено считать плавающую точку на SSE, поэтому её, так и быть, сделали на SSE. А x86? Да ну, чот страшно трогать, поломаем ещё... оставляем FPU. Отсюда и 2 раза.
У FPC, насколько помню, таких заморочек нет, там x86 компилятор может использовать SSE. Хотя наверное, его нужно принудительно включить.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации