Что делает FSharpFunc <> быстрее, чем Func <>?

Мне любопытно на предмет улучшений производительности, которые были сделаны для FSharpFunc <>. Действительно ли это - то, что это не содержит, несколько делегируют, таким образом, нет никакой потребности циклично выполниться по всем ссылкам при увольнении вызова функции? Что-либо еще?

22
задан boran 3 May 2013 в 15:41
поделиться

2 ответа

Я думаю, что первичная мотивация к использованию FSHARPFUNC <> , а не FUNC <> или любого другого делегата заключается в том, что вы не можете создать класс, который будет наследуться от типа делегата ( Сначала это звучит разумно, но в .NET, делегат на самом деле просто какой-то специальный класс, поэтому может быть в принципе возможно, чтобы позволить этому). Почему это нужно?

Если вы пишете функцию в f #, то она (в относительно немногих, но вполне важных случаях) обрабатывается в форме Curry. Например int -> int -> int на самом деле находится тип функции int -> (int -> int) (Carrying означает, что вы пишете функцию с использованием только функций одного параметра - Если вы назовите это с первым аргументом, вы получите функцию в результате, и вы можете вызвать возвращенную функцию со вторым аргументом).

Если F # использовал делегаты, тип будет что-то вроде Функна > . Как упомянул Брайан, вызов F X Y будет переведен на два вызова: F (x) (y) . Этот вид вызова, однако, является наиболее распространенным (указание всего одного аргумента приложение частичной функции ). Итак, когда F # компилирует такую ​​функцию, она создает унаследованный класс с оптимизированным методом invoke, чтобы его можно было вызвать как f.invoke (x, y) :

class @some_F#_name@ : Func<int, Func<int, int>> {
   public int Invoke(int arg1, int arg2) { /* optimized call */ }
}

К сожалению, это не Вы можете создать такой класс, наследующуюся из стандарта Func (потому что это делегат), поэтому F # должен объявить свой собственный тип, который можно использовать в качестве базового класса ...

25
ответ дан 29 November 2019 в 04:57
поделиться

Если я звоню «Метод ()», что происходит с объектом MyClass, который был создан в процессе?

Это создается на кучи GC. Тогда ссылка на его местоположение в куче помещается на стек. Тогда происходит звонок к другому Method. Затем называется метод ToString объекта, и результат напечатан. Тогда krymethod возвращается.

Это все еще существует в стеке после вызова, хотя это ничего не использует?

Ваш вопрос неоднозначен. По «вызову» вы имеете в виду вызов методу или другому Method? Это имеет значение, потому что на данный момент, является ли память кучи кандидатом для сборки мусора, зависит от того, скомпилированы ли вы с включенными или выключенными оптимизациями. Я собираюсь немного изменить свою программу, чтобы проиллюстрировать разницу. Предположим, что у вас есть:

void Method() 
{ 
   AnotherMethod(new MyClass()); 
   Console.WriteLine("Hello world");
} 

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

void Method() 
{ 
   var temp = new MyClass();
   AnotherMethod(temp); 
   Console.WriteLine("Hello world");
} 

в неоптимизированной версии, время выполнения будет фактически выбрать для лечения объекта, как не подходит, пока метод не возвращается, после возврата метода Отказ В оптимизированной версии время выполнения может выбрать для обработки объекта как коллекционируемых, как только oneMethod возвращается, перед WriteLine.

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

Или это удалено немедленно?

Ничто не собирается сразу; Коллектор мусора бежит, когда ощущается, как он должен бежать. Если вам нужен какой-либо ресурс, такой как файловый дескриптор, который следует сразу убирать, когда вы закончите, затем используйте блок «Использование». Если нет, то пусть сборщик мусора решается, когда собирать память.

Должен ли я установить его на NULL, чтобы получить GC, чтобы заметить его быстрее?

Вам нужно установить Что к нулю? Какую переменную вы имели в виду?

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

Я думаю, что вы перевыпите эту проблему. Пусть сборщик мусора делает свое дело и не подчеркивает об этом. Если у вас есть реальная проблема с памятью, не собираться своевременно, то покажи нам какой-то код, который иллюстрирует эту проблему; В противном случае просто расслабьтесь и научитесь любить автоматическое утилизацию хранения.

-121--3545712-

(Я думаю, что теперь они называются FSHARPFUNC , а не FastFunc .)

Он представлен как тип с одним абстрактным методом ( Вызвать), что я думаю, избегает некоторых накладных расходов, которые вы получаете с настоящими делегатами. И для нескольких параметров Curry Curry позволяет вам позвонить со всеми параметрами «сразу», а не один-по-либо (например, так, чтобы FXY можно вызывать на CLR CLR как F (x , y) , а не f (x) (y) .

. FS в FSHARP.CORE в исходном распределении, который поставляется с выпуском CTP.

12
ответ дан 29 November 2019 в 04:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: