Re[16]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 07.09.20 14:20
Оценка: :)
Здравствуйте, netch80, Вы писали:

N>Мне вот стало тут интересно

N>1) Какая принципиальная разница между загрузкой константы из литерала команды и из сегмента данных, кроме лишнего косвенного доступа по регистру и возможной задержки на чтении памяти?
N>Или тебе они настолько принципиальны?

Не готов спорить насчёт "принципиальности", но в реальных приложениях разница есть, когда используют регистры xmm даже не для векторных вычислений:

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



V>> Именно поэтому векторные операции и заруливают обычную арифметику с плавающей точкой, что за один раз можно указать адреса нескольких операндов (вектора их), бгг...

N>Это действительно основная причина? )

Да.
Поэтому и разница получается не "принципиальная", что-то около 15%.
(если аналогично потом выгружать в память из файла регистров результаты, как если бы происходили вычисления традиционным способом)

Плюс лишние операции со стековой машинкой вычислений с плавающей точкой — в отличие от нее mmx-регистры можно адресовать непосредственно.
ИМХО, тут больше рулит сам факт расширения файла регистров.

Ну и, совсем неординарная фишка — если используются инструкции вокруг mmx, то они замедляют традиционные вычисления.
Связано это с тем, что логически первые 8 64-битных mmx-регистров объединены со стековыми регистрами традиционной арифметики с плавающей точкой (вернее, с мантиссойй этих 80-тиразрядных регистров). Т.е., после работы с mmx-регистрами содержимое стека ST/BCD необходио рассматривать как невалидное, т.е., грубо, некоторые операции по подгрузке данных порой необхоимо "начинать сначала", как-то так.


V>>Фишка в том, что и обычная и векторная арифметика используют одни и те же аппаратные блоки ядер, т.е. унутре проца всё происходит с одинаковой скоростью, т.е. выигрыш сугубо "архитектурный" получается, а не волшебный-аппаратный. Поэтому, если векторные регистры используются не для векторных операций (а там есть и не векторные, ими можно как обычным файлом регистров распоряжаться), то быстродействие получается такое же. А чуть лучше оно получается в не-векторных операциях от того, что векторные регистры рассматриваются как дополнительный файл регистров, т.е. трафик общения проца и кеша 0-го уровня может быть заметно ужат.

N>Только гиморно это — как адрес не применить, сложение-вычитание целых не сделать, и вообще...

Целочисленные логические и арифметические операции над MMX-регистрами и векторами в памяти есть:
https://docs.oracle.com/cd/E18752_01/html/817-5477/eojdc.html#:~:text=The%20MMX%20instructions%20enable%20x86,or%20in%20general%2Dpurpose%20registers.

И там же есть операции загрузки-сохранения, именно поэтому С++ активно использует mmx-регистры даже при компиляции std::copy/std::move.
Т.е., однократное указание адреса для "большого" участка памяти за один раз — оно даёт профит.
(опять же ХЗ, насколько "принципиальный" и где вообще эта "принципиальность" начинается)


V>>Ты ведь курсе, например, что в природе нет активных поддерживаемых x86-х сборок Линукс?

V>>Они все давно переползли на x86_x64,
N>У тебя какая-то инопланетная природа.
N>Debian, например, продолжает вести 32-битные образы.

У нас дохрена Linux-юзверов, из DEB-мира у них только разные версии Убунты, смотрим:
https://releases.ubuntu.com/20.04.1/

Берём прошлый релиз:
http://old-releases.ubuntu.com/releases/18.04.1/

Последний релиз для x86 выходил в 2015-м году, т.е. 5 лет назад, в версии 16.04.

Для RHEL/CentOS это случилось еще раньше:

Since version 7, CentOS officially supports only the x86-64 architecture

это 2014-й.



N>Если постараться, ещё десяток можно поискать.


Если постараться, можно найти сотни Linux-сборок. ))
Но я говорил, как оно сейчас в мейнстриме.

Сейчас даже x86-х планшетов больше не выпускают, последние они были выпущены еще аж под Windows 8.1 (т.е. в 2016-м), сейчас планшеты идут с 64-битной версией Windows 10.
Узнать разницу просто — на планшеты до 4 гиг оперативы ставили преимущественно 32-разрядные винды, с 4 гигов ставят 64-разрядную.


N>[skip остальное, тут надо плотно сесть на вашу траву, чтобы понять смысл дискуссии]


