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

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

Попробуйте BenchmarkDotNet. Я уверен что он даст гораздо более точные результаты, к тому же он удобен и у него большой функционал. Ну и замерять в Debug режиме смысла много нету, так как финальное приложение в любом случае будет работать в Release.
Я видел легаси которое не могло скомпилиться в релизе потому что когда-то что-то сломали и никто не помнит что и где. Так что, кто знает. Авось пригодится.
О-о-о, можно очень жестко похоливарить.
1. Статический метод — это не вполне тоже самое, что метод подгружаемый с Reflection.Emit. Например, Reflection.Emit метод может подгружаться через сохраненную локально сгенерированную dll, а может подгружаться в отдельную динамическую либу.
2. Для замеров лучше использовать BenchmarkDotNet. Не то чтобы в замерах есть ошибки — просто меньше «сервисного» листинга.
3. Скорее всего, большую часть времени замера сжирают BitConverter.GetBytes и stream.Write методы. По факту, вы замеряете (время исполнения методов фреймворка + время исполнения сравниваемого кода).

Иными словами, в данном end-to-end сценарии можно использовать ExpressionTrees или Reflection.Emit — разница в производительности будет минимальна. В другом end-to-end сценарии, где меньше библиотечных вызовов и больше работы непосредственно с базовыми конструкциями C# — разница может быть существенной.

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

Есть еще такой проект интересный: FastExpressionCompiler, призванный как раз сократить разницу между Expression.Compile и Reflection.Emit.


Цитата оттуда:


The question is, why is the compiled delegate way slower than a manually-written delegate? Expression.Compile creates a DynamicMethod and associates it with an anonymous assembly to run it in a sandboxed environment. This makes it safe for a dynamic method to be emitted and executed by partially trusted code but adds some run-time overhead.
Сделал аналогичный тест, только без тяжелых методов фреймворка и аллокаций.
Тестовый метод считает побайтовый XOR от длинны строки и её символов.
Мой вывод: разница на уровне погрешности, что удобнее для задачи, то и следует использовать.
Код: gist.github.com

Подробные результаты
BenchmarkDotNet=v0.10.14, OS=Windows 7 SP1 (6.1.7601.0)
Intel Core i5-2500 CPU 3.30GHz (Sandy Bridge), 1 CPU, 4 logical and 4 physical cores, Frequency=3232187 Hz, Resolution=309.3880 ns, Timer=TSC
  Clr: .NET Framework 4.6.2 (CLR 4.0.30319.42000), 64bit RyuJIT-v4.6.1590.0

Method                                    Mean      Error      StdDev
Native                                  307.6 us   1.688 us   1.579 us
NativeUnsafe                            292.5 us   2.178 us   2.037 us
NativeDelegate                          307.8 us   1.743 us   1.631 us
LinqExpressions                         308.0 us   2.393 us   2.239 us
ReflectionEmitExpressionRunAndSave      307.4 us   1.437 us   1.344 us
ReflectionEmitExpressionRunAndCollect   307.5 us   1.776 us   1.575 us
ReflectionEmitExpressionRun             306.9 us   1.628 us   1.522 us
ReflectionEmitNativeRunAndSave          307.2 us   1.185 us   1.108 us
ReflectionEmitNativeRunAndCollect       308.8 us   2.162 us   2.022 us
ReflectionEmitNativeRun                 307.0 us   1.474 us   1.378 us

У Вас ошибка в листинге кода: TestNative и TestDelegateNative используют метод SaveString, но не через вызов делегата NativeDelegate.
Не знаю какой прирост даст в данном примере, но думаю статик филды делегатов лучше кешировать в локальную переменную, для чистоты теста!
Спасибо, тогда вообще непонятно, почему такие результаты :)
Испоользуйте BenchmarkDotNet.
Он более акуратно проведет тесты, плюс выдаст ошибку измерений!
Нравится простота в использовании.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории