C # / F # Сравнение производительности

Есть ли в Интернете какое-либо сравнение производительности C # / F #, чтобы показать правильное использование нового языка F #?


person Vijesh VP    schedule 27.09.2008    source источник


Ответы (3)


Естественный код F # (например, функциональный / неизменяемый) работает медленнее, чем естественный (императивный / изменяемый объектно-ориентированный) код C #. Однако этот вид F # намного короче обычного кода C #. Очевидно, здесь есть компромисс.

С другой стороны, в большинстве случаев можно достичь производительности кода F #, равной производительности кода C #. Обычно это требует кодирования в императивном или изменяемом объектно-ориентированном стиле, профилирования и устранения узких мест. Вы используете те же инструменты, что и в C #: например, .Net отражатель и профайлер.

При этом стоит знать о некоторых высокопроизводительных конструкциях F #, снижающих производительность. По своему опыту я видел следующие случаи:

  • ссылки (по сравнению с переменными экземпляра класса), только в коде, выполняемом миллиарды раз

  • Сравнение F # (‹=) с System.Collections.Generic.Comparer, например, в двоичном поиске или сортировке

  • хвостовые вызовы - только в определенных случаях, которые не могут быть оптимизированы компилятором или средой выполнения .Net. Как отмечено в комментариях, зависит от среды выполнения .Net.

  • Последовательности F # в два раза медленнее, чем LINQ. Это связано со ссылками и использованием функций в библиотеке F # для реализации перевода seq ‹_>. Это легко исправить, поскольку вы можете заменить модуль Seq на модуль с такими же сигнатурами, который использует Linq, PLinq или DryadLinq.

  • Кортежи, кортеж F # - это класс, отсортированный в куче. В некоторых случаях, например кортеж int * int, который может быть платным за использование структуры.

  • Распределения, стоит помнить, что замыкание - это класс, созданный с помощью оператора new, который запоминает доступные переменные. Возможно, стоит «снять» замыкание или заменить его функцией, которая явно принимает переменные, к которым осуществляется доступ, в качестве аргументов.

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

Мой опыт заключается в том, чтобы сначала написать код на F # и оптимизировать только те части, которые имеют значение. В некоторых случаях может быть проще написать медленные функции на C #, чем пытаться настроить F #. Однако с точки зрения эффективности программиста имеет смысл запускать / прототипировать на F #, затем профилировать, разбирать и оптимизировать.

Суть в том, что ваш код F # может работать медленнее, чем C #, из-за решений по разработке программы, но в конечном итоге эффективность может быть достигнута.

person Stefan Savev    schedule 02.01.2010
comment
Интересные моменты, но вам нужно будет проверить больше, чем одну среду выполнения; с CLI 2, x86 и x64 имели совсем другой хвостовой вызов; он явно был усилен частично из-за поддержки F #, но это может исказить профили C #. - person Marc Gravell; 03.01.2010
comment
Обычно это требует кодирования в императивном или изменяемом объектно-ориентированном стиле. Нет, вам нужны изменения для повышения производительности, но вы должны избегать объектно-ориентированного стиля в пользу стиля Fortran. ООП тоже медленный ... - person J D; 29.03.2011
comment
Если им действительно нужна скорость, я думаю, им следует больше думать о языке ассемблера. - person Little Jack; 05.09.2011
comment
что такое ссылки (по сравнению с переменными экземпляра класса)? - person colinfang; 01.05.2013
comment
F # не медленнее, чем C #, и не наоборот. Языки не имеют производительности исполнения. Мы говорим об эффективности компиляторов. Чем более совершенной становится технология компилятора, тем выше вероятность того, что языки более высокого уровня могут быть оптимизированы в большей степени, чем языки более низкого уровня, поскольку обычно вы можете больше рассуждать о функциональном источнике. Сейчас мы находимся на этапе, когда программирование на функциональных языках входит в основной бизнес, и одна из причин заключается в том, что скорость их выполнения приближается к императивным языкам. Мы можем надеяться, что они обгонят их через десять лет. - person Bent Tranberg; 16.09.2015
comment
@BentTranberg Неправильно. Языки определяют концепции, которые затем необходимо сопоставить с программами, работающими на реальном оборудовании. Некоторые из этих концепций труднее реализовать, чем другие. Например, если бы я разработал язык с одной инструкцией для автоматического понимания и решения любой проблемы, это было бы не только почти невозможно реализовать, но и было бы очень, очень, ОЧЕНЬ медленно ; и это не проблема компилятора, это проблема языка. - person Arshia001; 06.02.2019
comment
БентТранберг прав. Arshia001 тоже. Конечно, языку не присущи характеристики; это зависит от оптимизаций, которые может сделать компилятор. В то же время, очевидно, императивный язык легче оптимизировать, потому что он больше похож на то, как работает аппаратное обеспечение. Вот почему функциональный язык не использовался в реальной индустрии в течение многих лет. Haskell - хороший пример этого изменения, поскольку его компилятор может выполнять чудовищные оптимизации, компилируя код почти до скорости C. - person Mateus Felipe; 13.09.2019


Вот несколько ссылок по этой теме (или связанных с ней):

То, что я, кажется, помню из другого сообщения в блоге Роберта Пикеринга (или это был Скотт Хансельман?), Что, в конце концов, поскольку оба находятся на одной платформе, вы можете получить одинаковую производительность от обоих, но иногда для этого нужно «исказить» естественное выражение языка. В примере, который я помню, ему пришлось крутить F #, чтобы получить сопоставимую производительность с C # ...

person Benjol    schedule 29.09.2008
comment
Обратное также верно, если вы пользуетесь уникальными функциями F #, такими как inline. - person J D; 21.04.2010