Собсно, о чём и речь.
Синклер когда-то спровоцировал своим слогом посмотреть внимательней его эксперименты — не впечатлило:
— простейший мой хелпер показал аналогичные результаты в плане быстродействия;
— решение Синклера падало с исключением на большом классе алгоритмов.

В общем, реклама не соответствовала товару, поэтому сейчас и подавно смотреть облом, бо слог тот же, смотрю. ))
Несерьёзный какой-то подход...
Отредактировано 07.09.2020 14:23 vdimas . Предыдущая версия .
Re[6]: вопрос hi_octane про c#
От: vdimas Россия  
Дата: 07.09.20 15:03
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

T>>>ValueTask (асинхронный код без аллокаций)

V>>Не совсем без аллокаций, просто позволяет переиспользовать task-like объекты.
НС>В каком месте ValueTask обязательно порождает аллокации? И при чем тут переиспользование, если речь про замены классов на структуры? Моя твоя не понимай.

ValueTask — это пара { task : IValueTaskSource, token: Uint16 }, т.е. некий объект плюс индекс.
Объект, реализующий IValueTaskSource, должен быть создан в любом случае где-то в куче.

Токен полезен для повторного использования объекта, например, из некоторого пула их. Или если IValueTaskSource является объектом-контейнером неких внутренних value-type реализаций task-like объектов.

ИМХО, ValueTask — это то, чем оно должно было быть с самого начала, бо Task — слишком "жирный" объект, т.к. разрабатывался как всемогуттер, от этого перегружен функциональностью и в своей реализации из-за этого перегружен проверками.

Например, в своих проектах мы используем свои легковесные task-like объекты (более одного вида), под них была разработана необходимая обвязка для поддержки компилятором async/await, а ValueTask позволил на такой обвязке резко сэкономить, бо теперь достаточно реализовать интерфейс IValueTaskSource и вуаля.
Re[18]: вопрос hi_octane про c#
От: alex_public  
Дата: 09.09.20 01:29
Оценка: -2 :)
Здравствуйте, Sinclair, Вы писали:

S>>>
S>>>public IQueryable<OrderLine> GetOrderLines(DataConnection conn, int productID, DateTime? orderDateMin)
S>>>{
S>>>  var q = from line in conn.GetTable<OrderLine> where line.ProductID == productID select line;
S>>>  if(orderDateMin.HasValue)
S>>>    q = from line in q where line.Order.OrderDate>=orderDateMin.Value select line;
S>>>}
S>>>

_>>Так это же вроде прямо в точности тот базовый пример, который показывал я в предыдущих сообщениях. Или я что-то не вижу в этом коде? Какой sql должен сгенерироваться?
S>Примерно такой:
S>
S>select line.* from orderLines line 
S>  where line.productID = @productID 
S>

S>Или такой:
S>
S>select line.* from orderLines line 
S>  inner join orders o on line.orderId = o.id
S>  where line.productID = @productID and o.orderDate >= @orderDateMin 
S>

S>- в зависимости от того, что передано в качестве orderDateMin.


Оу, оу, вот именно про такое неудобство я и говорил. Вот как я мог из этого кода узнать о существование таблицы orders? Т.е. я даже не вижу упоминаний её в коде, а Linq при этом суёт мне аж join с ней. То ли дело явное задание всех join'ов.

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

S>>>Всё верно. Доли миллисекунды.

_>>Для link2db. Для EF будут уже не доли. И это всё для простых запросов.
S>Ага, я вижу пробуждение понимания того, что затраты зависят не от технологии, а от конкретной реализации. Так-то я могу и на C++ наколбасить код, который будет тратить сотни миллисекунд на подготовку SQL.

Так я изначально говорил, что сама идея мне нравится, а вот реализация хромает. Только хромает она не в реализации EF (хотя и там наверняка много ужасов, судя по цифрам), а в реализации самого Linq.

_>>Да, и главное то не абсолютные цифры, а относительные. В том тесте это было соответственно +60 и +500 процентов.

S>Совершенно верно
S>Но такие тесты опасно проводить в вакууме — можно сделать совершенно неверные выводы. К примеру, можно запустить такой запрос на пустой базе, и вернуть 0 записей за +60% от чистого SQL.

Не, в тех тестах точно не 0 записей было, потому что там ещё и замер мапинга важную роль играл.

S>А можно запустить "лобовой" вариант запроса на продакшн-базе, и получить на "чистом" SQL +500% к времени исполнения по сравнению с "медленным" linq:

