Здравствуйте, Serginio1, Вы писали:
S>Ну мы же можем скопировать тело конструктора предка в конструктор потомка.
Для начала — насколько я понял, SG не могут модифицировать код.
То есть мы уже выбежали за пределы source generator.
Далее, если мы попробуем делать какие-то ещё приседания на воображаемом будущем АПИ расширения компилятора: в предке нет никакого тела конструктора. Точно ли мы хотим дописать в конструктор потомка _a = default(), подразумевая семантику Child(int b) : base()?
Что делать, если в предке определён параметризованный конструктор?
В общем, нетривиально.
Возникает вопрос: а что за сценарий у нас такой, где нужны именно структуры, и именно наследование?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Ночной Смотрящий, Вы писали:
I>>Откуда ты взял эти "несколько десятков строк" ? НС>Ты опять не читаешь собеседника. Я писал откуда.
Я вижу только нечто туманное вида "данные передадут таблице"
Как правило, в таблицы пихают до тех пор, пока они справляются, а уже потом начинают приседать с виртуализацией.
Вобщем, не вижу указания, какой именно грид ты загадал
I>>Сеть, худший случай — рисуем все, когда юзер фильтрам-зумами-слоями включил всё. НС>И сеть биндится через штатный биндинг, да?
"штатный байндинг" Сколько недель ты будешь вопрошать про тупенькие контролы?
>>>У тебя при отрисовке в САПР модели в 1Гб был боксинг? Нафига? I>>Конечно же нет. На него издержки конские, потому я его истреблял всеми доступными мне методами.
НС>Т.е. изначально он там был?
Разумеется. Иначе как же я от него код вычищал, если его изначально не было?
Re[64]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Serginio1, Вы писали:
S>>Ну мы же можем скопировать тело конструктора предка в конструктор потомка. S>Для начала — насколько я понял, SG не могут модифицировать код.
Ну мы то генерим для новой структуры все методы предка. Ничего не модифицируем. Мы мо S>То есть мы уже выбежали за пределы source generator. S>Далее, если мы попробуем делать какие-то ещё приседания на воображаемом будущем АПИ расширения компилятора: в предке нет никакого тела конструктора. Точно ли мы хотим дописать в конструктор потомка _a = default(), подразумевая семантику Child(int b) : base()? S>Что делать, если в предке определён параметризованный конструктор?
Ну копируем тело конструктора предка. О чем я и писалю
S>Возникает вопрос: а что за сценарий у нас такой, где нужны именно структуры, и именно наследование?
Ну как раз есть у нас Дженерик тип, но хочется сделать расширение для конкретного типа.
Для класса просто наследуемся от Account<T>, для расширения для конкретного типа
class StringAccount : Account<string>
{
public StringAccount(string id) : base(id)
{
}
}
и солнце б утром не вставало, когда бы не было меня
Re[65]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Serginio1, Вы писали: S>Ну мы то генерим для новой структуры все методы предка. Ничего не модифицируем. Мы мо Конструктор потомка у нас уже есть, и он уже падает с ошибкой компиляции.
S>>Далее, если мы попробуем делать какие-то ещё приседания на воображаемом будущем АПИ расширения компилятора: в предке нет никакого тела конструктора. Точно ли мы хотим дописать в конструктор потомка _a = default(), подразумевая семантику Child(int b) : base()? S>>Что делать, если в предке определён параметризованный конструктор? S> Ну копируем тело конструктора предка. О чем я и писалю
Давайте проделаем этот мысленный эксперимент на практике:
[Inherits(typeof(Parent))]
public partial struct Child
{
private int _b;
public int GetB() = >_b;
public Child(int b) => _b = b;
{
_b = b;
_a = a; // error CS0103: The name 'a' does not exist in the current context
}
}
Упс! Тело конструктора предка нам ничем не помогает.
S>>Возникает вопрос: а что за сценарий у нас такой, где нужны именно структуры, и именно наследование?
S> Ну как раз есть у нас Дженерик тип, но хочется сделать расширение для конкретного типа. S>Для класса просто наследуемся от Account<T>, для расширения для конкретного типа
Это прекрасно — но со структурой-то какой сценарий? Почему вам нужна именно структура, а не класс со всеми его преимуществами?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[5]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, Sharov, Вы писали:
S>>Здравствуйте, gandjustas, Вы писали:
G>>>далеко не самый кроссплатформенный,
S>>А какой язык самый кроссплатформенный, помимо С? Работает всюду, из коробки.
G>JS. Код на C далеко не везде можно запустить.
А где можно запустить JavaScript, но получиться C?
Re[66]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Sinclair, Вы писали:
S>> Ну копируем тело конструктора предка. О чем я и писалю S>Давайте проделаем этот мысленный эксперимент на практике: S>
[Inherits(typeof(Parent))]
S>public partial struct Child
S>{
S> private int _b;
S> public int GetB() = >_b;
S> public Child(int b) => _b = b;
S> {
S> _b = b;
S> _a = a; // error CS0103: The name 'a' does not exist in the current context
S> }
S>}
S>
S>Упс! Тело конструктора предка нам ничем не помогает.
Всегда можно ручками самому прописать, а при генерации проверить есть ли уже такой. S>>>Возникает вопрос: а что за сценарий у нас такой, где нужны именно структуры, и именно наследование?
S>> Ну как раз есть у нас Дженерик тип, но хочется сделать расширение для конкретного типа. S>>Для класса просто наследуемся от Account<T>, для расширения для конкретного типа S>Это прекрасно — но со структурой-то какой сценарий? Почему вам нужна именно структура, а не класс со всеми его преимуществами?
Ну как раз при взаимодействии с нативным кодом, где передаются массив структур.
Ну и на самом деле SG может выступать как специализация из аля шаблона С++. То есть максимально приблизить к нативному коду.
Ну и учитывая Preview Features in .NET 6 – Generic Math
Еще легче переносить шаблоны С++
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S> Всегда можно ручками самому прописать, а при генерации проверить есть ли уже такой.
Ну, это, конечно, вариант. Наверное, я ещё не привык к SG, чтобы без стеснения писать такой код.
S> Ну как раз при взаимодействии с нативным кодом, где передаются массив структур.
Нужен какой-то конкретный пример, чтобы я понял, какой код приходится писать.
Пока что при моём ограниченном взаимодействии с нативным кодом получалось обойтись без наследования структур.
S>Ну и на самом деле SG может выступать как специализация из аля шаблона С++. То есть максимально приблизить к нативному коду. S>Ну и учитывая Preview Features in .NET 6 – Generic Math S>Еще легче переносить шаблоны С++
Какие именно шаблоны хочется перенести?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[6]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Sinclair, Вы писали:
V>>А как, по-твоему, возращается по-значению структура, размер которой больше ширины регистра? S>Как и всё — кладётся в стек.
Каким образом?
Это в модели .Net VM два независимых стека — стек данных и стек возвратов.
К тому же, стек данных волшебный, с безразмерными ячейками.
В мейнстримовых архитектурах у нас стек один, и мы оперируем в нём вполне конкретным набором бит.
При возврате из метода этот один стек должен вернуться к своему состоянию до вызова метода или даже до помещения туда аргументов (в первом случае cdecl, во втором остальные соглашения).
Работает оно так:
internal struct S1 {
public long l1, l2, l3;
public static S1 Create() => new S1();
public static void Create(out S1 result) {
result = new S1();
}
}
Оба метода Create эквиваленты в железе, т.е. в обоих случаях как аргумент будет подана ссылка на участок памяти, куда вернуть результат.
Например, в архитектуре x64 fastcall, эта ссылка в обоих случаях будет подана через RCX.
FindChild — тяжелый метод в смысле сложности операций.
Несколько арифметических операций приравниваются к одной операции сравнения в плане сложности, а у тебя весь метод — бесконечные сравнения.
Можно попробовать заменить childIndex_X на inplace массив и сделать линейный поиск в цикле.
Я когда-то экспериментировал, примерно до 20-30 элементов линейный поиск быстрее бинарного.
Скорее всего это связано с предсказателем переходов процессора.
Цикл стоит написать так, чтобы позитивная проверка продолжала цикл (как оно есть в обычном for в котором более одного условия продолжения), тогда будет больше вероятность правильного первого предсказанного ветвления. Остальные ветвления будут повторять предыдущие до момента нахождения нужного элемента, т.е. зацикливание будет бесплатным, в отличие от ветлений по ссылке.
Заодно тело метода станет маленьким, вероятность инлайна вырастет.
S>Опять же в доке сказано, что из разных потоков работать с зокетами нельзя.
Это клиентскому кому нельзя.
Прерывания от сетевой карты всё-равно асинхронные, исполняются с т.з. потоков в другом потоке, и в момент обнаружения и забора новых пакетов данных при очередном вызове со стороны юзверя унутре без синхронизации никак. Хотя, синхронизация может быть выполнена на lock-free алгоритмах, но знать бы достоверно...
S>Так что явно там нет никаких примитивов синхронизации.
Там нет синхронизации публичного АПИ.
Это не то же самое, что межпоточная перекачка данных.
Например, у нас есть эффективные очереди для перекачки данных м/у потоками.
В одну такую очередь могут писать несколько потоков, а читать без синхронизации только один.
Здесь примерно такая же схема — прерывание выполняется в некоем "случайном" аппаратном потоке в контексте ядра, обработчик прерывания должен покласть новые пакеты в межпоточную очередь.
V>>Выглядит так, что у тебя своеобразные представления как о возможностях AOT, так и о возможностях hot-spot оптимизаций. S>У меня своеобразные представления о том, как что должно работать.
Тю, они у меня, да и не только у меня примерно такие же.
Т.е. "на пальцах" мы сформулировать можем и даже понимаем, почему "это" можно сделать, но от формулирования до фактической реализации "кем-то" проходят десятки лет, однако.
В общем, при разработке требуется принимать актуальные решения, а не такие, которые потенциально могут сработать лет эдак через 20.
V>>Вручную писаный сериализатор будет оптимизирован и в АОТ, S>Каким образом? На основании чего АОТ будет выполнять спекулятивный инлайнинг?
Вручную писанные сериализаторы обычно оперируют конкретными типами, в этом случае для AOT раздолье.
V>>Например, "выпрямлять" в памяти банальный List<T>. S>Что значит "выпрямлять"? Он же уже и так прямой.
Он дважды косвенный.
V>>Статистика в основном нужна для определения мест, где требуется оптимизация. S>Мы ходим по кругу. Ну вот мы увидели, что у нас в горячем цикле вызывается _serializer.Serialize(dataReader, stringBuilder). S>Дальше что? Это косвенный вызов по интерфейсу.
Тебя интересует нынешнее положение дел или будущее гипотетическое?
В нынешнем состоянии джит делает те же оптимизации, какие сделал бы и АОТ, только ограничен по времени.
В гипотетическом спекулятивном оптимизаторе по фактически поданным типам он сможет убрать виртуальные вызовы, т.е. многое заинлайнить, в т.ч. исключить лишние выделения из кучи GC, но где-то на входе должна быть проверка, что поданные типы (рекурсивно по всем меберам, куда дотянулась спекулятивная оптимизация) — такие же.
И вот эта проверка — "природный" ограничитель возможности технологии спекулятивной оптимизации.
V>>В рекордсете из 1001 элемента первые 1000 будут прочитаны без оптимизации. V>>Затем будет выполнена дорогостоящая оптимизация и последний элемент прочитают оптимальным образом. S>Ага. Зато последующие обращения к этому же датасету будут уже оптимальны.
Схема рекордсета каждый раз создаётся с 0-ля, это будут другие экземпляры схемы с другими экземплярами абстрактных дескрипторов полей.
S>А АОТ так и оставит косвенный вызов через VMT.
Спекулятивный код с этой задачей тоже не справится.
Слишком много вложенных друг в друга абстракций.
V>>И даже если схемы будут те же — это будут другие экземпляры схем, вот в чём прикол. S>При чём тут экземпляры? Речь о коде методов, т.е. о содержимом VMT.
Первый VMT — это абстракция от провайдера БД.
Прошли.
Далее у нас массив абстрактных дескрипторов полей, вторая VMT.
Полей десяток-другой, допустим.
Для каждого поля надо убедиться, что тип дескриптора тот же.
А оно точно будет эффективнее предложенной мною схемы вызова ф-ии-маппера по указателю на метод?
Я думаю, что проверить можно уже прямо сейчас, т.е. написать гипотетический код, который сгенерировал бы спекулятивный оптимизатор со всеми предпроверками условий и сравнить с предложенной мною схемой.
V>>В случае DataReader в нынешнем виде не прокатит — слишком большая иерархия объектов, всю её проверять на соответствие текущему хот-спот-коду будет накладней получаемых от хот-спот плюшек. S>И удивительным образом, Java ухитряется сворачивать вполне себе прикладной код в приемлемый x86/x64.
Я не помню, чтобы она что-то там сворачивала, когда абстрактные объекты состоят из десятков других абстрактных объектов.
Мы тут однажды серьезно бодались с коллегой '.' (ник такой), он приводил примеры — они примитивнейшие все.
V>>Тогда проверка соответствия лейаута объекта будет сводиться к проверке только ссылок на метаинформацию столбцов рекодрсета, где эти столбцы ссылаются на одни и те же статические-заготовленные конвертеры. S>И даже такую конструкцию способен улучшить хотспот.
Убрать самый первый VMT.
Вот это он может, угу.
V>>Т.е. сравни — проверить только равенство ссылок в объекте верхнего уровня или рекурсивно пройтись по кучерявым объектам, проверяя равенство всех полей всех дочерних элементов. V>>Счётчик сложности в последнем случае скажет "извините, в другой раз". S>Вот это уже интересный вопрос. Всё зависит от того, сколько у нас реальных типов используется внутри тела цикла.
В данном случае — сколько читаемых полей в рекордсете.
Пусть даже все поля одного типа, но дескриптор для каждого поля — это уникальный экземпляр наследника абстрактного класса.
А в моей схеме на указателях на мемберы все дескрипторы полей любых типов имеют один и тот же тип (или как миниму не абстрактны).
А для полей одинакового типа и вовсе будет один и тот же экземпляр дескриптора.
V>>Я показал устройство таблицы конвертеров в сообщении, на которое уже давал ссылку. V>>Читабельность и поддерживаемость (то бишь расширяемость) прекрасная. V>>А в варианте с новыми указателями на ф-ии — еще и максимально-эффективная, т.е. даже, грубо, на асме или IL быстрее не сделаешь. S>Навскидку не видно, благодаря чему это будет быстрее вызова через интерфейс — ведь в реальности у нас будет не просто вызов по указателю. Сначала надо будет достать по указателю таблицу функций (рукопашный аналог VMT)
Ну да, просто минус одна косвенность.
Если сделать дескрипторы структурами (всё-равно в массивах хранятся) — минус две косвенности.
Если сделать часть массива inplace (как в std::string) — будет минус три косвенности.
S>Вот то-то и оно. Так что вы итоге мы обсуждаем гипотетический АОТ vs гипотетичексий хотспот. S>В моей идеальной картине мира они сосуществуют: то есть АОТ работает заранее, возможно, с применением PGO. Как опциональный компонент, призванный улучшить время холодного старта. S>А затем в дело вступает хотспот, который докомпилирует динамический код (если такой появится), и использует рантайм статистику для дальнейших оптимизаций уже и так неплохого кода.
После качественного AOT стираются типы.
Я не представляю, как у нас должна будет работать спекулятивная оптимизация в этом случае.
Это надо держать два варианта кода в бинарнике: скомпиллированный через АОТ и исходный IL.
V>>Даже существующий полноценный доступен только для iOS на основе mono (ХЗ какого он там качества). V>>А виндовые UWP-приложения на .Net Core UWP компиляются серверами магазина Windows под сетку устройств, тот код публично недоступен. S>Так нам же не исходники АОТ нужны.
Так он никак не доступен, если я правильно понимаю ситуацию.
А то, что доступно — это другие опенсорсные проекты в разной степени готовности.
Т.е., на прямо сейчас нельзя дать отмашку, мол, АОТ для .Net Core готово, пользуйтесь.
Насколько я понимаю, в некоторой степени будет готов AOT для webasm с выходом .Net 6.0.
V>>Я помню обратное — ты так и не прошёл понимание про повторно-используемые "кубики" при построении плана запроса. S>Я привёл пример "плана запроса" и просил показать, какие его запчасти можно повторно использовать для альтернативных планов того же запроса, или каких-то других запросов. V>>Псевдокод давался. S>Да, мной.
При желании можно будет вернуться и продолжить или создать тему-продолжение.
Обсуждение то было достаточно забавным, на мой взгляд.
Хорошо раскрыло уровень рассмотрения происходящего в БД с т.з. ведущих базоводов этого сайта, для меня было откровением, что настолько с высоты птичьего полёта на это смотрят.
Я еще там же высказался — это значит, что курс проектировани СУБД те коллеги не проходили.
(не путать с проектированием БД в конкретной СУБД)
Например, взять тебя.
Ты более-менее разбираешься в возможностях самой БД, т.е. в её основной функциональности.
Более-менее разбираешься в том, как база хранит данные (хотя, почему-то считал это чуть ли не откровением для MSSQL, хотя такой же принцип используют почти все ISAM-базы еще с конца 80-х, кроме хранилищ на DBF-файлах, которые у нас были слишком популярны из-за FoxPor и 1C). Т.е., как по мне, вот эти эксурсы в то, как база хранит данные, да еще выдаваемые за откровение — это всё сильно засоряло обсуждение информацией ни о чём.
Но основное, что обсуждалось — это то, что находится м/у данными и "публичной" функциональностью, т.е. в какой вид компиллируются, собсно, запросы и как исполняются на уровне железа — тут у тебя чёрная дыра.
Плюс, чуть что — убегаешь в O-сложности, по мне как за соломинку хватаешься, хотя по-факту базы редко хватаются за это O, бо в подавляющем большинстве таблиц у нас кол-во строк исчисляется единицами десятков, сотен, редко тысяч. Да еще почти всегда с "идеальным" для базы суррогатным первичным ключом, управляющим расположением записей на страницах.
Опять же — ограничения.
Разумеется, базы могут обслуживать произвольные сценарии и произвольные запросы.
Но для анализа придумали т.н. "исторические данные" и OLAP.
А боевое приложение магазина-склада или биржи — это набор хорошо формулируемых ограничений.
По правилам инженерии, чем больше ограничений, тем проще.
"База вообще" и "база, к которой обращается одно специально разработанное приложение" — две большие разницы.
Во втором случае кол-во join-ов может быть до смешного малым, например, в случае кеширования справочных данных приложением.
И рассуждения как раз шли в направлении того, сколько реальных вариантов запросов (за минусом параметров к ним) породит конкретное приложение.
Сколько потенциальных планов породит такой запрос, с учётом отброшенных заведомо неудачных не в рантайме, а еще на этапе компиляции.
Сколько запросов будут иметь общие части, например, в одном запросе where Field1=A, а в другом where Field1=A AND Field2=B.
Например, в обоих случаях может получиться так, что лучшим вариантом будет сканить по Field1, бо по этому полю стоит более выгодный индекс (больше уникальных значений в индексе и распределение строк по индексу более равномерное). Это пример той самой "склейки" генерируемой функциональности, где план второго запроса целиком включает план первого — вот что имелось ввиду под "экономией", т.е. имелось ввиду повторное использование.
И да, никто не призывал отказываться от статистики, статистика должна управлять выбором из уже готовых алгоритмов выборки данных.
Там же я на это отвечал неоднократно в ответ на попытки ликбеза очевидных вещей.
V>>Для статических еще в момент компиляции известны наличествующие индексы. S>Для любых. Дело не в динамике, а в количестве сочетаний.
Это соломинка для утопающих, а не аргумент.
Для произвольного анализа данных существует OLAP — используйте инструменты по назначению, как грится.
А для 99% применений БД (торговля и учёт ТМЦ, финансы/бухгалтерия, биржи, банковский опердень) — у нас операции сводятся к приходу-расходу-остаткам и сбоку те самые "справочные данные", составляющие большинство таблиц (но не большинство записей, ес-но).
Тут примерно как с твоей спекулятивной оптимизацией — даже грубое исследование операций показывает, что эти самые операции можно удешевить примерно на порядок.
Происходящее сейчас в индустрии очевидно — инструмент слишком общего назначения используют для слишком узких сценариев.
V>>Поэтому, комбинаторика будет только по различиям в статистике, где для многих типов индексов, которые я обозвал enum (разновидность справочных данных эдакого системного плана, т.е. которые жестко привязаны к версии приложения) — статистика известна на момент компиляции. То бишь, кол-во уникальных значений в индексе, характер этих значений (подряд или разрежёнными "островками" и т.д.). S>В реальной системе таких "индексов" пренебрежимо мало.
В складе-бухгалтерии получается прилично.
На бирже тоже, в которой из динамических справочных данных только контрагенты и конкретные экезмпляры (карточки) ценных бумаг.
Остальные справочные данные для конкретной биржи статические — типы ценных бумаг, типы лотов/ограничений, типы операций, типы ценовой сетки и т.д.
(Или для конкретного домена биржи, бо некоторые крупные биржи технически из себя представляют совокупность независимых бирж под одной крышей)
Для банка аналогично.
S>Ну, так это известный трюк, связанный не столько с хотспотом, сколько с отсутствием value-типов. А иногда — и с тем, что мы хотим получить автовекторизацию, которая не работает в случае int a; int b; int c.
В плюсах работает, значит и в джите потенциально может работать.
И для векторизации надо хранить в одном массиве подряд, а не в 3-х.
V>>Вытягивают её ручками, помогая хот-споту. S>Ну, по честному это применяется только в том случае, если перформанс прямо очень важен, а себестоимость разработки — нет. А обычные гражданские приложения, написанные идиоматическим образом, работают приемлемо быстро.
Разве что запускаются неприёмлимо долго.
И тормозят первые секунды.
Не от хорошей же жизни Андроид перешёл на AOT, а iOS отродясь бочку катила на скриптовые технологии, даже запретив Flash.
V>>Сам понимаешь, поддерживаемость ТАКОГО кода ни идёт ни в какое сравнение с предложенной мною микро-оптимизацией на основе таблицы диспетчеризации конвертеров. S>Да, с этим я не спорю. Именно поэтому мне CLR нравится больше, чем JVM.
А мне в сообществе дотнета не нравился все годы пропагандируемый отказ от борьбы за перформанс как таковой.
В джаве, не смотря на то, что в ней аналогичный перформанс достигается несравнимо большей трудоёмкостью, такого странного менталитета нет, народ к этим вещам относится спокойней.
И я приветсвую тот факт, что в .Net Core набежали суровые нейтивные ребята и стали диктовать свои условия, что нынешний дотнет уже не узнать.
Плохо, что так много времени было упущено, конечно...
Здравствуйте, Sinclair, Вы писали:
V>>Кстате, и тут АОТ может помочь, бо если две структуры имеют одинаковый лейаут и функциональность, то и сгенерённый код под них мог бы бы одинаковый. S>Так-то и джит мог бы "увидеть", что две структуры имеют одинаковый лэйаут, то можно сравнить MSIL методов и для совпадающих методов генерировать одну копию кода.
V>>Именно. V>>Хотя, при передаче по-значению можно выкрутиться через implicit-оператор приведения типа. S>Ну, это будет одновременно криво и неэффективно
Потому что нет возможности объявить оператор приведения типа в сигнатуре ref type.
Re[66]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Sinclair, Вы писали:
S>Упс! Тело конструктора предка нам ничем не помогает.
Это, скорее всего, делать необязательно.
Вот тут:
class Base {
private int a;
public Base(int a) => this.a = a;
}
class Derived : Base {
private int b;
public Derived(int a, int b)
: base(a)
=> this.b = b;
}
После джита всё-равно останется только
Derived(int a, int b) {
this.a = a;
this.b = b;
}
S>Это прекрасно — но со структурой-то какой сценарий? Почему вам нужна именно структура, а не класс со всеми его преимуществами?
Здравствуйте, Sinclair, Вы писали:
S>>Ну и учитывая Preview Features in .NET 6 – Generic Math S>>Еще легче переносить шаблоны С++ S>Какие именно шаблоны хочется перенести?
Где арифметические операции используются.
Я же говорю — набежали суровые нейтивные ребята и диктуют свои правила.
V>>>Даже существующий полноценный доступен только для iOS на основе mono (ХЗ какого он там качества). V>>>А виндовые UWP-приложения на .Net Core UWP компиляются серверами магазина Windows под сетку устройств, тот код публично недоступен.
Это в самом начале так было, еще во времена винфона.
Уже лет 5 как UWP приложение надо на .Net Native скомпилировать у себя на машине, иначе в стор залить не дадут.
Основные проблемы .Net Native:
— Микрософтовцы на него забили и больше не развивают
— Поддерживается .Net Core не выше 2 с чем-то
— Релизный код может работать совсем не так, как отлаженный на JIT. А отладчик там очень хреново работает, фиг поймешь, где сломалось.
— Результат часто тормознее, чем на JIT
.Net Native в качестве бэкенда использует микрософтовский компилятор Си++
V>Насколько я понимаю, в некоторой степени будет готов AOT для webasm с выходом .Net 6.0.
Не-а, для wasm сейчас используется адаптированный моновский (тот же, который для iOS, на основе LLVM)
Здравствуйте, Sinclair, Вы писали:
S>> Ну как раз при взаимодействии с нативным кодом, где передаются массив структур. S>Нужен какой-то конкретный пример, чтобы я понял, какой код приходится писать. S>Пока что при моём ограниченном взаимодействии с нативным кодом получалось обойтись без наследования структур.
Ну вы с vdimas как раз и обсуждаете нативный код. Так в С++ реально могут быть шаблоны которые можно перенести в C# через дженерики.
А вот конкретную реализацию для каждого типа без перегрузки операторов так любимых в C++ можно сгенерить через SG.
S>>Ну и на самом деле SG может выступать как специализация из аля шаблона С++. То есть максимально приблизить к нативному коду. S>>Ну и учитывая Preview Features in .NET 6 – Generic Math S>>Еще легче переносить шаблоны С++ S>Какие именно шаблоны хочется перенести?
Здравствуйте, vdimas, Вы писали:
V>Т.е., на прямо сейчас нельзя дать отмашку, мол, АОТ для .Net Core готово, пользуйтесь. V>Насколько я понимаю, в некоторой степени будет готов AOT для webasm с выходом .Net 6.0.
Здравствуйте, Sinclair, Вы писали:
S>А запрет на виртуальные методы в данном контексте плавно превращается в запрет реализовывать интерфейсы, чтобы избежать странных эффектов. S>Ну, либо правила определения того, что можно, а что нельзя, становятся чрезмерно сложными.
У value-типов исключили VMT, отсюда остальные правила выводятся автоматически, даже в случае разрешения наследования структур.
Например, по ссылке на value-тип волей-неволей придётся считать, что это точный тип.
Соотв., реализация интерфейсов должна быть в этом типе, потому что интерфейсные методы в генериках будут вызываться непосредственно.
Во время боксирования в куче тоже создаётся объект с типом ссылки и копируется тело известной структуры, а не неизвестного наследника.
Насчёт разруливания интерфейсов в боксированных значениях — там пока мест не видно никаких сложностей, можно брать готовый механизм из классов (а другого и не будет для боксированных значений).
Брать надо тот механизм где метод, реализующий интерфейс, не объявлен виртуальным (как оно происходит в случае структур).
Тогда одноимённый метод в классе-наследнике рассматривается уже как new, т.е. не переопределяет интерфейсный метод базового класса.
Чтобы в наследнике переопределить нужный метод интерфейса, надо наследнику опять указать в списке баз интерфейс и тогда уже переопределить интерфейсный метод одним из доступных способов:
interface I {
void Foo();
void Bar();
}
class Base : I {
public void Foo() {}
public void Bar() { }
}
class Derived : Base, I {
void I.Foo() {}
}
Если бы существовало наследование структур, то здесь достаточно было бы заменить class на struct, т.е. имеющиеся реализованные правила мэппинга методов интерфейсов на методы классов и так обеспечивают требуемую семантику.
Т.е. я понимаю, что ловушкой тут может быть недопонимание разработчиками происходящего, когда они подадут наследника по ссылке, а будут вызываться методы базового класса.
Но не готов судить, какая чаша весов перевесит, если на другой чаше лежит возможность наследовать структуры, т.е. откроет возможность для более агрессивного проектирования в стиле value-type...
Здравствуйте, Евгений Акиньшин, Вы писали:
V>>>>А виндовые UWP-приложения на .Net Core UWP компиляются серверами магазина Windows под сетку устройств, тот код публично недоступен. ЕА>Это в самом начале так было, еще во времена винфона. ЕА>Уже лет 5 как UWP приложение надо на .Net Native скомпилировать у себя на машине, иначе в стор залить не дадут.
Т.е., Windows UWP ARM32/ARM64 тоже самим компилять?
V>>Насколько я понимаю, в некоторой степени будет готов AOT для webasm с выходом .Net 6.0. ЕА>Не-а, для wasm сейчас используется адаптированный моновский (тот же, который для iOS, на основе LLVM)
Мде?
А я тут краем глаза не раз натыкался на то, что для Blazor будет AOT в .Net 6.0.
А это всё тот же моновский?..
Ну, тогда всё еще печальнее, чем я думал.
Re[51]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, Serginio1, Вы писали:
V>>Насколько я понимаю, в некоторой степени будет готов AOT для webasm с выходом .Net 6.0. S>На самом то деле он есть. И я тебе уже ссылку давал https://devblogs.microsoft.com/dotnet/conversation-about-ready-to-run/ S>Называется Ready to run (R2R).
Это не то.
R2R идёт вместе с исходным IL и JIT.
Для Blazor обещали железобетонный АОТ, безо-всякого IL+JIT в нагрузку, чтобы уменьшить размер образа.
С этой же целью для него уже сделали триммер.
Re[52]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, Евгений Акиньшин, Вы писали:
V>>>>>А виндовые UWP-приложения на .Net Core UWP компиляются серверами магазина Windows под сетку устройств, тот код публично недоступен. ЕА>>Это в самом начале так было, еще во времена винфона. ЕА>>Уже лет 5 как UWP приложение надо на .Net Native скомпилировать у себя на машине, иначе в стор залить не дадут.
V>Т.е., Windows UWP ARM32/ARM64 тоже самим компилять?
Только ARM64.
Я сейчас собираю и выкладываю 3 пекиджа: x86\x64\ARM64
V>>>Насколько я понимаю, в некоторой степени будет готов AOT для webasm с выходом .Net 6.0. ЕА>>Не-а, для wasm сейчас используется адаптированный моновский (тот же, который для iOS, на основе LLVM)
V>Мде? V>А я тут краем глаза не раз натыкался на то, что для Blazor будет AOT в .Net 6.0. V>А это всё тот же моновский?..
V>Ну, тогда всё еще печальнее, чем я думал.
Ну конкретно AOT в моно не плох — там за конечную оптимизацию, если я правильно понимаю, LVVM отвечает.
Весь BCL теперь единый — несовместимостей нет.
Остается убогий моновский сборщик мусора, он действительно может быть сильно медленней, чем в нормальном дотнете.
Но, фактически, по крайней мере на iOS, все достаточно шустро работает, если за мусором следить. Точно, не хуже их нативного ObjectiveC.
Там печаль в другом. Некоторые вещи из дотнетовской VM плохо на wasm ложатся и из-за необходимости их эмулировать тормоза возникают.
Сейчас блазорный код, даже с AOT, работает медленней jscript-го. Обычно в разы.
Здравствуйте, vdimas, Вы писали:
V>Для Blazor обещали железобетонный АОТ, безо-всякого IL+JIT в нагрузку, чтобы уменьшить размер образа. V>С этой же целью для него уже сделали триммер.
Они много чего обещали , я даже когда-то верил.
В текущей версии дополнительно к скомпилированному через AOT wasm на клиента тащится весь IL.
JIT-а там и правда нет, вместо него есть интерпретатор, который работает там, где AOT что-то не смог.
Интерпретированный код где-то в 50 раз тормозней нормального.
Триммер да, вроде хорошо получился, объем сильно меньше, чем в 5-м .net.