Здравствуйте, vdimas, Вы писали:
S>>А почему тело Invoke на лету генерируется? V>Потому что тело Invoke может быть уникальным для различных экземпляров делегатов одного и того же типа.
V>Причём, даже если тело Invoke было ранее создано для конкретного SomeObj.SomeMethod, всё равно каждый раз с 0-ля генерится Invoke конкретно для типа SomeObj и его метода SomeMethod. V>Т.е., с каждым экземпляром делегата растёт и память, занимаемая областью кода. V>И финализация делегатов от этого тоже чуть дороже, потому что надо убирать память из сегментов кода, а там с перемещениями и уплотнениями не так всё радужно, как в сегментах данных.
А про это можно где-то почитать, потому что звучит крайне странно? Ладно, в первый раз надо скомплировать il код, но
далее он же кэширутся как для SomeObj.SomeMethod так и для других делегатов. А в новый версиях C# (>= 3.0) это
как-то исправлялось?
Здравствуйте, Sharov, Вы писали:
S>V>Причём, даже если тело Invoke было ранее создано для конкретного SomeObj.SomeMethod, всё равно каждый раз с 0-ля генерится Invoke конкретно для типа SomeObj и его метода SomeMethod. V>>Т.е., с каждым экземпляром делегата растёт и память, занимаемая областью кода. V>>И финализация делегатов от этого тоже чуть дороже, потому что надо убирать память из сегментов кода, а там с перемещениями и уплотнениями не так всё радужно, как в сегментах данных. S>А про это можно где-то почитать, потому что звучит крайне странно?
Это можно продебажить.
S>Ладно, в первый раз надо скомплировать il код, но
Дык, в том и суть, что способы создания функциональных объектов уже много десятилетий хорошо обкатаны в статически-типизированных языках.
Для каждого функционального объекта еще на этапе компиляции создаётся специальная функция, которая исполняет некое своё тело. И создание функционального объекта заключается в создании экземпляра объекта, который хранит данные захваченного контекста и указатель на эту сгенерённую функцию. Таким образом, экземпляры делегатов от одного thunk чаще всего отличаются только фактически захваченными аргументами (контекстом), а в случае, когда контекст (замыкание или частичные применения аргументов) отсутствуют, то делегат может быть вовсе синглтоном-константой (и это известно тоже еще на этапе компиляции).
Т.е., создание функционального объекта должно быть очень дешевым.
Почему в дотнете не сделали так же — вопрос на 100 мильонов. ))
S>далее он же кэширутся как для SomeObj.SomeMethod так и для других делегатов. А в новый версиях C# (>= 3.0) это S>как-то исправлялось?
Это надо смотреть от 8-го дотнета, там что-то пытались оптимизировать, я еще не дебажил.
Может и кешируют уже что-то.
Но до 8-го оно было так.
И я не видел патчей, которые создают эти внутренние свободные функции с телами делегатов на этапе компиляции.
Вряд ли пропустил, но если бы мне самому показали, что это уже довели до ума — было бы здорово, конечно.
Но что-то сомневаюсь, бо это натурально катастрофические изменения компилятора. Ведь рантайм должен поддерживать и старый способ, т.к. не только язык C# там работает, плюс рантайм еще должен уметь исполнять весь старый байт-код. Т.е. тут нужны как новые ср-ва рантайма, так и использование их из компилятора. Я о таком пока не слышал.
Здравствуйте, Shmj, Вы писали:
S>1. Для всех целых чисел один тип int. Там все.
Ну и правильно. А то в Расте том же заманали дрочеры на "доменно-ориентированное" говно. Один такой дрочер в своей либе использует u32, другой i32, третий usize. А потом мне надо сложить два результата или проитерироваться по результату, заполняя массив и начинается, ведь идеоматический Раст запрещает складывать i32 с usize, ну и код превращается в "ехал явно написанный числовой каст через явно написанный числовой каст". За этими приведениями типов логику происходящего не видно.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте