Re[13]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 14.04.15 23:46
Оценка: -1
Здравствуйте, gandjustas, Вы писали:

G>>>Ну ок, возьми не C#, а любой другой статически типизированный язык. В любом языке все придет к формированию деревьев выражений на основе конструкций языка, которые потом надо будет отобразить на метаданные классов и на базе этого построить SQL. Так что накладные расходы также будут присутствовать.

EP>>Вот конкретный пример: compile-time template engine
Автор: Evgeny.Panasyuk
Дата: 12.10.14

EP>>В compile-time делается анализ строки, и на основе этого генерируется определённая последовательность вызовов, результирующий ASM код получается идентичным тому, который соответствует полностью ручному оптимальному коду.
G>А при чем тут Linq? Он как раз может не имея целого запроса в одном месте собрать его по кускам. Обратная задача не нужна.

При том что ты выше говорил что формирование деревьев выражений на основе конструкций языка, с отображением на классы, и последующем построением SQL будет давать накладные расходы.
Пример же показывает что возможно делать compile-time обработку без накладных расходов. Это конечно не LINQ, но представление о стоимости compile-time процессинга вполне может дать.

G>Ну ок, возьми не C#, а любой другой статически типизированный язык. В любом языке все придет к формированию деревьев выражений на основе конструкций языка, которые потом надо будет отобразить на метаданные классов и на базе этого построить SQL. Так что накладные расходы также будут присутствовать.


Дело в том что деревья выражений можно полностью обрабатывать в compile-time, точно также как и обходить метаданные классов, точно также как и строить SQL запрос по этим данным — неоткуда тут взяться накладным расходам времени выполнения.
Отредактировано 14.04.2015 23:47 Evgeny.Panasyuk . Предыдущая версия .
Re[21]: EntityFramework - тормоз
От: alex_public  
Дата: 15.04.15 03:55
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Отличный пример. Запрос секунду обрабатывался почему? Наверное потому что данные были на диске, а не в памяти. И какбы идеально, чтобы меньше запросов требовало чтения с диска. Но если у тебя часть памяти сервера скушано кешем запросов, то чтения с диска будут происходить чаще, что приведет к общему снижению быстродействия.

G>Если же у тебя кеш получился высокоэффективный, и большая часть отдается из кеша, то в случае отсуствия кеша у тебя будут данные самих таблиц находиться в памяти и эффективно обслуживать все запросы, а не только те, которые совпадают буква-в-букву.

Вообще то размера кэша обычно измеряется в мегабайтах, а не гигабайтах, так что о влияние его размера на оперативную память говорить просто смешно. Но даже если бы это было и так. Ты действительно считаешь, что на маленьких (помещающихся в оперативную память) базах сумеешь добиться без кэширования времени обработки запроса измеряемого в микросекундах? )

G>Вообще MySQL изобилует сомнительными решениями, я бы не стал его в пример приводить.


http://www.oracle-developer.net/display.php?id=503 Oracle тоже является сомнительным инструментом? ))) Да, и кстати говоря... Даже если бы это работало исключительно в mysql, то твой очаровательный тезис "на уровне БД кеширования запросов нет, угадай почему" всё равно отлично демонстрировал бы твой уровень познаний. )))

Кстати, а если делать кэширование не в БД, а в приложение (как ты вроде и хотел), то как тогда проверяется, что нужные данные не изменены в БД другим приложением?

_>>Как ты думаешь, будут ли на таком фоне заметны тормоза linq или нет? )

G>Нет, даже если у тебя приложение только и делает, что получает одну и ту же строку запроса. А если приложение более сложное и делает более сложные запросы, то даже под микроскопом не различишь.

Проверим на практике? ))) Берём некую БД с кэшированием запросов и пишем к ней 3 варианта одного и того же запроса: через sql строку, через linq, через sqlpp11. И посмотрим насколько процентов будут отличаться результаты...

G>Накладыне расходы на Linq видны при масштабе. Когда у тебя тысячи запросов в секунду, убрав linq можешь получить пару процентов прироста быстродействия. А если у тебя приложение только и делает, что ждет ответ от СУБД, то отказ от Linq ничего не даст вообще.


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

G>Я что-то не вижу как компилятор проверяет, что нельзя обращаться к row.feature если не выполнилась строка dysel.selected_columns.add(p.feature). Более того, мои знания языка C++ говорят что тип row в цикле for (const auto& row : db(dysel)) статический и проекцию никак не учитывает.


