Re[50]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 10.09.21 09:42
Оценка: 3 (1)
Здравствуйте, vdimas, Вы писали:

V>FindChild — тяжелый метод в смысле сложности операций.

V>Несколько арифметических операций приравниваются к одной операции сравнения в плане сложности, а у тебя весь метод — бесконечные сравнения.
Вот не в этом дело.
V>Можно попробовать заменить childIndex_X на inplace массив и сделать линейный поиск в цикле.
Замена не нужна — там же спан торчит.

V>Я когда-то экспериментировал, примерно до 20-30 элементов линейный поиск быстрее бинарного.

V>Скорее всего это связано с предсказателем переходов процессора.
Интересно.
Попробовал на шарплабе — неа, не хочет инлайнить:
https://sharplab.io/#v2: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=

На всякий случай запихал в гитхаб, чтобы прогнать бенчмарки.
  Результат по-прежнему так себе:

V>Заодно тело метода станет маленьким, вероятность инлайна вырастет.
Тут в чём-то другом дело.

V>Прерывания от сетевой карты всё-равно асинхронные, исполняются с т.з. потоков в другом потоке, и в момент обнаружения и забора новых пакетов данных при очередном вызове со стороны юзверя унутре без синхронизации никак. Хотя, синхронизация может быть выполнена на lock-free алгоритмах, но знать бы достоверно...

А у них сорцы не открыты?


V>В общем, при разработке требуется принимать актуальные решения, а не такие, которые потенциально могут сработать лет эдак через 20.

Ну так именно поэтому чудеса АОТ нас только ждут, а динамически порождать эффективный код я умею уже сейчас

V>>>Вручную писаный сериализатор будет оптимизирован и в АОТ,

S>>Каким образом? На основании чего АОТ будет выполнять спекулятивный инлайнинг?
V>Вручную писанные сериализаторы обычно оперируют конкретными типами, в этом случае для AOT раздолье.
Я напомню, что в рассмотренном примере у нас два вручную писанных сериализатора, которые вызываются через IMySerializer _serializer.

V>>>Например, "выпрямлять" в памяти банальный List<T>.

S>>Что значит "выпрямлять"? Он же уже и так прямой.
V>Он дважды косвенный.
Чтобы он стал единожды косвенным, его нужно превратить в структуру. Тот самый escape analysis, который делается в C2 или GraalVM.
Ну, и конечно ситуация должна быть подходящей — нужно ухитриться написать такой метод, где конструируется List<T> и никуда больше не передаётся. Ну, точнее, из транзитивного замыкания этого метода и всех проинлайненных в него методов

V>Тебя интересует нынешнее положение дел или будущее гипотетическое?

Да, будущее гипотетическое.

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

Откуда этот гипотетический спекулятивный оптимизатор получит инфу о том, какой из типов инлайнить?

V>И вот эта проверка — "природный" ограничитель возможности технологии спекулятивной оптимизации.

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

V>Схема рекордсета каждый раз создаётся с 0-ля, это будут другие экземпляры схемы с другими экземплярами абстрактных дескрипторов полей.

Да при чём тут экземпляры-то? Речь о типах. У нас будет заинлайнен код конкретного MySqlDataset.GetInt32(2). В этом коде у нас ветвление типа if(_columns[2].StoreType == Int32), которое, как правило, оказывается верным. Это заставляет джит сделать эту ветку основной, а процессор — предсказывать отсутствие jmp.

S>>А АОТ так и оставит косвенный вызов через VMT.

V>Спекулятивный код с этой задачей тоже не справится.
V>Слишком много вложенных друг в друга абстракций.
Пока не вижу никаких особых сложностей. Сам алгоритм достаточно прямолинейный.

V>Первый VMT — это абстракция от провайдера БД.

V>Прошли.
V>Далее у нас массив абстрактных дескрипторов полей, вторая VMT.
Почему абстрактных-то? Дескрипторы все однотипные. Там работает не спекулятивный инлайнинг, а тупой анализ частоты переходов. Его делает даже процессор без помощи JIT.
V>Полей десяток-другой, допустим.
V>Для каждого поля надо убедиться, что тип дескриптора тот же.
V>А оно точно будет эффективнее предложенной мною схемы вызова ф-ии-маппера по указателю на метод?
V>Я думаю, что проверить можно уже прямо сейчас, т.е. написать гипотетический код, который сгенерировал бы спекулятивный оптимизатор со всеми предпроверками условий и сравнить с предложенной мною схемой.
Да, можно.

V>Мы тут однажды серьезно бодались с коллегой '.' (ник такой), он приводил примеры — они примитивнейшие все.

Да, надо отложить эту дискуссию — времени проверять нету, а без проверок это всё кальянные разговоры.

V>В данном случае — сколько читаемых полей в рекордсете.

V>Пусть даже все поля одного типа, но дескриптор для каждого поля — это уникальный экземпляр наследника абстрактного класса.
Да, верно. В самом внутреннем цикле не должно быть слишком много guard-ов, иначе процессор перестанет предсказывать переходы.

V>А в моей схеме на указателях на мемберы все дескрипторы полей любых типов имеют один и тот же тип (или как миниму не абстрактны).

V>А для полей одинакового типа и вовсе будет один и тот же экземпляр дескриптора.
Применимость этой схемы не зависит от выбора между AOT и JIT.

V>Ну да, просто минус одна косвенность.

V>Если сделать дескрипторы структурами (всё-равно в массивах хранятся) — минус две косвенности.
V>Если сделать часть массива inplace (как в std::string) — будет минус три косвенности.
Да, надо написать и замерить.

V>После качественного AOT стираются типы.

