Здравствуйте, liiw, Вы писали:
L>В действительности время соединения тут не замеряется нигде, т.к. в ADO.NET используется Connection Pooling ( https://msdn.microsoft.com/en-us/library/8xx3tyca(v=vs.110).aspx )
Зато замеряется время создания контекста.
L>На открытие соединения по вышеприведённой причине тратится 0% времени, и измерять его не вижу смысла, т.к. оно не зависит от наличия LINQ'а и используемой ORM. Я хотел протестировать именно ORM.
L>Примерно так и есть, используется 100 итераций для разогрева и 1000 для замера. Делать больше не знаю есть ли смысл, т.к. ждать надо будет сильно дольше, а результаты немного прыгают между замерами (без влияния на результаты тестирования).
В результат попадает общее время или только среднее по 1000 "прогретых" запусков?
Здравствуйте, gandjustas, Вы писали: L>>Примерно так и есть, используется 100 итераций для разогрева и 1000 для замера. Делать больше не знаю есть ли смысл, т.к. ждать надо будет сильно дольше, а результаты немного прыгают между замерами (без влияния на результаты тестирования). G>В результат попадает общее время или только среднее по 1000 "прогретых" запусков?
Сначала делается 100 итераций для разогрева. Это время никак не учитывается.
После этого делается 1000 итераций и берётся среднее время (время выполнения 1000 итераций делённое на 1000).
И так делается 3 раза. После этого берётся среднее из 3х раз.
Здравствуйте, IT, Вы писали:
I>>Пудозреваю, именно здесь якобы и есть те самые 90% о которых вещает alex_public
IT>Нет. Там в принципе другой тест должен быть, в котором на каждый запрос открывается соединение. Я это тоже тестировал. 90% не наблюдал в упор.
А почему не надо замерять инициализацию контекста, раз обычно создают один раз на реквест ?
Здравствуйте, liiw, Вы писали:
L>Тесты тестируют скорость выволнения запросов . На время инициализации контекста можно не смотреть, т.к. что имеено в него входит я не знаю — можно смотреть только суммарное время выпонения запроса. Контекстом я хотел померять накладные расходы за вычетом самого запроса (компилция LINQ, выполнение запроса, материализация). И как видно по тестам, на что-то там ещё тратится время, хоть и незначительное.
А почему время инициализации контекста можно смотреть ? У тебя получается что выпячивается именно эта инициализация. Если контекст создаётся каждый раз на реквест, то на простецких запросах это вылезет.
То есть, непонятен сам тест, что он показывает, с учетом твоих коментариев. Если тест про то, что время инициализации сравнимо с временем работы маппинга, то это мне кажется надо как то иначе замерять.
Здравствуйте, Ikemefula, Вы писали:
I>Здравствуйте, liiw, Вы писали:
L>>Тесты тестируют скорость выволнения запросов :). На время инициализации контекста можно не смотреть, т.к. что имеено в него входит я не знаю — можно смотреть только суммарное время выпонения запроса. Контекстом я хотел померять накладные расходы за вычетом самого запроса (компилция LINQ, выполнение запроса, материализация). И как видно по тестам, на что-то там ещё тратится время, хоть и незначительное.
I>А почему время инициализации контекста можно смотреть ? У тебя получается что выпячивается именно эта инициализация. Если контекст создаётся каждый раз на реквест, то на простецких запросах это вылезет. I>То есть, непонятен сам тест, что он показывает, с учетом твоих коментариев. Если тест про то, что время инициализации сравнимо с временем работы маппинга, то это мне кажется надо как то иначе замерять.
Не очень понял вопрос. Почему нужно (а не "можно") смотреть время инициализации контекста?
Я рассуждал так.
Есть время выполнения запроса — создание SQL комманды (с помощью LINQ или сразу текста), посылка её SQL-серверу, выполнение команды SQL-сервером, чтение ответа SQL-сервера, и материализация данных.
У меня было предположение, что помимо самого выполнения запроса на суммарное время могут влиять другие факторы. Какие — не суть важно. Я назвал эти факторы инициализацией контекста.
И это не обязательно только создание класса — "new NorthwindEfDbContextCodeFirst()". Может непосредственно при вызове SQL-запроса что-то ещё делается. Не суть важно. Я хотел померять это.
Результат — т.к. это время получилось относительно маленьким, то для реальных запросов (т.е. не однострочных типа "SELECT * FROM Table1") его влияние можно не учитывать. Не учитывать для ADO.NET и LINQ2DB. Для EF нужно учитывать — что при его использовании для не сильно сложных запросов это время может существенно влиять если запросов много.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, IT, Вы писали:
IT>>·>Как ни странно, но всё перечисленное не уступает, а чаще лучше в мире java, особенно если ещё всякие другие jvm-языки рассмотреть. IT>>Весьма голословное утверждение. Давай посмотрим хотя бы на LINQ в .NET и благодаря ему возможность работы с БД с использованием фактически типизированного SQL.
_>Кстати, весьма тормознутая вещь. Вообще это решение достаточно феерично своей кривизной. Умудриться сделать проверку синтаксиса во время компиляции, но при этом строить sql строки в рантайме на базе тормознутой рефлексии — это просто нечто. )))
IT>>Ну и под конец главный козырь LINQ — type safety. Можете мне петь любые песни про любые тормоза, но это преимущество ни много ни мало переводит работу с БД на принципиально другой уровень. EP>Это преимущество достижимо и без runtime overhead. IT>>где высвобожденное время можно с успехом потратить, например, на архитектуру приложения и добиться лучшей производительности архитектурными решениями. А это уже может оказаться не 2%, а 2000. EP>Ага, вот прям высвобожденное время бегут тратить на архитектуру: для простейшего алгоритма в десяток строк в итоге нагенерили 4k строк — точно 2000%
Михаил Романов, Yoriсk, Danchik, вы не согласны с чем-то конкретным?
Здравствуйте, Ikemefula, Вы писали:
S>>>Ну, расскажите мне, какая из "многих популярных СУБД" выполняет prepared statements без помощи SQL. _>>Ну например в той же mysql http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html, которая будет попопулярнее вашего любимого SQL Server. ))) Я уже не говорю о том, что sqlite и т.п. встроенные решения априори работают в данном моменте без sql. ))) I>Это какая то глупая шутка. В качестве примера "без помощи SQL" ты показал "PREPARE, EXECUTE, and DEALLOCATE PREPARE Statements" I>
I>SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
I>PREPARE stmt2 FROM @s;
I>SET @a = 6;
I>SET @b = 8;
I>EXECUTE stmt2 USING @a, @b;
I>DEALLOCATE PREPARE stmt2;
I>
I>Первые две строчки выполнятся один раз. Остальное — каждый раз. И все это SQL. Да-да.
Меня всё больше пугают проблемы с твоим зрением. ))) Прямо по данной ссылке указанное тобой описывается как:
An alternative SQL interface to prepared statements is available. This interface is not as efficient as using the binary protocol through a prepared statement API, but requires no programming because it is available directly at the SQL level
Самое забавное, что это указано во второй части статьи, а в первой (которую твоё зрение не позволило увидеть) ясно написано:
MySQL 5.7 provides support for server-side prepared statements. This support takes advantage of the efficient client/server binary protocol.
Ну и чтобы до тебя окончательно дошло: в sql варианте для предкомпилированного запроса используется уникальное текстовое имя, а в нормальном (родными средствами) режиме естественно никаких уникальных имён не требуется.
Здравствуйте, Sinclair, Вы писали:
_>>Ну например в той же mysql http://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html, которая будет попопулярнее вашего любимого SQL Server. S>Ну да, всё правильно. В сервер уезжает стеймент EXECUTE. Который парсится на общих основаниях. S>Всё ровно точно так же, как и в моём любимом SQL Server. И в Postgres, к слову, также.
Здравствуйте, Ikemefula, Вы писали:
_>>И снова у тебя какие-то проблемы со зрением. Причём очень серьёзные, поскольку про ручное выписывание всех join я говорил в сообщения выше не один раз, а уже очень много. В положительном ключе естественно, т.к. это более правильный способ работы с РСУБД. I>А вот с объектной моделью это совсем не правильный способ.
С абстрактной объектной моделью и у linq всё плохо. Скажем если мы захотим поработать с банальным деревом, не говоря уже о более сложных структурах произвольной вложенности.
>>Кстати, глядя на все эти игры с join (правда это только речь про inner, в случае outer в linq вообще жуть рисуется) в linq возникает вопрос: а зачем там тогда from висит, может и его надо убрать? ))) I>Не ясно, где ты жуть увидел. I>
I>var q =
I> from c in categories
I> join p in products on c equals p.Category into ps
I> from p in ps.DefaultIfEmpty()
I> select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };
I>
Ну так куча синтаксического хлама. Даже чистый sql тут красивее выглядит.
Здравствуйте, Ikemefula, Вы писали:
_>>Ты похоже забыл что такое вообще ORM. ))) Напомню, что данное понятие зародилось задолго до всяких там linq. I>1 Автор sqlpp11 утверждает, что sqlpp11 не является OR/Mapper. I>2 современный OR/Mapper в обязательном порядке использует язык запросов. I>3 В дотнет такой язык как правило реализуется через linq, ибо искаропки получается унификация интерфейса со всеми остальными либами чз IQueryable. I>Пример — на платформе Java hibernate использует HQL I>
I>Hibernate Query Language (HQL) is an object-oriented query language, similar to SQL, but instead of operating on tables and columns, HQL works with persistent objects and their properties
Мне сейчас не охота заниматься словесными играми, так что в этот раз разберём вопрос быстро и просто. Ответь просто на один вопрос: Dapper — это ORM или нет? ) Думаю твой ответ сразу закончит данную дискуссию, т.к. после него уже больше не получится развлекаться демагогическими увёртками. )
Здравствуйте, IT, Вы писали: _>>Ну так если ты настаиваешь, что 5% — это самый большой возможный уровень накладных расходов у linq2db, то как ты тогда объясняешь 90% в данном http://liiw.blogspot.ru/2015/03/performance-of-linq-to-db-vs-entity.html тесте (случай Simple TOP 10 query)? IT>Это объясняется тем, что я вообще не понимаю что тестируют эти тесты. Вот мой тест: IT>
Скрытый текст
IT>
IT>using System;
IT>using System.Collections.Generic;
IT>using System.Configuration;
IT>using System.Data.SqlClient;
IT>using System.Diagnostics;
IT>using System.Linq;
IT>using DataModels;
IT>namespace ConsoleApplication3
IT>{
IT> class Program
IT> {
IT> static void Main(string[] args)
IT> {
IT> var sw = new Stopwatch();
IT> LinqTest(sw);
IT> AdoTest(sw);
IT> var n = LinqTest(sw);
IT> Console.WriteLine("LINQ: {0} in {1}", n, sw.Elapsed);
IT> n = AdoTest(sw);
IT> Console.WriteLine("ADO: {0} in {1}", n, sw.Elapsed);
IT> }
IT> static int LinqTest(Stopwatch sw)
IT> {
IT> sw.Reset();
IT> var count = 0;
IT> using (var ctx = new NorthwindDB())
IT> {
IT> for (var i = 0; i < 10000; i++)
IT> {
IT> sw.Start();
IT> var list =
IT> (
IT> from o in ctx.Orders
IT> join c in ctx.Customers on o.CustomerID equals c.CustomerID
IT> select new { o.OrderID, o.OrderDate, c.Country, c.CompanyName }
IT> ).Take(10).ToList();
IT> sw.Stop();
IT> count += list.Count;
IT> }
IT> }
IT> return count;
IT> }
IT> static int AdoTest(Stopwatch sw)
IT> {
IT> sw.Reset();
IT> var count = 0;
IT> using (var con = new SqlConnection(ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString))
IT> {
IT> con.Open();
IT> for (var i = 0; i < 10000; i++)
IT> {
IT> sw.Start();
IT> var list = new List<object>();
IT> using (var cmd = new SqlCommand(@"
IT> SELECT TOP (10)
IT> [o].[OrderID],
IT> [o].[OrderDate],
IT> [c].[Country],
IT> [c].[CompanyName]
IT> FROM
IT> [dbo].[Orders] [o]
IT> INNER JOIN [dbo].[Customers] [c] ON [o].[CustomerID] = [c].[CustomerID]", con))
IT> {
IT> using (var reader = cmd.ExecuteReader())
IT> {
IT> if (reader.HasRows)
IT> {
IT> while (reader.Read())
IT> {
IT> list.Add(new
IT> {
IT> OrderID = (int)reader["OrderID"],
IT> OrderDate = (DateTime)reader["OrderDate"],
IT> Country = (string)reader["Country"],
IT> CompanyName = (string)reader["CompanyName"],
IT> });
IT> }
IT> }
IT> }
IT> }
IT> sw.Stop();
IT> count += list.Count;
IT> }
IT> }
IT> return count;
IT> }
IT> }
IT>}
IT>
IT>Отличается от предыдущих тем, что более менее отражает реалии жизни. Во-первых, БД находится на другой машине. Во-вторых, в реальности на ADO.NET так никто не пишет. Ни один вменяемый разработчик не будет использовать индексы вместо имён полей. Такой код живёт ровно до первого изменения. IT>Результат: IT>
IT>LINQ: 100000 in 00:00:05.7321425
IT>ADO: 100000 in 00:00:05.5328326
IT>
IT>Разница в районе одного процента туда суда. А если я ещё добавлю в тест ADO.NET проверку на DBNull, то он вообще может оказаться медленнее.
Предложенный тобой тест не имеет никакого отношения к обсуждаемой теме (тормозам от Linq), потому как в нём используются не только разные методы формирования запросов, но и разные методы обработки получаемых данных. Так что результаты подобного теста вообще ни о чём полезном сказать не могут. Для получения истинного значения накладных расходов от linq проведи буквально этот же тест, но только между linq2db в режиме linq и linq2db в режиме row sql.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, все. IT>Ещё раз попытаюсь объяснить где у LINQ могут быть тормоза и насколько они влияют на общую картину.
1. Ну вот наконец то адекватный текст, а не жалкая истерика, как у некоторых местных "фанатов".
2. Если говорит в рамках мирка C#, то собственно никаких особых возражений к данному тексту быть не может.
3. Если не ограничивать себя рамками C#, то неявно прозвучавшая в твоём тексте дилемма "или дополнительные накладные расходы (степень их ужасности должна оцениваться для каждого отдельного проекта индивидуально) или статический анализ" уже становится ложной.
Здравствуйте, IT, Вы писали:
EP>>С тем что для некоторых задач этот overhead не критичен? Так с этим и я не спорю. IT>Для некоторых — это примерно 99%.
Насчёт критичности для 1% (понятно что цифра условная) — это верно. Но и для очень многих других накладные расходы тоже актуальны, т.к. это всё на практике стоит вполне реальных денег. Причина же использования всех этих тормознутых решений довольно банальна — затраты на оплату работы "оптимизатора" в большинстве случаев больше, чем затраты на оплату ресурсов для этих самых накладных расходов. Однако если появится инструмент (собственно такое уже не раз бывало во многих направлениях), позволяющий легко (без привлечения крутых "оптимизаторов") разрабатывать продукт без соответствующих накладных расходов, то вся индустрия очень быстро начнёт переползать на него...
IT>Про D не знаю, но что-то ничего не слышал о том, чтобы он полноценно поддерживал разработку DSL.
Можешь глянуть например здесь: http://vibed.org — вполне интересный продукт сам по себе. Ну а если тебе всё же лень копаться, то прокомментирую: там используется полноценный шаблонизатор html страниц (с синтаксисом типа Jade), в котором страницы компилируются в бинарный исполняемый файл (сервера). Так вот это происходит без всяких препроцессоров и т.п., просто силами самого компилятора D. )))
Ну и D — это опять же не единственный пример. В том же Rust'e макросы способны например такое: https://github.com/sfackler/rust-postgres-macros. Понятно что это немного не то, что мы обсуждали в данной темке. Но если уж можно такое, то без проблем реализуется и статический генератор запросов. Надо просто сесть и написать. )))
Здравствуйте, alex_public, Вы писали:
_>2. Если говорит в рамках мирка C#, то собственно никаких особых возражений к данному тексту быть не может.
Давай без пафоса, а только факты. "Мирок" C# вместе с "мирком" Java покрывает сегодня "мега вселенную" C++ как бык овцу.
_>3. Если не ограничивать себя рамками C#, то неявно прозвучавшая в твоём тексте дилемма "или дополнительные накладные расходы (степень их ужасности должна оцениваться для каждого отдельного проекта индивидуально) или статический анализ" уже становится ложной.
Ничего не понял. Оценивать нужно не индивидуальные проекты, а типичные сценарии. В типичных сценариях, как мы выяснили, накладные расходы вменяемого linq провайдера несущественны, а приведённые тобой средства, как мы тоже уже тоже разобрались, не болле, чем овца.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, alex_public, Вы писали:
_>Предложенный тобой тест не имеет никакого отношения к обсуждаемой теме (тормозам от Linq), потому как в нём используются не только разные методы формирования запросов, но и разные методы обработки получаемых данных. Так что результаты подобного теста вообще ни о чём полезном сказать не могут.
Это как? Приведённые тесты более точно отражают реалии. Если тебе не эти тесты, потому что они тебя не устраивают, то это твоя личная проблема. Можешь написать свой вариант и мы его обсудим.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, alex_public, Вы писали:
_>С абстрактной объектной моделью и у linq всё плохо.
Плохо по сравнению с чем? С твоими абстрактными фантазиями? Не спорю, мои абстрактные фантазии тоже иногда бывают такими абстрактными...
_>Ну так куча синтаксического хлама. Даже чистый sql тут красивее выглядит.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
_>>2. Если говорит в рамках мирка C#, то собственно никаких особых возражений к данному тексту быть не может. IT>Давай без пафоса, а только факты. "Мирок" C# вместе с "мирком" Java покрывает сегодня "мега вселенную" C++ как бык овцу.
Угу, "галантерейщик и кардинал — это сила... "))) Может Java и слегка обходит C/C++ по популярности (при этом прямая конкуренция у них минимальная), но в любом случае они оба где-то очень далеко от C#. )))
_>>3. Если не ограничивать себя рамками C#, то неявно прозвучавшая в твоём тексте дилемма "или дополнительные накладные расходы (степень их ужасности должна оцениваться для каждого отдельного проекта индивидуально) или статический анализ" уже становится ложной. IT>Ничего не понял. Оценивать нужно не индивидуальные проекты, а типичные сценарии. В типичных сценариях, как мы выяснили, накладные расходы вменяемого linq провайдера несущественны, а приведённые тобой средства, как мы тоже уже тоже разобрались, не болле, чем овца.
Это всего лишь твоё личное мнение, которое по моему личному мнению имеет мало что общего с истиной. )