Ты что-то невнимательно читаешь опять же. Там нет вообще обращения к row.feature в случае использования dysel.selected_columns.add(p.feature) — используется другой механизм доступа к полю. Собственно обращение к row.feature вызовет ошибку компиляции (при использование dynamic_select(db).dynamic_columns(p.name).from(p).dynamic_where()) вне зависимости от наличия или отсутствия вызовов selected_columns.add(p.feature).

Однако это всё поддержка для случаев "совсем динамики", когда надо не просто сформировать динамический запрос и выполнить его, но ещё и обязательно его куда-то пересылать (т.е. чтобы у самого запроса был одинаковый тип при любом варианте ветвления) или что-то подобное. Естественно оно всё равно намного эффективнее варианта с linq, но лично я даже такое редко использую, потому как для большинства случаев (включая твой же первый пример в данной темке, который с if'ми) гораздо проще и удобнее сформировать два (ну или сколько там надо, в зависимости от количества ветвлений) статических запроса и сразу же выполнить их по месту.

G>Или например джоин:

G>
G>select(p.id, x.name).from(p.join(x).on(p.feature == x.feature)
G>

G>Я не очень понимаю как компилятор будет проверять, что указанное в select реально есть в таблицах, указанных во from. Аналогичная проблема в предикатом джоина, неясно как проверяется что выражение в предикате соответствует таблицам во from и join.

Нуу ты приглядись к select повнимательнее — на самом деле таблицы указаны прямо в нём (p и x же имеют свои типы). Т.е. поле from реально приносит пользу только как раз для всяких там join и т.п., а в обычных запросах присутствует скорее для красоты (хотя если передать туда неверную таблицу, то всё равно будет ошибка).

G>Так что я не верю что такм такой же уровень типизации, как в Linq. Покажи пример что будет если попробовать составить неправильный запрос.

G>А также приведи пример как навесить джоин на уже существующий запрос.

И это тоже всё есть в тех же самых примерах. Например если ты заменишь здесь https://github.com/rbock/sqlpp11/blob/master/examples/select.cpp#L57 "#if 0" на "if !0", то получишь две ошибки:
select.cpp:60:20: error: 'const struct sqlpp::result_row_t<MockDbT<false>, sqlpp::field_spec_t<test::TabPerson_::Name::_alias_t, sqlpp::text, false, false> >' has no member named 'id'
   int64_t id = row.id;
                   ^
select.cpp:62:25: error: 'const struct sqlpp::result_row_t<MockDbT<false>, sqlpp::field_spec_t<test::TabPerson_::Name::_alias_t, sqlpp::text, false, false> >' has no member named 'feature'
   int64_t feature = row.feature;                         ^


Да, и правильно что не веришь (вообще конечно это интересное слово в устах инженера...), что тут всё так же как в linq. Потому как тут очевидно лучше и эффективнее. )))

_>>Зато в библиотечке примеры вполне даже компилируемые. Но ты их похоже принципиально не замечаешь. )

G>Только там от силы 10% того, что умеет linq.
G>Тут два варианта: или больше не умеет, или не все так хорошо, как ты описываешь.
G>Поэтому приведи аналог того примера, что я писал и мы поверим. А пока — увы. Аналогов linq и близко нет.

Эм, а с чего ты взял, что тут кто-то пытается создать аналог linq? ) Пытаться повторить кривой инструмент? Нет, спасибо, такого не надо. Нам нужно построить удобный и эффективный инструмент для работы с SQL БД. И мы этот инструмент имеем — полное статически типизрованное отражение sql в язык.
Re[13]: EntityFramework - тормоз
От: alex_public  
Дата: 15.04.15 04:09
Оценка: 1 (1)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>А почему предпочитаешь "лёгкие" решения?

EP>Я понимаю если база данных уже есть сама по себе, и всё что нужно это сделать несколько запросов — то тут конечно "лёгкие" решения оптимальны.
EP>Но если же нам нужно отображать развесистую модель данных на БД, которая при этом ещё и изменяется во времени — то ведь в этом случае больше подходит "тяжёлый комбайн", нежели рукопашная реализация его фич поверх "лёгких" решений.

