Re[11]: Unity
От: vdimas Россия  
Дата: 31.07.21 00:27
Оценка:
Здравствуйте, Serginio1, Вы писали:

V>>Откуда взяться дотнету в нейтивном коде?

S> Легко. .Net Core для отладки используется

Не используется.


S> Искать неохота. Но старай вариант

S>https://docs.microsoft.com/ru-ru/archive/msdn-magazine/2015/windows-10-special-issue/microsoft-net-net-and-universal-windows-platform-development

Речь шла про Unity.
Нет в Unity никакого дотнета.


V>>У них сборщик не из дотнета, известный консервативный https://www.hboehm.info/gc/.

V>>Г-но.
S>Но могут и коровский подключить.

Я тоже теоретически могу в космос полететь.
Но пока не полетел.
Вот там так же.


V>>ИМХО, именно поэтому было выбрано генерирование в исходники С++, т.к. это автоматизирует отладку по исходникам C# даже с учётом конверсии исходников через свою приблуду.

S>С++ выбран из-за оптимизирующих компиляторов. Тот же .Net Native точно так же и поступает и CoreRT dhjlt

.Net Native не имеет к Unity никакого отношения.
И иметь никогда не будет.
По крайней мере до тех пор, пока не научатся дешево размечать стек.

Давай я тебе немного бенчмарков приведу:
Последовательно сравнивается стоимость вызов через интерфейс, делегат, через делегат поверх FunctionPointer, через managed и unamaned указатели на функцию (фишка С# 9.0, можно вызывать ф-ию по её адресу без создания объекта-делегата).
          Baseline |   147.9 us
          Delegate |   275.9 us
  Delegate from MI |   280.7 us
 Delegate from ptr | 8,202.5 us
    DllGetProcAddr |   756.3 us
         DllImport |   733.4 us
         Interface |   319.7 us
  Managed func ptr |   183.2 us
 Ptr from delegate | 1,327.1 us
Unmanaged func ptr | 7,209.2 us


Baseline — накладные расходы, измеряет стоимость прокладки пути к целевым измерениям (руки не дошли прикрутить кастомный ColumnProvider в тест, этот BaseLine надо вычитать из других значений, а не смотреть на отношение к нему).

Но и так ситуация понятна, ИМХО.
Delegate from ptr — это создание делегата на адрес managed-ф-ии через Marshall.GetDelegateForFunctionPointer, т.к. указатель на ф-ию рассматривается как unmanaged.
Есть и наборот, в обоих случаях указатель ф-ии в любом случае считается указателем на unmanaged функцию.

Unmanaged func ptr — это вызов managed-кода через unmanaged указатель на managed метод следующего типа:

private readonly delegate* unmanaged<IBar, ref ulong, void> _fn;
...
_fn(_bar, ref value);


Далее, адрес managed-ф-ии получается через рефлексию
bar.GetType().GetMethod("Foo")!.MethodHandle.GetFunctionPointer()

Или через
delegate* managed<IBar, ref ulong, void> _fn = &bar.Foo


DllImport — встроенный DllImport.
GetProcAddr — получение адреса символа из DLL вручную в unmanaged указатель на ф-ию и последующий вызов.
По стоимости примерно равны.

Одним словом, вызов нейтивного кода из managed относительно дорогой.
Но вызов managed кода из нейтивного — вообще ж-па, а в графических приложениях и то и другое активно юзается.

А я еще так думаю, что проблема в новом JIT, который тщательно оптимизирует ф-ии только после многих вызовов.
В дотнете до 3.1 такого не было.
Т.е., может захватываться адрес самого первого, неоптимизированного варианта ф-ии, который был в момент загрузки кода JIT-ом и затем вызов происходит только по этому адресу.
Это объясняет разницу м/у Ptr from delegate и Unmanaged func ptr.
В первом случае делегат держит ссылку на на managed указатель на метод и, когда джит подготовит новый метод, переключит указатель на него.
Во втором случае остаётся указатель на неоптимизированный вариант первоначальной JIT-компиляции.

(если любопытно, могу в "Дотнете" выложить тесты целиком с пояснениями)

В общем, опять облом-с.
А я серьезно на этот указатель на функцию рассчитывал. ))
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.