Re[38]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 19.04.15 15:38
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Только при её генерации не будет таких диких накладных расходов, как у linq.


Ну сколько можно? Тебе уже несколько человек говорят — не трепись о том, о чем не знаешь. Нет там никаких "диких" расходов.
Re[36]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 19.04.15 15:38
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Например взглянуть на наверняка известный тебе инструмент ReSharper — как ты считаешь, его создателей можно считать специалистами по C# или нет?


В решарпере нет доступа к БД через линк. От слова совсем. IQueryable и IEnumerable это далеко не одно и тоже.
Re[38]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 15:40
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Что значит генерировать запросы лучше, чем linq? ) SQL строка отсылаемая в СУБД будет очевидно точной такой же, как и у linq варианта. Только при её генерации не будет таких диких накладных расходов, как у linq.


Всё же у LINQ уровень выше чем у SQL — он отходит в сторону ORM. Точнее высота уровня зависит от конкретной используемой библиотеки.
И, например, за счёт того что доступна информация о связях — имеется возможность писать более высокоуровневые запросы нежели SQL (а не просто типизированный SQL), которые уже нижележащий слой переведёт в SQL, причём результирующий запрос может содержать DB-specific оптимизации.
Как сам понимаешь, создать аналогичный EDSL, но без runtime жира — не проблема. Были ли какие-то серьёзные попытки — никогда не интересовался
Re[38]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 19.04.15 15:41
Оценка: +2
Здравствуйте, alex_public, Вы писали:

С>>Из каких "других языков"? В каких широко распространенных языках есть цитирование кода?

_>Sequence в Swift'e, std.range в D, boost.range в C++ и т.п.

Re[39]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 15:50
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

_>>Только при её генерации не будет таких диких накладных расходов, как у linq.

НС>Ну сколько можно? Тебе уже несколько человек говорят — не трепись о том, о чем не знаешь. Нет там никаких "диких" расходов.

Несколько миллисекунд (о которых gandjustas) — это и есть "дикие" расходы
Re[36]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.04.15 15:51
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

G>>Теоретические изыскания неинтересны.

EP>Почему же? В начале топика ты отрицал что это вообще возможно, теперь вот знаешь что это не так
Я отрицал что это на практике возможно. И собственно практика подтверждает мои слова.

EP>>>Что мешает построить эффективный запрос без LINQ? Например каким-нибудь другим декларативным способом, или тем же "обезжиренным" LINQ?

G>>Построить — ничего не мешает, а вот поддерживать — ад.
EP>То есть ты утверждаешь что поддерживать код с любым другим декларативным доступом к данным это ад?
Ты бы еще по одному слову цитировал.
Специально для тебя повторяю мысль полностью (ключевое выделено)

Построить — ничего не мешает, а вот поддерживать — ад. Опять-так в теории все можно, а на практике есть linq и близких аналогов нет вообще.


В этой ветке конструктив кончился еще 10 постов назад, у меня нет желания продолжать.
Re[39]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 15:53
Оценка:
Здравствуйте, Слава, Вы писали:

_>> Только при её генерации не будет таких диких накладных расходов, как у linq.

С>Какая восхитительная подмена. Внезапно, микросекунды уже стали "дикими" расходами, при том, что выше по треду убедительно разъяснялись пропорции расходов.

Речь шла о миллисекундах, а не микро-. И да — для современного железа это "дикие" расходы.
Re[36]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 19.04.15 15:54
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Да всё понятно теперь. ))) Просто только приперев тебя к стенке удалось выяснить, что реально тебе нужны совсем не динамические запросы. А как раз классические статические, но конструируемые по частям.


Мне вот интересно — ты действительно не понимаешь или усиленно прикидываешься? Типичный код:
var query = db.MyTable;
if (someCondition)
    query = query.Where(m => m.SomeRef.Foo > 4);
var data = query.Select(m => new {m.X, m.Y});

Ты как, в состоянии понять что при срабатывании условия запрос не просто будет немножечко дописан, он будет другой — в нем появится джойн?
И это самый простейший случай, когда у тебя все в одном методе. В реальности 1 строчка может быть в одном слое и даже отдельной dll, а 2 и 3 — в другом.
Re[30]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 19.04.15 15:54
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>>>Пара миллисекунд практически на ровном месте. Да это же 1/50 секунды современного железа!

НС>>1/500

EP>Точно, ошибся. Спасибо что исправил.

EP>Тем не менее, это всё равно очень много.

Много для чего? На фоне десятков миллисекунд доступа к БД даже на простых запросах — совсем немного.
Re[40]: EntityFramework - тормоз
От: Ночной Смотрящий Россия  
Дата: 19.04.15 15:58
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Несколько миллисекунд (о которых gandjustas) — это и есть "дикие" расходы