Нуу т.к. у меня задачи обычно где-то посередине между этими двумя крайностями (БД создаётся под приложение, но при этом обычно неизменна на протяжение жизни), то тут уже выбор становится по сути делом вкуса. ))) Ну а т.к. я вообще не очень люблю какие-либо фреймворки, то... )
Re[8]: EntityFramework - тормоз
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.04.15 05:50
Оценка: 1 (1)
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>То есть обычно ORM используют третий (смешанный) вариант, отсюда и проблемы?
ORM, которые бы навязывали хранимки, мне неизвестны. Но зачастую смешанный вариант используют поклонники хранимок как решения проблемы производительности ORM. Просто потому, что не отдают себе отчёта в этой проблеме, и у них нет мотивации идти до конца — т.е. превращать SQL в сервер приложений, мигрируя в хранимки/триггеры/view всю прикладную логику.

EP>Например в ODB вся логика обработки данных содержится в одном месте. И если, например, произойдёт откат базы — то при доступе к ней произойдёт обновление схемы и миграция данных (причём есть опция постепенного перехода).

Звучит неплохо. Подробности надо изучать. Во времена, когда я этим интенсивно занимался, никаких ODB ещё не было. Были Versant, Gemstone, а ORM существовали в виде рекомендаций Фаулера, а не готовых фреймворков.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: EntityFramework - тормоз
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.04.15 05:53
Оценка: +1
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, Sinclair, Вы писали:


_>Ну так мы же можем без проблем реализовать такое на уровне склейки sql строк, не так ли? ) Тогда почему возникают сомнения, что можно написать статически типизируемый код, который компилируется в полный аналог такой склейки строк?

Потому, что вы уже пять сообщений подряд уклоняетесь от того, чтобы показать нам этот код.
_>Гмммм, насколько я помню, ты же вроде в курсе C++. Тогда откуда такие вопросы? Это же вот прямо самый базисный принцип программирования на шаблонах C++, из-за которого разбухают итоговые бинарники, но при этом достигается непревзойдённая производительность.
Это общие слова. Пока что я не вижу способа, которым бы они воплотились в действие. Вы покажите код, чтобы было что обсуждать. Базисные принципы программирования тут неинтересны — их так много, что можно подвести подходящий принцип под любое высказывание и под его отрицание.

_>Ммм, варианта от Евгения мало что ли? )

Он использует какую-то другую библиотеку, чем вы (причём непонятно какую).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[20]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.04.15 09:05
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>Это не в C++ взаимоисключающие, а по сути. То есть даже при использовании внешнего генератора (с любым языком), в случае с .dll из пункта 1, есть выбор:

EP>* либо выносить в интерфейс "жёсткий" тип запроса, который при изменении запроса будет меняться (и требовать переборки зависимого кода), но что позволит в месте вызова запроса производить полную compile-time обработку, без всякого runtime overhead'а.
EP>* либо же делать стирание типа, что даст "мягкий" тип запроса, который не будет зависеть от его мелких деталей, но при этом мы неизбежно получаем runtime penalty — так как в месте вызова запроса мы уже не знаем всех его деталей во время компиляции, и полностью построить его в compile-time не сможем.

EP>Этот выбор продиктован не какими-то недостатками C++, а самой задачей, и не зависит от языка/технологии. Там где нужна динамика приходится платить в рантайме.


Опять чуда не случилось. C++ со всем метапрограммированием помогает только в статическом случае, который с точки зрения генерации SQL даже неинтересен. А когда динамика, то ничего близкого к linq нету. Хотя изначально утверждалось обратное.
Re[14]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.04.15 09:07
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, gandjustas, Вы писали:


EP>При том что ты выше говорил что формирование деревьев выражений на основе конструкций языка, с отображением на классы, и последующем построением SQL будет давать накладные расходы.

EP>Пример же показывает что возможно делать compile-time обработку без накладных расходов. Это конечно не LINQ, но представление о стоимости compile-time процессинга вполне может дать.
Да ни о чем пример, так как он статическую строку обрабатывает.

EP>Дело в том что деревья выражений можно полностью обрабатывать в compile-time, точно также как и обходить метаданные классов, точно также как и строить SQL запрос по этим данным — неоткуда тут взяться накладным расходам времени выполнения.

Это только в случае статического дерева, который крайне неинтересен.
Re[22]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.04.15 09:21
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, gandjustas, Вы писали:


G>>Отличный пример. Запрос секунду обрабатывался почему? Наверное потому что данные были на диске, а не в памяти. И какбы идеально, чтобы меньше запросов требовало чтения с диска. Но если у тебя часть памяти сервера скушано кешем запросов, то чтения с диска будут происходить чаще, что приведет к общему снижению быстродействия.

