Emit mapper vs valueinjecter или autopper производительность
Я провел некоторое время, сравнивая эти три картографа, и интересно, почему такая большая разница в производительности между emitmapper и любым из valueinjecter или automapper(последние два сопоставимы по производительности). Из бенчмарк-теста в решении emitmapper(1000000 итераций):
Auto Mapper (simple): 38483 milliseconds
Emit Mapper (simple): 118 milliseconds
Handwritten Mapper (simple): 37 milliseconds
Auto Mapper (Nested): 53800 milliseconds
Emit Mapper (Nested): 130 milliseconds
Handwritten Mapper (Nested): 128 milliseconds
Auto Mapper (Custom): 49587 milliseconds
Emit Mapper (Custom): 231 milliseconds
Также некоторые тесты из valueinjecter, запущенные с добавленным emitmapper(для 10000 итераций):
Convention: 00:00:00.5016074
Automapper: 00:00:00.1992945
Smart convention: 00:00:00.2132185
Emit mapper(each time new mapper): 00:00:00.1168676
Emit mapper(one mapper): 00:00:00.0012337
Там в первом тесте emit mapper - он создавался каждый раз, во втором - один маппер для всех преобразований.
Принимая это во внимание, получим результат как valueinjecter(также как autopper) медленнее, чем в 100 раз, чем emit mapper. В чем причина такой огромной разницы в производительности? Что касается меня, то сопоставление объекта с объектом не может занимать столько времени по сравнению с рукописным отображением, сколько является узким местом проекта (например, если нам нужно отобразить коллекцию объектов).
В данный момент я думаю об использовании emit mapper, но единственная причина, по которой я не готов принять решение: emit mapper вообще не поддерживается первыми разработчиками, но я не уверен, что это очень важно (очень низкая вероятность требованию некоторого дополнительного функционала).
1 ответ
Причина объясняется в документации EmitMapper:
Он эффективно использует библиотеку Emit для генерации преобразователей во время выполнения напрямую в IL, как будто эти преобразователи написаны вручную. Большинство других картографов используют библиотеку Reflection для отображения (или генерации исходного кода). Также EmitMapper минимизирует операции распаковки и дополнительных вызовов во время сопоставления. Например, он выполняет преобразование типов для типов-значений без распаковки и преобразования вложенных элементов без рекурсии (однопроходный алгоритм), когда это возможно.
Отражение очень медленное по сравнению с рукописным кодом. Вместо этого EmitMapper, по сравнению с рукописным отображением, имеет только накладные расходы при запуске, когда он излучает.