Несколько миллисекунд это вообще весь меппинг. Избавившись от линка ты просто вынужден будешь писать меппинг руками. Получив все те же миллисекунды. Ты уж поверь — в процессе разработки linq2db он сравнивался с полностью рукопашным кодом. Разница там — смешные проценты. От тех самых единиц миллисекунд. На фоне запроса в БД это такие крохи, что их не так то просто измерить.
Re[38]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.04.15 15:59
Оценка:
Здравствуйте, alex_public, Вы писали:

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


G>>А с чего ты взял что я путаю? Заказчик (как конечный пользователь, так и корп. заказчик) покупает услугу, хотя маркетологи называют её продуктом. Суть услуги в повышении прибыли (снижении издержек), медленное и глючное приложение издержки повышает. Причем конечного пользователя еще можно развести "красивостями" и "стилем", то для корпоративного заказчика такая хрень не катит. Если ты сделал даже очень красивое говно, то с тобой перестанут сотрудничать.

G>>И если для дескопного софта есть 2-3 альтернативы, которые конкурируют между собой, то в корпоративном секторе сотни компаний готовы оказывать услуги.

_>Ты путаешься в терминологии. Внутрикорпоративный софт — это не тот, который просто используется внутри корпораций, а тот, который пишется в них (т.е. пишется в IT отделе не IT компании, а не покупается у специализированной IT компании). Т.е. тот же MSSQL очевидно не является внутрикорпоративным софтом. А вот формочка для ввода данных сотрудниками в банке именно им и является.

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

G>>Ты все еще веришь в то, что сможешь генерировать запросы лучше, чем умеет linq? Ты похоже никогда этим не занимался.


_>Что значит генерировать запросы лучше, чем linq? ) SQL строка отсылаемая в СУБД будет очевидно точной такой же, как и у linq варианта. Только при её генерации не будет таких диких накладных расходов, как у linq. Плюс если в приложение будет реализован нормальный слой абстракции БД, то мы можем получить ещё и более удобный и безопасный внутренний API.

Еще раз для тебя повторю проблему: надо под каждый сценарий генерировать свою строку. В серьезной программе таких строк — тысячи. Просто выписать их невозможно, генерировать с помощью склейки — проблемно. При ручной склейке строк возникают проблемы безопасности (ты и сам пример привел), часто получаются неочень корректные и неочень оптимальные запросы.

Нужен тул, который автоматизириует. А еще надо поддерживать (то есть править строки при правке логики и схемы данных), что с Linq делать очень удобно, а без него — ад.

Я тебе это уже раз десять повторил. Ты все еще не понял проблемы? Зачем тогда продолжаешь писать?
Re[37]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 16:03
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>>>Теоретические изыскания неинтересны.

EP>>Почему же? В начале топика ты отрицал что это вообще возможно, теперь вот знаешь что это не так
G>Я отрицал что это на практике возможно. И собственно практика подтверждает мои слова.

Ещё раз, вот твои слова где-то в начале ветки:

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

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

То есть тут ты говорил про практику, а не теорию, да? Это вот это вот "какой бы DSL ты не создал" — практика?
Re[36]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.04.15 16:20
Оценка:
Здравствуйте, alex_public, Вы писали:

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


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

_>Угу, есть. И не точечные. Правда не какого-то большого приложения, а специально написанного мелкого тестового.
Показывай.

_>Да, и кстати чем больше база, тем собственно больше будет бонус от подключения кэша (он то по любому в оперативной памяти сидит и при этом занимает не особо много места).

Это полнейший бред. Чем больше база, тем больше памяти нужно для каждого запроса. При чтении с дика данные поднимаются в память (buffer pool), а уже оттуда отдаются на клиент. Если у тебя есть кеш, то он отнимает память у buffer pool и базе приходится чаще читать с диска.

Ты ни разу не тестировал на базе, которая не влезает в ОП если так говоришь.

_>>>Угу, возрастала в разы относительно случая без кэша. А если бы применил вместо этого кэш в БД, то выросло бы не в разы, а в десятки раз.

G>>Откуда такая уверенность? Ты понимаешь как БД работает вообще? Я вот понимаю и не вижу откуда возьмутся десятки раз. Ты очень далек от бд и архитектуры, на основании чего утверждаешь?

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


Логика на грани фантастики. Небольшой ликбез — реальное быстродействие запроса зависит от количества чтений с диска. Чтение происходит страницами, есть более-менее универсальный показатель physical read. Чем больше физических чтений, тем медленнее работает.
Если база маленькая (влезает в ОП с запасом), то physical read = 0 всегда и быстродействие начинает зависеть от многих факторов, но несильно. Чем меньше у тебя памяти под buffer pool, тем больше physical read, тем медленнее все работа. Кеш в базе отбирает память у buffer pool, причем чем чаще попадания в кеш, тем меньше памяти у buffer pool и тем медленнее все работает. Естественно это можно увидеть только на базах, больших чем ОП сервера, есть подозрение, что ты таких не видел.