G>>Если же у тебя кеш получился высокоэффективный, и большая часть отдается из кеша, то в случае отсуствия кеша у тебя будут данные самих таблиц находиться в памяти и эффективно обслуживать все запросы, а не только те, которые совпадают буква-в-букву.

_>Вообще то размера кэша обычно измеряется в мегабайтах, а не гигабайтах, так что о влияние его размера на оперативную память говорить просто смешно. Но даже если бы это было и так. Ты действительно считаешь, что на маленьких (помещающихся в оперативную память) базах сумеешь добиться без кэширования времени обработки запроса измеряемого в микросекундах? )

Если кеш меряется в мегабайтах, то это настолько маленькая база, что нет смысла говорить о быстродействии. Её можно полностью затянуть в память приложения и по ней ходить. Естественно в этом случае скорость выполнения запросов составит микросекунды.


G>>Вообще MySQL изобилует сомнительными решениями, я бы не стал его в пример приводить.


_>http://www.oracle-developer.net/display.php?id=503 Oracle тоже является сомнительным инструментом? ))) Да, и кстати говоря... Даже если бы это работало исключительно в mysql, то твой очаровательный тезис "на уровне БД кеширования запросов нет, угадай почему" всё равно отлично демонстрировал бы твой уровень познаний. )))

А ты по ссылкам не читал дальше? Вот например http://www.pythian.com/blog/oracle-11g-result-cache-tested-on-eight-way-itanium/
Оказывается кеш в оракле плохо масштабируется, и по умолчанию он выключен. Видимо для очень специфических сценариев применяется. Включенного кеша я ни на одном оракловом сервере не видел.

_>Кстати, а если делать кэширование не в БД, а в приложение (как ты вроде и хотел), то как тогда проверяется, что нужные данные не изменены в БД другим приложением?

Ты удивишься, но 90%+ критичных к скорости приложений не допускают в базу другие приложения. В оставшихся 10% можно таймстемпы и тригеры прикрутить.

_>Проверим на практике? ))) Берём некую БД с кэшированием запросов и пишем к ней 3 варианта одного и того же запроса: через sql строку, через linq, через sqlpp11. И посмотрим насколько процентов будут отличаться результаты...

Вперед, пиши. Пример на C# я привел, давай аналогичный на голом SQL и sqlpp11.
Еще раз напомню, что ты утверждал, что можно сделать быстрее без потери возможностей linq. Вот и делай пример.

G>>Накладыне расходы на Linq видны при масштабе. Когда у тебя тысячи запросов в секунду, убрав linq можешь получить пару процентов прироста быстродействия. А если у тебя приложение только и делает, что ждет ответ от СУБД, то отказ от Linq ничего не даст вообще.


_>Ну если у тебя все запросы очень медленные и нет кэширования, то возможно тормознутость linq и не заметна. Только не стоит считать, что все вокруг имеют дело с точно такой же ситуацией.

Случай примитивных запросов рассматривать неинтересно. В linq их можно прогнать через compiled query и расходы на создание\обход деревьев упадут до нуля.

G>>Я что-то не вижу как компилятор проверяет, что нельзя обращаться к row.feature если не выполнилась строка dysel.selected_columns.add(p.feature). Более того, мои знания языка C++ говорят что тип row в цикле for (const auto& row : db(dysel)) статический и проекцию никак не учитывает.


_>Ты что-то невнимательно читаешь опять же. Там нет вообще обращения к row.feature в случае использования dysel.selected_columns.add(p.feature) — используется другой механизм доступа к полю. Собственно обращение к row.feature вызовет ошибку компиляции (при использование dynamic_select(db).dynamic_columns(p.name).from(p).dynamic_where()) вне зависимости от наличия или отсутствия вызовов selected_columns.add(p.feature).

То есть я добавил в проекцию поле и не могу обратиться к нему? Это гениально!