V>Я не представляю, как у нас должна будет работать спекулятивная оптимизация в этом случае.
V>Это надо держать два варианта кода в бинарнике: скомпиллированный через АОТ и исходный IL.
Конечно. IL занимает копейки на фоне бинаря.

V>При желании можно будет вернуться и продолжить или создать тему-продолжение.

V>Обсуждение то было достаточно забавным, на мой взгляд.
V>Хорошо раскрыло уровень рассмотрения происходящего в БД с т.з. ведущих базоводов этого сайта, для меня было откровением, что настолько с высоты птичьего полёта на это смотрят.
Можно и вернуться.

V>Но основное, что обсуждалось — это то, что находится м/у данными и "публичной" функциональностью, т.е. в какой вид компиллируются, собсно, запросы и как исполняются на уровне железа — тут у тебя чёрная дыра.



V>"База вообще" и "база, к которой обращается одно специально разработанное приложение" — две большие разницы.

V>Во втором случае кол-во join-ов может быть до смешного малым, например, в случае кеширования справочных данных приложением.
Это ваша типичная ошибка — вы съезжаете на то, что "вот я же могу взять вот такие таблицы регистров", забывая про то, что СУБД берутся обслуживать более-менее произвольные структуры.
И то, что в теории вы можете хранить одну таблицу на 10 записей и не иметь в ней индексов, не означает, что для любой реальной БД применимы те же алгоритмы, что и в вашем вырожденном случае.

V>И рассуждения как раз шли в направлении того, сколько реальных вариантов запросов (за минусом параметров к ним) породит конкретное приложение.

V>Сколько потенциальных планов породит такой запрос, с учётом отброшенных заведомо неудачных не в рантайме, а еще на этапе компиляции.
Да.

V>Сколько запросов будут иметь общие части, например, в одном запросе where Field1=A, а в другом where Field1=A AND Field2=B.

V>Например, в обоих случаях может получиться так, что лучшим вариантом будет сканить по Field1, бо по этому полю стоит более выгодный индекс (больше уникальных значений в индексе и распределение строк по индексу более равномерное). Это пример той самой "склейки" генерируемой функциональности, где план второго запроса целиком включает план первого — вот что имелось ввиду под "экономией", т.е. имелось ввиду повторное использование.
Это, конечно же, понятно. Но вы не понимаете простой штуки — план работает не так, что мы сначала "сканим по Field1", а потом "фильтруем по Field2".
Эти инструкции перемешаны во внутреннем цикле сканирования. Поэтому бинарь для этих двух запросов будет совершенно разный.

V>Для произвольного анализа данных существует OLAP — используйте инструменты по назначению, как грится.

Нет, это называется "я не сумел написать эффективную СУБД, поэтому пожалуйста возьмите другой инструмент".

V>Происходящее сейчас в индустрии очевидно — инструмент слишком общего назначения используют для слишком узких сценариев.



V>В складе-бухгалтерии получается прилично.

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

S>>Ну, так это известный трюк, связанный не столько с хотспотом, сколько с отсутствием value-типов. А иногда — и с тем, что мы хотим получить автовекторизацию, которая не работает в случае int a; int b; int c.

V>В плюсах работает, значит и в джите потенциально может работать.
Неа, не работает.
V>И для векторизации надо хранить в одном массиве подряд, а не в 3-х.
Наоборот. Стандартный ответ на вопрос "как мне векторизовать операции над комплексными числами" — "храните отдельно double[] Re, double[] Im".

V>Разве что запускаются неприёмлимо долго.

V>И тормозят первые секунды.
Я не знаю, что там такое делает жава, что её VM стартует дольше, чем дотнетная программа (без АОТ) завершается.

V>А мне в сообществе дотнета не нравился все годы пропагандируемый отказ от борьбы за перформанс как таковой.

Там не было никакого пропагандируемого отказа. Было вечное перекладывание ответственности, типа "это пусть делает джит" — "нет, пусть это улучшает компилятор".

V>В джаве, не смотря на то, что в ней аналогичный перформанс достигается несравнимо большей трудоёмкостью, такого странного менталитета нет, народ к этим вещам относится спокойней.

В джаве сосуществует множество "школ" и направлений. Кто-то пилит приложения под JVM на котлине; кто-то пилит hi-performance c пулами байтовых буферов и реинтерпретацией; кто-то пилит кровавый энтерпрайз с менталитетом "у нас business flow, мы берём метод обработки одного шага, стартуем джава-машину, выполняем его, сохраняем результат в базу и глушим машину".

V>Плохо, что так много времени было упущено, конечно...

Ну, я себя чувствую как футбольный болельщик. Типа я посмотрел матч. Что за полтора часа произошло с точки зрения игрока? "Я делал то-то и то-то; это кульминация моих изнурительных тренировок. Что-то я сделал хорошо, а где-то допустил ошибки. Что-то у меня получилось, что-то не получилось". Игрок внёс вклад как в позицию команды в турнирном рейтинге, так и в развитие команды в целом и себя как профессионала.
Что произошло с точки зрения тренера? Какие-то тактические наработки и схемы тренировок сработали, какие-то нет. Тренер получил информацию о наработках другой команды, внёс вклад как в позицию команды в турнирном рейтинге, так и в развитие команды в целом и себя как профессионала.
Что произошло с точки зрения болельщика? Выпит ящик пива, сорван голос, болят колени и ладони. Всё. Даже если это прямо тру фанат, который усовершенствовал свои знания достоинств и недостатков отдельных команд — это никак не поможет ни развитию команды, ни футбола как игры.

Так и мы — в основном пьём пиво, и спорим о том, кто как сыграл вчера и как сыграет завтра. Мы инвестируем свои усилия в пивные животы и сорванные глотки.
По крайней мере, пока мы не контрибутим в public domain.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.