S>
S>select line.* from orderLines line 
S>  inner join orders o on line.orderId = o.id
S>  where line.productID = @productID and (o.orderDate >= @orderDateMin or  @orderDateMin is null)  
S>


Нуу это уже опять очевидное передёргивание. Если ты поставил в своём коде с Linq явный ручной if, то почему ты отказываешь в существование в точности такому же if'у в коде с голым sql?

_>>Подожди, тут же не о том речь. Я сам не в восторге от sql по целому ряду причин. Но при этом если уж у нас выбран такой способ диалога с СУБД, то надо именно его придерживаться. Всё равно же в итоге генерируется sql и лучше если программист будет понимать какой.

S>Это какое-то странное рассуждение. Да, лучше, если программист будет понимать, какой код будет генерироваться. Но это совершенно не означает, что он обязан весь его выписывать руками.
S>Если мы отвлечёмся от SQL, то "способом диалога" с процессором у нас является бинарный код. Конечно же, будет лучше, если программист понимает, какой именно код там генерируется. Но надо ли придерживаться именно такого "способа диалога" при написании прикладных программ? Или можно всё же пользоваться языком высокого уровня, а раскладку данных по регистрам и выбор конкретных команд доверять компилятору?

Только вот нюанс в том, что SQL — это как раз язык высокого уровня, созданный не то чтобы не для машин, а вообще даже не для программистов (а для бухгалтеров). Если бы в СУБД отправлялся бы какой-нибудь низкоуровневый байткод, генерируемый встроенным в ПО оптимизатором под конкретную таблицу — тогда бы вопросов не было и лазить в такое имело бы смысл 0.001% профессионалов в этой области. Но это явно не тот случай, к моему сожалению (и не только моему, судя по успеху всяких СУБД поверх hadoop и т.п.).

S>>>Нет конечно. Семантическая оптимизация — устранение, к примеру, left outer join, или inner join по верифицированному foreign key, если в результате не используются поля присоединяемой таблицы. Такие штуки делают далеко не все СУБД, несмотря на то, что для них не нужна статистика. Большинство движков СУБД рассчитывают на то, что автор запроса не пишет фигни; они лучше всего работают тогда, когда им даётся предварительно урезанный до минимума запрос — тогда у оптимизатора хватает сил и времени на выбор оптимальной стратегии исполнения.

_>>И что это за не все СУБД?
S>Да практически в любую ткни. Приведённый пример прикрутили в MS SQL Server, емнип, году в 2012, если не позже. MySQL этого делать даже не пытается, насчёт Оракла и Постгре я сомневаюсь.

Ну т.е. по факту ты не в курсе просто. Но что-то там утверждаешь... Я вот кстати тоже не в курсе (т.к. это не моя тема вообще говоря), но обычно в таком случае или не болтаю или же в начале хоть знакомлюсь с темой. За 5 секунд в гугле нашлось это https://oracle-base.com/articles/misc/join-elimination. Дальше лазить по другим СУБД уже не стал... )

Да, а ты в курсе надеюсь, что такая оптимизация вообще говоря может ухудшить быстродействие в некоторых случаях? Поэтому тот же Oracle позволяет её отключать для конкретного запроса. А linq2db что, всегда её делает что ли? )))

_>>Пруф на то, что C++ код будет быстрее C# кода?

S>Да, конечно.

https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/csharpcore-gpp.html — так пойдёт? )))
Re[20]: вопрос hi_octane про c#
От: alex_public  
Дата: 09.09.20 02:01
Оценка:
Здравствуйте, Sinclair, Вы писали:

_>>Не, любые математические выражения записываются намного проще.

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

Так ты определить, какой алгоритм у тебя там используется. С предварительным интегрированием или без. Это два принципиально разных подхода к вычислению локального среднего.

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

S>Я не очень хорошо знаком с numpy, но либо они используют порождение кода на лету (т.е. аналог linq), либо получают существенное замедление.


Нет там никакой генерации. Т.е. в вычислениях на Питоне она местами используется (см. Numba — работает через llvm, причём в виде банального декоратора @njit у нужной функции), но для особо сложных случаев. А numpy — это такой простенький инструмент для большинства обычных матричных задач.

S>Можете напилить бенчмарк с предложенной вами реализацией?


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

_>>Для случая окна размером 3 пикселя (как раз твой код), собственно свёртку на numpy вообще по другому проще (и эффективнее) будет записать. А именно, сделать 4 сдвига нашей матрицы (причём можно без выделения памяти, как срез) и потом их просто сложить.