_>Однако это всё поддержка для случаев "совсем динамики", когда надо не просто сформировать динамический запрос и выполнить его, но ещё и обязательно его куда-то пересылать (т.е. чтобы у самого запроса был одинаковый тип при любом варианте ветвления) или что-то подобное. Естественно оно всё равно намного эффективнее варианта с linq, но лично я даже такое редко использую, потому как для большинства случаев (включая твой же первый пример в данной темке, который с if'ми) гораздо проще и удобнее сформировать два (ну или сколько там надо, в зависимости от количества ветвлений) статических запроса и сразу же выполнить их по месту.

Понятно, значит ничего не умеет, так и запишем.

У меня был код, в котором linq запрос формировался с учетом около 8 параметров. Это 256 вариантов (на практике около 150 корректных). Посмотрю я как ты их все выписывать будешь.


_>Нуу ты приглядись к select повнимательнее — на самом деле таблицы указаны прямо в нём (p и x же имеют свои типы). Т.е. поле from реально приносит пользу только как раз для всяких там join и т.п., а в обычных запросах присутствует скорее для красоты (хотя если передать туда неверную таблицу, то всё равно будет ошибка).

То есть типизированных джоинов тоже нет.

Ладно, продолжать неинтересно. Я уже увидел что от силы 10% возможностей linq покрывается, и то самых простых.
Re: EntityFramework - тормоз
От: koodeer  
Дата: 15.04.15 10:24
Оценка:
Когда в теме сошлись такие дотнетчики, как gandjustas, и плюсисты, как Evgeny.Panasyuk и alex_public, мне стало ясно, как будет идти их общение. Крестоносцы будут говорить, что в плюсах можно сделать всё (и даже больше!), а шарписты требовать: ты покажи именно то, что я написал!

Припоминается такой же стиль общения в теме по async.

И, как и в прошлый раз, я напишу следующее: имхо, C++ действительно позволяет всё то, что есть в C#/linq. Но дело в том, что linq/EF в мире .NET — это обыденная вещь, которую используют даже начинающие. А в C++ использование метапрограммирования и всех тех вкусностей, что приводили вышеупомянутые товарищи, доступно лишь немногим джедаям, и уж точно не новичку.
Re[2]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 15.04.15 11:41
Оценка: +1
Здравствуйте, koodeer, Вы писали:

K>Когда в теме сошлись такие дотнетчики, как gandjustas, и плюсисты, как Evgeny.Panasyuk и alex_public, мне стало ясно, как будет идти их общение. Крестоносцы будут говорить, что в плюсах можно сделать всё (и даже больше!), а шарписты требовать: ты покажи именно то, что я написал!


Тут всё же дискуссия не о том как сделать LINQ в C++, а о том что этот самый LINQ в большинстве случаев может быть/(мог бы быть) более оптимальным, даже в том же C#. То есть всё закрутилось вокруг:

G>>Ты ищешь какие-то накладные расходы в linq, хотя я тебе уже написал, что это обход expression tree, от которого ты никуда не денешься, какой бы DSL ты не создал.
_>Это вполне может отрабатываться на этапе компиляции.

В рамках C++ это возможно, но с заморочками, так ещё нет встроенного compile-time reflection. В рамках D и Nemerle это тоже возможно, но намного проще чем в C++. А вот в C#, насколько я вижу, это невозможно, но вполне реализуемо в качестве внешнего инструмента.
Re[2]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.04.15 12:32
Оценка:
Здравствуйте, koodeer, Вы писали:

K>И, как и в прошлый раз, я напишу следующее: имхо, C++ действительно позволяет всё то, что есть в C#/linq. Но дело в том, что linq/EF в мире .NET — это обыденная вещь, которую используют даже начинающие. А в C++ использование метапрограммирования и всех тех вкусностей, что приводили вышеупомянутые товарищи, доступно лишь немногим джедаям, и уж точно не новичку.

Пока никто не показал типизированные проекции и джоины в динамических запросах. Примерно та же проблема, что и с другими фичами яызка. Можно отдаленно повторить, если обвесить тонной макросов и шаблонов, в которых кроме автора никто не разберется в жизни.
Re[3]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.04.15 12:43
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, koodeer, Вы писали:


K>>Когда в теме сошлись такие дотнетчики, как gandjustas, и плюсисты, как Evgeny.Panasyuk и alex_public, мне стало ясно, как будет идти их общение. Крестоносцы будут говорить, что в плюсах можно сделать всё (и даже больше!), а шарписты требовать: ты покажи именно то, что я написал!


EP>Тут всё же дискуссия не о том как сделать LINQ в C++, а о том что этот самый LINQ в большинстве случаев может быть/(мог бы быть) более оптимальным, даже в том же C#.

Но вот примеров чего угодно с возможностями linq для построения запросов к базе мы не увидели. То что некоторые примеры на примитивных случаях работают быстрее не имеет никакой практической пользы.

EP>В рамках C++ это возможно, но с заморочками, так ещё нет встроенного compile-time reflection. В рамках D и Nemerle это тоже возможно, но намного проще чем в C++. А вот в C#, насколько я вижу, это невозможно, но вполне реализуемо в качестве внешнего инструмента.

Я вроде писал тебе про compiled query. В статическом случае все запросы прогоняются через него. А "с заморочками" вполне можно написать плагин компилятора, который эту операцию автоматизирует. То есть все статические запросы (определенные целиком внуnри метода без ветвлений), можно превратить в статические поля, которые созданы с помощью compiled query. И будут нулевые затраты.
Но это даст такой мизер, что имеет смысл заниматься минимум при масштабе StackOverflow.
Re[4]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 15.04.15 12:56
Оценка:
Здравствуйте, gandjustas, Вы писали:

EP>>В рамках C++ это возможно, но с заморочками, так ещё нет встроенного compile-time reflection. В рамках D и Nemerle это тоже возможно, но намного проще чем в C++. А вот в C#, насколько я вижу, это невозможно, но вполне реализуемо в качестве внешнего инструмента.

G>Я вроде писал тебе про compiled query. В статическом случае все запросы прогоняются через него.

При этом обходятся ET через runtime reflection

G>А "с заморочками" вполне можно написать плагин компилятора, который эту операцию автоматизирует. То есть все статические запросы (определенные целиком внуnри метода без ветвлений), можно превратить в статические поля, которые созданы с помощью compiled query. И будут нулевые затраты.


О чём собственно и речь, но ты почему-то говорил что это невозможно:

G>Ты ищешь какие-то накладные расходы в linq, хотя я тебе уже написал, что это обход expression tree, от которого ты никуда не денешься, какой бы DSL ты не создал.

G>Ну ок, возьми не C#, а любой другой статически типизированный язык. В любом языке все придет к формированию деревьев выражений на основе конструкций языка, которые потом надо будет отобразить на метаданные классов и на базе этого построить SQL. Так что накладные расходы также будут присутствовать.

Отредактировано 15.04.2015 12:58 Evgeny.Panasyuk . Предыдущая версия .
Re[5]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 15.04.15 13:18
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Здравствуйте, gandjustas, Вы писали:


EP>>>В рамках C++ это возможно, но с заморочками, так ещё нет встроенного compile-time reflection. В рамках D и Nemerle это тоже возможно, но намного проще чем в C++. А вот в C#, насколько я вижу, это невозможно, но вполне реализуемо в качестве внешнего инструмента.

G>>Я вроде писал тебе про compiled query. В статическом случае все запросы прогоняются через него.

EP>При этом обходятся ET через runtime reflection

Это не так. Но незнание деталей тебе простим.


G>>А "с заморочками" вполне можно написать плагин компилятора, который эту операцию автоматизирует. То есть все статические запросы (определенные целиком внуnри метода без ветвлений), можно превратить в статические поля, которые созданы с помощью compiled query. И будут нулевые затраты.


EP>О чём собственно и речь, но ты почему-то говорил что это невозможно:

EP>

G>>Ты ищешь какие-то накладные расходы в linq, хотя я тебе уже написал, что это обход expression tree, от которого ты никуда не денешься, какой бы DSL ты не создал.

EP>

G>>Ну ок, возьми не C#, а любой другой статически типизированный язык. В любом языке все придет к формированию деревьев выражений на основе конструкций языка, которые потом надо будет отобразить на метаданные классов и на базе этого построить SQL. Так что накладные расходы также будут присутствовать.


Я изначально говорил о динамической композиции запросов. И примеры приводил соответствующие. Если вы не удосужились пример прочитать и понять его суть, то зачем вообще спорить начали?
Вся тема началась с того, что кому-то не понравился EF и было предложение использовать хранимки. Но хранимки часто получаются медленнее, чем склейка запросов, которую прекрасно автоматизирует linq (linq2db, EF, linq2sql). Вообще не было речи о статических примитивных запросах. Это уже ты и _alex_public_ начали выкручиваться, сводя разговор к примитивным случаям.
Re[6]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 15.04.15 13:40
Оценка:
Здравствуйте, gandjustas, Вы писали:

EP>>>>В рамках C++ это возможно, но с заморочками, так ещё нет встроенного compile-time reflection. В рамках D и Nemerle это тоже возможно, но намного проще чем в C++. А вот в C#, насколько я вижу, это невозможно, но вполне реализуемо в качестве внешнего инструмента.

G>>>Я вроде писал тебе про compiled query. В статическом случае все запросы прогоняются через него.
EP>>При этом обходятся ET через runtime reflection
G>Это не так. Но незнание деталей тебе простим.

Что конкретно не так?
Компиляция compiled query происходит не в runtime? Или в runtime, но не через runtime reflection?
Re[7]: EntityFramework - тормоз
От: WolfHound  
Дата: 15.04.15 13:58
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Что конкретно не так?

EP>Компиляция compiled query происходит не в runtime? Или в runtime, но не через runtime reflection?
Она происходит один раз, а значит ей можно пренебречь.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 15.04.15 14:11
Оценка:
Здравствуйте, WolfHound, Вы писали:

EP>>Что конкретно не так?

EP>>Компиляция compiled query происходит не в runtime? Или в runtime, но не через runtime reflection?
WH>Она происходит один раз, а значит ей можно пренебречь.

С этим не буду спорить. Но тут-то речь о другом шла:

G>>>Я вроде писал тебе про compiled query. В статическом случае все запросы прогоняются через него.
EP>>При этом обходятся ET через runtime reflection
G>Это не так. Но незнание деталей тебе простим.

Тут какая-то ошибка в деталях?
Re[6]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 15.04.15 14:30
Оценка:
Здравствуйте, gandjustas, Вы писали:

EP>>О чём собственно и речь, но ты почему-то говорил что это невозможно:

EP>>

G>>>Ты ищешь какие-то накладные расходы в linq, хотя я тебе уже написал, что это обход expression tree, от которого ты никуда не денешься, какой бы DSL ты не создал.

EP>>

G>>>Ну ок, возьми не C#, а любой другой статически типизированный язык. В любом языке все придет к формированию деревьев выражений на основе конструкций языка, которые потом надо будет отобразить на метаданные классов и на базе этого построить SQL. Так что накладные расходы также будут присутствовать.

G>Я изначально говорил о динамической композиции запросов.

Где? После приведённых выше цитат?

G>И примеры приводил соответствующие.


Пример был после цитат.

G>Если вы не удосужились пример прочитать и понять его суть, то зачем вообще спорить начали?


Я показал возможный аналог
Автор: Evgeny.Panasyuk
Дата: 14.04.15
этого примера, с комментариями. По комментариям разве не видно что пример я прочитал и понял — если же не согласен, то покажи конкретное место которое я не понял или не прочёл.

G>Вся тема началась с того, что кому-то не понравился EF и было предложение использовать хранимки. Но хранимки часто получаются медленнее, чем склейка запросов, которую прекрасно автоматизирует linq (linq2db, EF, linq2sql).


Мы находимся в под-теме, и EF вообще не обсуждаем.

G>Вообще не было речи о статических примитивных запросах. Это уже ты и _alex_public_ начали выкручиваться, сводя разговор к примитивным случаям.


Согласен с тем что деревья выражений всё-таки можно обходить без накладных расходов в compile-time (даже при динамической композиции, но уже частично; например те самые "16 сгенерированных в compile-time версий запроса" по четырём условиям)?
Re[23]: EntityFramework - тормоз
От: alex_public  
Дата: 16.04.15 01:37
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Если кеш меряется в мегабайтах, то это настолько маленькая база, что нет смысла говорить о быстродействии. Её можно полностью затянуть в память приложения и по ней ходить. Естественно в этом случае скорость выполнения запросов составит микросекунды.


Откуда это тебе знать? ) Ты же до этого момента даже не подозревал о существование таких кэшей. А тут вдруг резко стал экспертом по их работе? )))

