Pull to refresh

Comments 17

Субъективно насколько ef core тормознутый? Вроде быстрее чем на 4.5? Но тоже вопрос на сколько? Иной раз кажется что орм по джаву все равно быстрее! Так как там очень экосистема развита!

Dapper бы еще в сравнение ;)
А смысл? Быстрее чем ADO.NET не будет. Если LINQ2DB использовать только как мэппер (писать запросы руками текстом), то он не медленнее ADO.NET. Да и даже если использовать LINQ-запросы то LINQ2DB почти так же быстр как ADO.NET. Выбор очевиден :).
Смысл посмотреть, сможет ли LINQ2DB потягаться с Dapper на сценариях с raw sql запросами. Судя по тестам Dapper он очень близок к ADO.
LINQ2DB не только может потягаться но и как минимум не хуже, т.к. не проигрывает ADO.NET (и дапперу значит тоже) — видно по результату «LINQ to DB raw SQL query».
Я бы поставил вопрос наоборот — может ли даппер потягаться с LINQ2DB? На мой взгляд не может — даже если даппер так же быстр, он не умеет LINQ. Используя linq2db можно использовать LINQ не думая о производительности, а в крайнем случае всегда можно написать raw SQL.
Вот тесты бы живые посмотреть :)
LINQ не думая о производительности? :) Может в BenchmarkDotNet пару тестов накидаете LINQ vs Raw SQL;)
Ну и неплохо было бы для начала поддержку NetStandard увидеть.
Было бы неплохо для начала поддержку асинхронности сделать. Я врядли бы взял нычне билиотеку, которая работает с i\o и не имеет асинхронного API. все остальные бенефиты нивелируються на фоне этого минуса.
Если сравнивать с Dapper, его движок работает с reflection emit, linqtodb с lazy expression — которые он использует для сиквела и для маппинга, скорость приблизительно одинакова — кромме первой прогонки, когда linqtodb будет сливать колосально из-за необходимости построить sql и скомпилировать делегат для мапера IDataRecord -> IEnumerable.
Но как я сказал на фоне такого глобального недостатка как отсуствие асинхронной работы с бд и повсеместное блокирование потоков — это колосальный минус и пережиток прошлого, тут и dapper и даже медленный EF во многих сценариях остануться предпочтительней.
Вот интересно посмотреть как на микробенчмакре будут показывать себя LINQ запросы. Выражение то все равно собирается в юзер коде. Тоесть есть какой-то оверхед на GC. Поправьте если не прав.
И NetStandard не наблюдается чет в Nuget…
А можете указать в коде linq2db где они блочат потоки и нет асинхронной работы с бд?
судя по коду они асинхронно вызывают ADO.NET ридеры…
Заходим на доку:
https://github.com/linq2db/linq2db

return query.ToList();

products.Count();

Ничего об асинхронности.

Смотрим дальше — что-то есть AsyncExtensions.cs…

Заглядываем внутрь:
public static Task<List> ToListAsync(this IQueryable source, CancellationToken token)
{
return GetTask(
() => source.AsEnumerable().TakeWhile(_ => !token.IsCancellationRequested).ToList(),
token);
}

Cихнронный блокирующий код запущен в отдельном потоке — антипатерн. Синхронная блокирующая работа с I\O замаскированная под асинхронность. В итоге имеем истощение тред пулла — и общие тормоза приложения. Лучше чем писать такое, просто писать синхронный блокирующий код и не запускать его на тред пуле с блокированием.

Я уже накидал тесты по ссылке выше :). В том числе и [LINQ via LINQ2DB] vs [raw SQL via LINQ2DB] vs [raw SQL via ADO.NET]. Причём raw SQL через LINQ2DB ещё и маппит результаты а не вручную как с ADO.NET и всё равно не отстаёт.
Да, если использовать LINQ2DB то можно не думать (или почти не думать) о производительности. Некоторые вообще EF используют — с ним конечно надо думать. Хотя у EF Core уже намного лучше с этим.
Чет все в одну кучу намешали :)
1. Как dotnetdonik заметил, нет async.
2. Все тесты последовательные с одним запросом. Сделайте хотя бы 32 потока.
3. Важно сколько объектов генерится при обработке каждого запроса. Поэтому и просил BenchmarkDotNet со статистикой GC ;)
Как спросили всё вместе так и ответил :).
1) Это к автору linq2db. Я не использую, но вот вроде есть — AsyncTests.cs.
2) Я сделал тесты, которые интересовали меня, а вы можете сделать те, которые интересуют вас и поделиться результатами :). Код в паблике если вдруг нужен.
3) Мне более важно чтобы быстро работало. Вот когда появится ORM которая будет быстрее чем LINQ2DB, тогда автор (а не я) пусть и смотрит статистику GC или ищет другую причину почему так :).
Тоесть есть какой-то оверхед на GC. Поправьте если не прав.

Основной оверхед при
скомпилировать делегат для мапера IDataRecord -> IEnumerable
— очень медленно
и при
построить sql из expression

Когда это делается в первый раз это тоже медленней чем собрать sql и строки. т.е. каждое новое linq выражение будет давать небольшой оверхед — это проход по дереву выражений естественно с доп обьектами и операциями т.д.
Синтетические тесты плохой пример — они работают с одним и тем же типом и одним и тем же запросом, который linqtodb закеширует и не будет показывать реальной картины.

В целом это нормальный подход при наличии кеша, а он есть у linqtodb. Основной недостаток этой библиотеки блокирующий синхронный API для работы с базой — все миллисекунды выигрыша полностью нивелирует этот подход с точки зрения вреда для приложения.
У меня есть пара замечаний:
Во-первых переименуйте хотя бы контекст, потому что название в 55 символов не читается.
Во-вторых Вас должен был напрячь тот факт, что для создания ограничения уникальности (п. 9) приходится в 2х местах вручную добавлять код (а в ModelSnapshot особенно осторожно). Ограничение надо было добавить в модель в контексте, перегрузив метод DbContext::OnModelCreating и потом создать миграцию:
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<City>()
                .HasIndex(I => I.Name)
                .IsUnique();
        }
Sign up to leave a comment.

Articles