S>Давайте от абстрактных рассуждений перейдём к коду. Как будет выглядеть сложение этих сдвигов?

Так просто A=A1+A2+A3+A4

_>>Правильно ли я понимаю, что с твоей точки зрения IEnumerable и IQueryable — это не часть Linq, а всего лишь какие-то там интерфейсы из неких прикладных библиотек?

S>Конечно. Их можно убрать, и в языке ничего не изменится.
S>Также, как numpy не является частью языка Python.

А, ну в таком случае в принципе можно считать, что Linq есть в любом языке, позволяющем строить в коде и анализировать деревья выражений, правильно?
Re[19]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.09.20 02:14
Оценка: +3 :)
Здравствуйте, alex_public, Вы писали:
_>Оу, оу, вот именно про такое неудобство я и говорил. Вот как я мог из этого кода узнать о существование таблицы orders? Т.е. я даже не вижу упоминаний её в коде, а Linq при этом суёт мне аж join с ней. То ли дело явное задание всех join'ов.
Точно так же, как и всегда — смотрим определение Order, видим, к чему он привязан.

_>Ну и да, после отработки метакода в таком случае будет просто двойнной if (хотя от оптимизатора зависит — он может и одинарным сделать).

Непонятно, как это будет сделано.

_>Так я изначально говорил, что сама идея мне нравится, а вот реализация хромает. Только хромает она не в реализации EF (хотя и там наверняка много ужасов, судя по цифрам), а в реализации самого Linq.



S>>
S>>select line.* from orderLines line 
S>>  inner join orders o on line.orderId = o.id
S>>  where line.productID = @productID and (o.orderDate >= @orderDateMin or  @orderDateMin is null)  
S>>


_>Нуу это уже опять очевидное передёргивание. Если ты поставил в своём коде с Linq явный ручной if, то почему ты отказываешь в существование в точности такому же if'у в коде с голым sql?

Мы, конечно же, уже ездили по этому кругу. Но почему бы и нет?
Отказываю я потому, что "точно такой" же if приводит либо к дублированию, либо к нечитаемому коду. Вы попробуйте, собственно, выписать код — сами всё поймёте.
А потом мы добавим ещё один опциональный параметр, и код на if-ах вообще превратится в лапшу, которую умрёшь маинтейнить. Как вы думаете, почему в реальных проектах все пишут (o.orderDate >= @orderDateMin or @orderDateMin is null), а не код на if-ах?

_>Только вот нюанс в том, что SQL — это как раз язык высокого уровня, созданный не то чтобы не для машин, а вообще даже не для программистов (а для бухгалтеров). Если бы в СУБД отправлялся бы какой-нибудь низкоуровневый байткод, генерируемый встроенным в ПО оптимизатором под конкретную таблицу — тогда бы вопросов не было и лазить в такое имело бы смысл 0.001% профессионалов в этой области. Но это явно не тот случай, к моему сожалению (и не только моему, судя по успеху всяких СУБД поверх hadoop и т.п.).

Неважно, для кого он создавался. С тех пор прошло 40 лет, два поколения бухгалтеров сменилось с тех пор, а SQL они так и не усвоили. В итоге SQL остался полу-языком: он слишком низкого уровня для написания настоящих программ.
Но это, собственно говоря, неважно. Язык C++ начинался как CFront, который компилировался в C; Typescript и сейчас компилируется в JS. Это не мешает обоим быть достойными языками для своих целей. Не обязательно порождать "нечитаемый байткод" — достаточно давать преимущества в написании кода.


_>Да, а ты в курсе надеюсь, что такая оптимизация вообще говоря может ухудшить быстродействие в некоторых случаях?

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

А вот про поддержку: https://blog.jooq.org/2017/09/01/join-elimination-an-essential-optimiser-feature-for-advanced-sql-usage/
Видим, что три года назад такая оптимизация работала только во взрослых СУБД. А то, на чём ездит весь опен-сорс и значительная часть коммерции — это MySQL и Postgre — не дотягивают до планки.
Что будет лучше, при наличии выбора — добавить в проект бесплатный linq2db, перейти на Oracle, или руками пилить оптимизацию запросов на if-ах?

_>Поэтому тот же Oracle позволяет её отключать для конкретного запроса. А linq2db что, всегда её делает что ли? )))

Сложно сказать — это пусть лучше Danchik расскажет.

_>>>Пруф на то, что C++ код будет быстрее C# кода?