G>А ты по ссылкам не читал дальше? Вот например http://www.pythian.com/blog/oracle-11g-result-cache-tested-on-eight-way-itanium/

G>Оказывается кеш в оракле плохо масштабируется, и по умолчанию он выключен. Видимо для очень специфических сценариев применяется. Включенного кеша я ни на одном оракловом сервере не видел.

Я уже не сомневаюсь, что ты придумаешь отмазку на любой аргумент (и на любые другие БД). ))) Однако это всё равно не поможет — картина уже понятна. )))

G>Ты удивишься, но 90%+ критичных к скорости приложений не допускают в базу другие приложения. В оставшихся 10% можно таймстемпы и тригеры прикрутить.


Ну так могут быть например просто несколько процессов одного и того же приложения. Как я понимаю, твоё решение в таком случае будет совсем печальным по быстродействию? )

_>>Проверим на практике? ))) Берём некую БД с кэшированием запросов и пишем к ней 3 варианта одного и того же запроса: через sql строку, через linq, через sqlpp11. И посмотрим насколько процентов будут отличаться результаты...

G>Вперед, пиши. Пример на C# я привел, давай аналогичный на голом SQL и sqlpp11.
G>Еще раз напомню, что ты утверждал, что можно сделать быстрее без потери возможностей linq. Вот и делай пример.