_>>>Я не очень понял как коррелируют твои слова о пользе проекции (причём динамической) с твоим же словами о том, что лучше, когда датасет не меняется.

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

_>Да всё понятно теперь. ))) Просто только приперев тебя к стенке удалось выяснить, что реально тебе нужны совсем не динамические запросы. А как раз классические статические, но конструируемые по частям.

Это и есть динамические запросы. Так как в точки зрения конструктора нет ни одной фиксированной части запроса, на которую можно ориентироваться. Я это уже объяснял — что можно взять запрос, навесить на него свой предикат\проекцию\группировку, и передать в другую функцию в другой сборке. Ты не понял? Я тебе уже по 10 раз одно и тоже разными словами пытаюсь объяснить, а ты до сих пор делаешь вид что не понимаешь. Или ты реально не понимаешь? Тогда зачем пишешь?
Re[38]: EntityFramework - тормоз
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 19.04.15 16:22
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

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


G>>>>Теоретические изыскания неинтересны.

EP>>>Почему же? В начале топика ты отрицал что это вообще возможно, теперь вот знаешь что это не так
G>>Я отрицал что это на практике возможно. И собственно практика подтверждает мои слова.

EP>Ещё раз, вот твои слова где-то в начале ветки:

EP>

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

EP>

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

EP>То есть тут ты говорил про практику, а не теорию, да? Это вот это вот "какой бы DSL ты не создал" — практика?
Да, это означает, что ты на практике не сможешь родить такой DSL. Не в теории, а на практике.
Re[37]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 16:41
Оценка: +1
Здравствуйте, Ночной Смотрящий, Вы писали:

_>>Да всё понятно теперь. ))) Просто только приперев тебя к стенке удалось выяснить, что реально тебе нужны совсем не динамические запросы. А как раз классические статические, но конструируемые по частям.

НС>Мне вот интересно — ты действительно не понимаешь или усиленно прикидываешься? Типичный код:
НС>
НС>var query = db.MyTable;
НС>if (someCondition)
НС>    query = query.Where(m => m.SomeRef.Foo > 4);
НС>var data = query.Select(m => new {m.X, m.Y});
НС>

НС>Ты как, в состоянии понять что при срабатывании условия запрос не просто будет немножечко дописан, он будет другой — в нем появится джойн?
НС>И это самый простейший случай, когда у тебя все в одном методе. В реальности 1 строчка может быть в одном слое и даже отдельной dll, а 2 и 3 — в другом.

Здесь в ветке смешались в кучу несколько разных понятий, и по сути у вас нет общего языка для общения. Попытаюсь резюмировать дабы увеличить уровень взаимопонимания:

1) Запросы статические по сути, но сконструированные из нескольких частей, возможно даже в разных функциях.
2) Статические запросы построенные через динамическую композицию — статические части запроса комбинируются разными способами в зависимости от runtime условий (то есть расширение пункта 1).
3) Динамические запросы — имена полей, таблиц, выражения условий и т.п. не известны на этапе компиляции.
4) Стирание полного типа запроса — это позволяет частично отличающимся запросам иметь одинаковый тип. Степень отличия контролируется тем, насколько стёрт тип.
5) Конструирование частей запросов в разных динамических библиотеках. Вообще говоря это ортогонально пунктам 1-4 и работает для каждого из них.

Из всего этого только 3) и 4) мешают полностью сгенерировать текст запроса во время компиляции.
Вариант 3) нужен очень редко, и убивает возможность части статических проверок — что в LINQ'е, что в любом другом EDSL.
Насколько я вижу, вариант 4) тоже далеко не всегда необходим. Причём каких-то принципиальных предпосылок/аргументов к его необходимости в этом топике я не увидел.

При этом в этой ветке упор в основном делался на 1) и на 2) — вполне резонно, но это прекрасно резульзуется и в compile-time EDSL.
Помимо этого, мимоходом зачем-то кидаются запросы по 5) (попытка хоть как-то выкрутится?), хотя видимо подразумевалось 4)
Отредактировано 19.04.2015 17:10 Evgeny.Panasyuk . Предыдущая версия . Еще …
Отредактировано 19.04.2015 16:54 Evgeny.Panasyuk . Предыдущая версия .
Отредактировано 19.04.2015 16:52 Evgeny.Panasyuk . Предыдущая версия .
Отредактировано 19.04.2015 16:49 Evgeny.Panasyuk . Предыдущая версия .
Re[39]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 17:13
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Да, это означает, что ты на практике не сможешь родить такой DSL. Не в теории, а на практике.