S>>Да, конечно.
_>https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/csharpcore-gpp.html — так пойдёт? )))
Неа. Не пойдёт. Вы мне С4 или Sauvola покажите на C++.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[21]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.09.20 02:20
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Так ты определить, какой алгоритм у тебя там используется. С предварительным интегрированием или без. Это два принципиально разных подхода к вычислению локального среднего.

Я уже определился. Вот код:
public static byte[,] SauvolaBinarize(byte[,] grayScale, int WHalf, double K)
{
    var integrate = 
            from g in grayScale
            from ri in Result.SubstBy(0)    // сумма элементов - int32
            from rq in Result.SubstBy(0L)    // сумма квадратов - int64. Можно обойтись и int32, если площадь окна просмотра не более 2^16, но так честнее
            select ValueTuple.Create(
                ri[-1, 0] + ri[0, -1] - ri[-1, -1] + g,
                rq[-1, 0] + rq[0, -1] - rq[-1, -1] + g * g);
    var (p, sq) = integrate.ToArrays();    // вычисляем оба интеграла сразу

    var detect = 
            from g in grayScale
            from i in p.With(OutOfBoundsStrategy.Integral(0))    // специальная стратегия подстановки для значений за пределами массива - 0 для слева-сверху,
            from q in sq.With(OutOfBoundsStrategy.Integral(0L)) // ближайший сосед для справа-снизу.
            let tl = i.Offset(-WHalf - 1, -WHalf - 1)        // самая громоздкая часть: вычисляем эффективное окно просмотра, смещая текущую точку на +-Whalf
            let tr = i.Offset(-WHalf - 1, WHalf)        // нам нужны 8 точек, т.к. мы используем оба предынтегрированных массива
            let bl = i.Offset(WHalf, -WHalf - 1)
            let br = i.Offset(WHalf, WHalf)
            let tlq = q.Offset(-WHalf - 1, -WHalf - 1)
            let trq = q.Offset(-WHalf - 1, WHalf)
            let blq = q.Offset(WHalf, -WHalf - 1)
            let brq = q.Offset(WHalf, WHalf)
            let area = (br.X - tl.X) * (br.Y - tl.Y)        // площадь окна разная, в зависимости от того, куда попала точка; все поправки в X и Y учитываются OutOfBoundsStrategy.Integral
            let diff = br.Value + tl.Value - tr.Value - bl.Value
            let sqdiff = brq.Value + tlq.Value - trq.Value - blq.Value
            let mean = (double)diff / area            // вообще, здесь можно и не приводить к double. Но это мешает векторизации, т.к. целочисленный div есть только в AVX-512. 
            let std = Math.Sqrt((sqdiff - diff * mean) / (area - 1)) // А вот double делятся уже в avx2.

            let threshold = mean * (1 + K * ((std / 128) - 1))

            select g > threshold ? byte.MaxValue : byte.MinValue;
}

_>Если у тебя точно такой же алгоритм (с интегрированием), то твой код действительно может быть быстрее, потому что это всё же Питон (пусть и использующий местами C). Если же у тебя алгоритм без интегрирования, то он априори может быть быстрее только для вырожденных случаев размера окна.
S>>Я не очень хорошо знаком с numpy, но либо они используют порождение кода на лету (т.е. аналог linq), либо получают существенное замедление.
_>Нет там никакой генерации. Т.е. в вычислениях на Питоне она местами используется (см. Numba — работает через llvm, причём в виде банального декоратора @njit у нужной функции), но для особо сложных случаев. А numpy — это такой простенький инструмент для большинства обычных матричных задач.
Тогда конкретно на этой задаче numpy сольёт.

_>Так просто A=A1+A2+A3+A4

Нет, так не получится. Я не вижу здесь nearest neighbour.

_>А, ну в таком случае в принципе можно считать, что Linq есть в любом языке, позволяющем строить в коде и анализировать деревья выражений, правильно?

Ну, если он ещё и позволяет генерировать код на лету — да, так и есть.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[16]: вопрос hi_octane про c#
От: alex_public  
Дата: 09.09.20 02:24
Оценка:
Здравствуйте, Sinclair, Вы писали:

_>>Твой код работает как O(n^2), где n — это размер окна.

S>Нет конечно. Он точно так же вычисляет сумму и сумму квадратов через предварительно рассчитанные интегралы.