Ты про аналог такого кода?
var query = context.Employees.Select(e => new {e.FirstName, е.LastName, е.EmploymentDate});
if(!string.IsNullOrEmpty(lastName)) query = query.Where(e => e.LastName = lastName);
if(!string.IsNullOrEmpty(firstName)) query = query.Where(e => e.FirstName= firstName);
if(employmentDateFrom.HasValue) query = query.Where(e => e.EmploymentDate >= employmentDateFrom.Value);
if(employmentDateTo.HasValue) query = query.Where(e => e.EmploymentDate <= employmentDateTo.Value);

Да какие там могут быть сложности:
string query="select first_name, last_name, employment_date from Employees where 1";
if(!first_name.empty()) query+=" and first_name=\""+first_name+'"';
if(!last_name.empty()) query+=" and last_name=\""+last_name+'"';
if(employment_date_from) query+=" and employment_date>="+to_string(employment_date_from);
if(employment_date_to) query+=" and employment_date<"+to_string(employment_date_to);

Employees e;
auto query=dynamic_select(db).columns(e.first_name, e.last_name, e.employment_date).from(e).dynamic_where();
if(!first_name.empty()) query.where.add(e.first_name == first_name);
if(!last_name.empty()) query.where.add(e.last_name == last_name);
if(employment_date_from) query.where.add(e.employment_date >= employment_date_from);
if(employment_date_to) query.where.add(e.employment_date < employment_date_to);