Поясни что ты конкретно имеешь в виду.
Re[31]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 17:22
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>>>Пара миллисекунд практически на ровном месте. Да это же 1/50 секунды современного железа!

НС>>>1/500
EP>>Точно, ошибся. Спасибо что исправил.
EP>>Тем не менее, это всё равно очень много.
НС>Много для чего?

Много для операции результат которой выводится во время компиляции. Причём это же не просто задержки, которые иногда можно за-pipeline'ить — это же реальная загрузка CPU.

НС>На фоне десятков миллисекунд доступа к БД даже на простых запросах — совсем немного.


А если запрос в БД закэширован, или хотя бы нужные страницы уже в памяти? Неужели даже в этих случаях современные БД дают десятки миллисекунд?
Re[35]: EntityFramework - тормоз
От: alex_public  
Дата: 19.04.15 17:29
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

_>>Ну так значит "внезапно" реляционная модель оказывается не единственной полезной? )

НС>Извивы твоей логики от меня ускользают.

Всё ты прекрасно понял. ) Просто не стоило кидаться фразами что "реляционная модель — это единственный способ получит производительное приложение". Сам же понимаешь, что будет в случае попытки использования этой модели для каких-нибудь там графов. )

_>> И при необходимости эти ограничения легко (во всяком случае в языках со статической типизацией) вводятся в код.

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

Речь не про рантайм проверки данных, а про статические ограничения для программиста, мешающие ему делать ошибки.

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

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

Покажи пример реализации. ) Ну вот предположим int поле из БД должно отoбражаться во что-то типа class MyInt{int val; public: operator=(...); operator+(...);...}.

_>>Если ты считаешь вышеприведённый пример не введением дополнительного слоя абстракции

НС>А с чего бы мне считать обычную функцию аж слоем абстракции? Слой это когда ты полностью все закрываешь. А когда у тебя чтение пользователей все равно через IQueryable идет — никакой это не слой.

Про чтение мы ещё не говорили, пока речь была просто про создание. И там функция имела вид dbAddUser(string), а внутри могла иметь как несколько sql запросов, так и один nosql (в таких базах благодаря иерархической структуре обычно достаточно одного). На мой взгляд вполне себе нормальная абстракция.

Ну и если говорить о чтение, то откуда там обязательно IQueryable? ) Скорее User dbGetUser(int id); и vector<User> dbGetUsers(); или что-то подобное. )

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


Ну так в общем случае конечно же не получится написать что-то оптимальное. Однако если мы говорим о конкретном приложение с конкретной БД (не СУБД, а именно таблицами и т.п.), то какие могут быть проблемы в написание оптимального слоя абстракции?
Re[39]: EntityFramework - тормоз
От: alex_public  
Дата: 19.04.15 17:34
Оценка: +1
Здравствуйте, Слава, Вы писали:

_>> Только при её генерации не будет таких диких накладных расходов, как у linq.

С>Какая восхитительная подмена. Внезапно, микросекунды уже стали "дикими" расходами, при том, что выше по треду убедительно разъяснялись пропорции расходов.

Микросекунды действительно не являются дикими расходами. Только вот для linq озвучивались (причём не мною!) цифры в миллисекунды, а это уже действительно серьёзно, т.к. приближается ко времени маленького запроса. А уж в случае использования кэширования (при котором запрос может "исполняться" меньше миллисекунды) это вообще мрак и ужас.
Re[41]: EntityFramework - тормоз
От: Evgeny.Panasyuk Россия  
Дата: 19.04.15 17:35
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

EP>>Несколько миллисекунд (о которых gandjustas) — это и есть "дикие" расходы

НС>Несколько миллисекунд это вообще весь меппинг.

Возможно, но вот что было выше по ветке:

http://rsdn.ru/forum/flame.comp/6013262.1


G>Вот только план в SQL делается один раз и живет долго, а по Expression Tree каждый раз надо бегать.
G>На нетривиальных запросах это несколько миллисекунд. При тыще запросов в секунду только формирование SQL из ET скушает пару ядер процессора.


НС>Избавившись от линка ты просто вынужден будешь писать меппинг руками. Получив все те же миллисекунды.


Что конкретно входит в mapping? Используется ли там что-то типа reflection?

НС>Ты уж поверь — в процессе разработки linq2db он сравнивался с полностью рукопашным кодом.


С каким конкретно рукопашным кодом? Гвоздями прибитым к конкретным структурам, или всё же с некоторой автоматизацией?
Спрашиваю потому что в C# практически каждая автоматизация имеет abstraction penatly — хочу понять какая разница по сравнению с zero-overhead кодом.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.