Так, подожди, если у тебя там идёт расчёт через интегралы, то к чему тогда вообще тут Linq? Т.е. если ты не задаёшь произвольные попикесельные свёртки руками, а используешь просто предвычисленный интеграл и потом манипуляции с массивом целиком (как в том же numpy), то полностью теряется весь смысл от возможности задания произвольных выражений.
Re[17]: вопрос hi_octane про c#
От: Sinclair Россия https://github.com/evilguest/
Дата: 09.09.20 02:28
Оценка:
Здравствуйте, alex_public, Вы писали:
_>Так, подожди, если у тебя там идёт расчёт через интегралы, то к чему тогда вообще тут Linq? Т.е. если ты не задаёшь произвольные попикесельные свёртки руками, а используешь просто предвычисленный интеграл и потом манипуляции с массивом целиком (как в том же numpy), то полностью теряется весь смысл от возможности задания произвольных выражений.
Ничего не понял. Что тут теряется? И интеграл, и пороговое значение, и собственно результат сравнения пикселов с порогом — всё вычислено на Linq.
Может, всё-таки прочитать https://github.com/evilguest/linq2d/blob/master/README.md?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[19]: вопрос hi_octane про c#
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 09.09.20 06:14
Оценка:
Здравствуйте, alex_public, Вы писали:

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


S>>>>
S>>>>public IQueryable<OrderLine> GetOrderLines(DataConnection conn, int productID, DateTime? orderDateMin)
S>>>>{
S>>>>  var q = from line in conn.GetTable<OrderLine> where line.ProductID == productID select line;
S>>>>  if(orderDateMin.HasValue)
S>>>>    q = from line in q where line.Order.OrderDate>=orderDateMin.Value select line;
S>>>>}
S>>>>




_>Оу, оу, вот именно про такое неудобство я и говорил. Вот как я мог из этого кода узнать о существование таблицы orders? Т.е. я даже не вижу упоминаний её в коде, а Linq при этом суёт мне аж join с ней. То ли дело явное задание всех join'ов.


_>Ну и да, после отработки метакода в таком случае будет просто двойнной if (хотя от оптимизатора зависит — он может и одинарным сделать).


Ну вот сразу видно, что ты с ОRM не имел дела. В том же 1С и EF это нормальная практика. Виртуальные свойства называются, только у них можно доступ иметь через 2 и более точки.
https://metanit.com/sharp/entityframework/3.2.php

Мало того таких ифоф может быть огромная куча.
Например как универсальные отчеты типа https://www.linqpad.net/
Когда можно составить любой запрос, с любыми объединениями и группировками и полями
Одним из преимуществ .Net это динамическая компиляция https://infostart.ru/1c/articles/547389/
и солнце б утром не вставало, когда бы не было меня
Отредактировано 09.09.2020 10:45 Serginio1 . Предыдущая версия .
Re[19]: вопрос hi_octane про c#
От: Danchik Украина  
Дата: 09.09.20 08:05
Оценка: +3
Здравствуйте, alex_public, Вы писали:


_>Оу, оу, вот именно про такое неудобство я и говорил. Вот как я мог из этого кода узнать о существование таблицы orders? Т.е. я даже не вижу упоминаний её в коде, а Linq при этом суёт мне аж join с ней. То ли дело явное задание всех join'ов.


Да задавай джоиы, блин. Только смотри не промахнись в условиях. Ассоциации для предотвращения тупых ошибок копипасты и удобства.

_>Ну и да, после отработки метакода в таком случае будет просто двойнной if (хотя от оптимизатора зависит — он может и одинарным сделать).


S>>>>Всё верно. Доли миллисекунды.

_>>>Для link2db. Для EF будут уже не доли. И это всё для простых запросов.
S>>Ага, я вижу пробуждение понимания того, что затраты зависят не от технологии, а от конкретной реализации. Так-то я могу и на C++ наколбасить код, который будет тратить сотни миллисекунд на подготовку SQL.

_>Так я изначально говорил, что сама идея мне нравится, а вот реализация хромает. Только хромает она не в реализации EF (хотя и там наверняка много ужасов, судя по цифрам), а в реализации самого Linq.


По твоим постам только видно как ты нос ворочаешь. Толку Zero. Удачи тебе в полемиках. Вижу Антону еще хватает выдержки.

[Отскипано, коментировать нечего]


_>Да, а ты в курсе надеюсь, что такая оптимизация вообще говоря может ухудшить быстродействие в некоторых случаях? Поэтому тот же Oracle позволяет её отключать для конкретного запроса. А linq2db что, всегда её делает что ли? )))


Тоесть убрать лишний джоин — ухудшить запрс. Мило. Давай пример.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.