Как будем измерять? ) Напомню, что хочется особенно посмотреть на кэшированных запросах (которые меньше миллисекунды "исполняются").


G>Случай примитивных запросов рассматривать неинтересно. В linq их можно прогнать через compiled query и расходы на создание\обход деревьев упадут до нуля.


"Можно" — это конечно хорошо звучит. Так покажи, как такой код будет выглядеть на практике. Вот опять же на базе того твоего примера с if'ми. )))

G>То есть я добавил в проекцию поле и не могу обратиться к нему? Это гениально!


Можешь, но через специальную функцию, а не в виде обычного поля) Т.к. собственно ситуация динамической проекции (в отличие от динамических запросов) является совсем нестандартным случаем.

G>Понятно, значит ничего не умеет, так и запишем.


Ну если ты смог только такое понять, после просмотра тех примеров, то тогда сочувствую. )))

G>То есть типизированных джоинов тоже нет.


И снова у тебя плохо с чтением. Если ты потребуешь не то поле, то получишь ошибку. ) Я тебе об этом писал ещё в предыдущем сообщение.

G>Ладно, продолжать неинтересно. Я уже увидел что от силы 10% возможностей linq покрывается, и то самых простых.


Уже сливаешься? )
Re[2]: EntityFramework - тормоз
От: alex_public  
Дата: 16.04.15 01:44
Оценка:
Здравствуйте, koodeer, Вы писали:

K>Когда в теме сошлись такие дотнетчики, как gandjustas, и плюсисты, как Evgeny.Panasyuk и alex_public, мне стало ясно, как будет идти их общение. Крестоносцы будут говорить, что в плюсах можно сделать всё (и даже больше!), а шарписты требовать: ты покажи именно то, что я написал!


K>Припоминается такой же стиль общения в теме по async.


K>И, как и в прошлый раз, я напишу следующее: имхо, C++ действительно позволяет всё то, что есть в C#/linq. Но дело в том, что linq/EF в мире .NET — это обыденная вещь, которую используют даже начинающие. А в C++ использование метапрограммирования и всех тех вкусностей, что приводили вышеупомянутые товарищи, доступно лишь немногим джедаям, и уж точно не новичку.


Всё верно сказано. Но есть один неучтённый нюанс. В C++ действительно сложно заниматься метапрограммированием. А вот пользоваться результатами метапрограммирования обычно как раз наоборот очень просто и удобно. Т.е. грубо говоря, если по данной тематике существует проработанная готовая библиотека, то не смотря на дикую жуть внутри, пользоваться ею сможет даже новичок. Собственно по async такой библиотеки в то время не было и пришлось писать свою реализацию, а вот по sql, как видно, всё есть и даже не одна.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.