Здравствуйте, Sinclair, Вы писали:
S>>>По-моему, нормальный вариант — только один. Если API принимает struct, то мы и отдаём struct.
V>>Или class, если требуется сохранить затем.
S>И сразу нарываемся на custom marshaller. Зачем?
На практике не нарываемся, если класс содержит только примитивные типы в полях.
Структуры в АПИ обычно идут по указателю, на стороне C# это ref для struct или просто классы по ссылке.
Маршаллер пинит экземпляры таких классов, вот и весь маршаллинг.
V>>Практически всегда, если данные не предназначены для последующего хранения, вплоть до того, что могут ссылаться на невалидную область памяти.
S>Хранение хранению рознь. У реф структ слишком много ограничений
Ограничений, считай, два всего:
— они могут располагаться только на стеке;
— не могут быть аргументами генериков.
Оба случая хорошо подходят под интероп.
V>>В select в линухах подаются битовые массивы, поэтому stackalloc решает вопрос.
V>>Длина битовых массивов идёт первым аргументом — как максимальный номер хендла.
S>Ну это тривиальный частный случай. Как только мы встречаем что-то сложнее примитивного массива интов, начинаются танцы с бубном.
Такой же stackalloc начинается.
V>>А как же замкнуть фрейм стека для GC?
S>А зачем?
Чтобы GC игнорировал стек нейтивных вызовов.
Т.е., возможна зебра вглубь всех вызовов:
— из управляемого кода в нейтив;
— оттуда приходит колбэк в управляемый код (многие перечисления в системных АПИ так работают);
— из этого фрейма опять вызывается что-то в нейтиве.
Указанные два "островка" управляемого стека должны быть связаны в однонаправленный список, от текущего верха стека к его нижним фреймам.
Дотнетный дебаггер при отладке, кстате, показывает места, где участки нейтивного стека пропущены.
V>>Такие у меня тоже есть в текущем дотнете, но по-мелочи.
V>>В RuiJIT сейчас чёрт ногу сломит, его надо серьёзно переделывать.
S>Я на своём уровне некомпетентности вижу только одну глобальную проблему: нет, как такового, хотспоттинга. Tiered compilation выглядит как жалкое подобие левой руки.
Tiered compilation и есть hotspot.
В моём примере с IConfig до появления Tiered compilation джит сразу генерил свой оптимизированный, но глупый код.
Теперь этот код надо исполнять сколько-то раз в цикле, чтобы джит его соптимизировал, иначе там 1-в-1 с исходником.
Tiered compilation выглядит как попытка ускорить старт приложения и ничего более.
Средней величины дотнетное приложение до него запускалось по 600-800 ms, сейчас примерно вдвое быстрее.
Особенно чувствительны к этой технологии те приложения, где инициализируется много статических данных (например, WPF и прочие, где описаны мильоны dependency property).
Cтоимость джита инициализирующего кода была в разы больше стоимости его исполнения, а код-то одноразовый.
S>Может, оно и блеснёт в какой-то момент (например, развязав руки дорогостоящим оптимизациям в Tier1), но мне кажется, что как-то это всё очень вяло. Чтобы выжимать из managed code максимум, надо уметь помимо "ой, давайте при первом проходе просто отдавать говнокод" делать очень много profile-based вещей, типа спекулятивного инлайнинга. Как я понимаю, в текущей архитектуре джита и CLR это вообще недостижимо. Максимум, что мы сможем получить эволюционным путём — это tier2 поверх tier0 и tier1.
Спасёт только качественный AOT.
Но разговоры об этом идут последние лет 15.
Последнее актуальное:
We are building a new version of Crossgen – Crossgen 2 – which starts with a new code base architected to be a compiler that can perform analysis and optimizations not possible with the previous version.
К нашей пенсии всё будет ОК, не переживай. ))
V>>ХЗ, именно в то время опенсорсный GCC развивался бешенными темпами, что аж догнал MSVC.
S>Ну, тут спорный момент. Я в чём-то понимаю позицию команды. Для GCC была уверенность в том, что коммиты не будут в будущем списаны за ненадобностью.
S>Для Рослин была совершенно стандартная ситуация легаси — когда есть уже ясное видение, что в долгосрочной перспективе мы не хотим ехать на существующей технологии;
Ммм...
В общем, там несравнимые объемы и сложность кода, имелось ввиду это.
Если тебе Рослин кажется сложным проектом — ты сильно заблуждаешься.
Рослин простой как балалайка, хотя и достаточно объемный.
И что странно — нормального оптимизирующего компилятора C# всё еще нет.
Т.е. слишком многое оставлено джиту такого, что можно причесать и до джит.
Например, тот же пример с
SomeClass<Config1> c1 = ...; c.Foo();
Если все типы объявлены в одной сборке, там нефик делать соптимизировать лишнее компилятором.
Аналогично куча строковых вычислений и прочих, особенно при инициализации — компилятор честным образом отдаёт это всё в рантайм, хотя там до половины и более зачастую вычислимы в compile time.
S>инкрементально переехать на новую технологию мы не можем; при этом в каждый момент мы понимаем, что если мы вкладываемся в легаси, то получаем быстрый результат, но при этом а) отнимаем ресурсы от проекта портирования, и б) увеличиваем количество кода, которое надо будет портировать. Это отдаляет "светлое будущее" с удвоенной скоростью.
Да не факт.
Основное при разработке сложных проектов — хорошо понимать собственный код.
Итеративность в этом смысле привносит оперативность.
Т.е., в чём-то больше работы, да, но в целом происходящее оперативнее, т.к. некоторые бока/недоработки нового кода раньше вскрываются.
Любому "светлому будущему" надо по классике отводить примерно 9 месяцев на что-то средней сложности и не более 18-ти для чего-то совсем кардинального.
А тут 5-6 лет возни.
Это

И не переубедишь. ))
S>Многие компании на этом вообще ломаются.
Именно.
Просто MS сломать не так просто.
S>А MS ничего, всё же выехали с рослиным. Стиснули зубы, понимая, что рискуют аудиторией, но пилили.
Да, аудитория начала разбегаться.
Спас ход конём — выкатили для линухов и ушли в опенсорс, аудитория потихоньку возвращается.