Недавно в соседнем канале я наткнулся на обсуждение скорости работы ORM. Естественно, разговор крутился вокруг Dapper, Linq2Db и EntityFramework (EF, EF Core). Заявлялось, что библиотека
Linq2db не только удобна как EF, но и быстра, как Dapper. Это меня удивило, так как в моём мировоззрении скорость Dapper достижима только при отказе от удобства уровня EF и при написании чистого SQL (хотя, возможно, кому-то нравится писать запросы руками). Я взял классическую задачу - есть блоги, у блогов есть посты. Я развернул базу данных PostgreSQL в Docker, добавил в неё 100 блогов по 200 постов. Код с использованием EF я написал быстро, с Linq2Db пришлось немного сложнее, но помогла документация, а вот Dapper дался сильно не сразу - именно поэтому по нему два бенчмарка.
Замечу, что я замерял только чтение (SELECT). Измерения скорости добавления и удаления я, возможно, произведу позже.
Тем более, что результаты чтения меня удивили, так как Linq2Db работает очень эффективно. При этом код, который необходимо написать для получения блогов и их постов, подозрительно краток и лаконичен. Ещё более меня удивило то, что скорость близка к Dapper (замер с двумя запросами) и немного выше, чем у рекомендованного для данного случая
QueryAsync<Blog, Post, Blog> с маппингом и splitOn.Мой фаворит, по результатам замеров - Linq2Db, который весьма неплохо справляется с чтением данных из БД, при этом код устойчив к изменениям и прост, в отличии от того же Dapper. EF традиционно отстаёт, но проигрывает не сильно. При выполнении SQL-запросов через метод
FromSqlRaw EF показывает впечатляющие результаты, не очень сильно отставая от Dapper. Пока готовил бенчмарки, с ужасом осознал, что "готовить" EF я более-менее могу, а вот с Dapper и Linq2Db у меня сложности. Поэтому, если уважаемые читатели заметят какие-либо проблемы с кодом и его оптимальностью, я буду счастлив. Дело в том, что этим бенчмарком я получил неожиданные для себя результаты. Хотелось бы вернуть мир на место.
Кода много, поэтому он тут. Я думаю, что интересующимся не составит труда самостоятельно поднять PG в Docker'e и наполнить БД данными через миграцию в EF.
P.S.: Бенчи Ef_ToArray и Ef_ToList отдельно рассмотрены тут. То, что их результаты разные в данном измерении - скорее всего погрешность измерителя. Они должны быть плюс-минус одинаковыми.
