Сообщение Re[2]: Сделал так от 31.07.2020 19:26
Изменено 31.07.2020 19:33 Mystic Artifact
Re[2]: Сделал так
Здравствуйте, igor-booch, Вы писали:
IB>Всем спасибо, c рефлешеном, понятно, что можно всё, но производительность страдает,
IB>пока сделал так
С точки зрения производительности, не смотря, что такой паттерн не очень красивый (и имеет свои ограничения), — похожие паттерны уже распознаются JIT.
Ну, например:
Такой метод будет раскрываться в GetIntValue/GetDoubleValue/GetStringValue как будто никакого generic метода и нет вовсе, и т.к. T заранее известен — цепочка боксинга/анбоксинга так же подавляется, даже в Debug билдах.
--
С методом "public static void Do<TClass>(TClass @object) where TClass : IBase" немного иначе — в виду того, что на сегодня есть только фич-реквесты для раздельной компиляции специализаций. Тем не менее если метод Do<TClass> заставить инлайнится — то результат будет так же хорошим.
В частности с хинтом AggressiveInlining на Do и AggressiveOptimization на Main (не уверен что они нужны), метод Main примет форму (испытано на .net 5):
Как видно — в данном простом случае — JIT справился более чем отлично. Понятно, что это не совсем универсально (в случае если JIT откажется инлайнить — то будет уже совсем не всё так красиво ).
IB>Всем спасибо, c рефлешеном, понятно, что можно всё, но производительность страдает,
IB>пока сделал так
С точки зрения производительности, не смотря, что такой паттерн не очень красивый (и имеет свои ограничения), — похожие паттерны уже распознаются JIT.
Ну, например:
public T GetValue<T>() {
if (typeof(T) == typeof(int)) {
return (T)(object)GetIntValue();
}
else if (typeof(T) == typeof(double)) {
return (T)(object)GetDoubleValue();
}
else if (typeof(T) == typeof(string)) {
return (T)(object)GetStringValue();
}
else throw new InvalidOperationException();
}
Такой метод будет раскрываться в GetIntValue/GetDoubleValue/GetStringValue как будто никакого generic метода и нет вовсе, и т.к. T заранее известен — цепочка боксинга/анбоксинга так же подавляется, даже в Debug билдах.
--
С методом "public static void Do<TClass>(TClass @object) where TClass : IBase" немного иначе — в виду того, что на сегодня есть только фич-реквесты для раздельной компиляции специализаций. Тем не менее если метод Do<TClass> заставить инлайнится — то результат будет так же хорошим.
В частности с хинтом AggressiveInlining на Do и AggressiveOptimization на Main (не уверен что они нужны), метод Main примет форму (испытано на .net 5):
IN0015: 000000 sub rsp, 40
G_M59663_IG02: ; offs=000004H, size=0072H, bbWeight=1 PerfScore 20.75, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref
IN0001: 000004 mov rcx, 0x257900030B8
IN0002: 00000E mov rcx, gword ptr [rcx]
IN0003: 000011 call Console:WriteLine(String)
IN0004: 000016 mov rcx, 0x257900030C0
IN0005: 000020 mov rcx, gword ptr [rcx]
IN0006: 000023 call Console:WriteLine(String)
IN0007: 000028 mov rcx, 0x257900030C8
IN0008: 000032 mov rcx, gword ptr [rcx]
IN0009: 000035 call Console:WriteLine(String)
IN000a: 00003A mov rcx, 0x257900030B8
IN000b: 000044 mov rcx, gword ptr [rcx]
IN000c: 000047 call Console:WriteLine(String)
IN000d: 00004C mov rcx, 0x257900030C0
IN000e: 000056 mov rcx, gword ptr [rcx]
IN000f: 000059 call Console:WriteLine(String)
IN0010: 00005E mov rcx, 0x257900030C8
IN0011: 000068 mov rcx, gword ptr [rcx]
IN0012: 00006B call Console:WriteLine(String)
IN0013: 000070 call Console:ReadLine():String
IN0014: 000075 nop
G_M59663_IG03: ; offs=000076H, size=0005H, bbWeight=1 PerfScore 1.25, epilog, nogc, extend
IN0016: 000076 add rsp, 40
IN0017: 00007A ret
Как видно — в данном простом случае — JIT справился более чем отлично. Понятно, что это не совсем универсально (в случае если JIT откажется инлайнить — то будет уже совсем не всё так красиво ).
Re[2]: Сделал так
Здравствуйте, igor-booch, Вы писали:
IB>Всем спасибо, c рефлешеном, понятно, что можно всё, но производительность страдает,
IB>пока сделал так
С точки зрения производительности, не смотря, что такой паттерн не очень красивый (и имеет свои ограничения), — похожие паттерны уже распознаются JIT.
Ну, например:
Такой метод будет раскрываться в GetIntValue/GetDoubleValue/GetStringValue как будто никакого generic метода и нет вовсе, и т.к. T заранее известен — цепочка боксинга/анбоксинга так же подавляется, даже в Debug билдах.
--
С методом "public static void Do<TClass>(TClass @object) where TClass : IBase" немного иначе — в виду того, что на сегодня есть только фич-реквесты для раздельной компиляции специализаций. Тем не менее если метод Do<TClass> заставить инлайнится — то результат будет так же хорошим.
В частности с хинтом AggressiveInlining на Do и AggressiveOptimization на Main (не уверен что они нужны), метод Main примет форму (испытано на .net 5):
Как видно — в данном простом случае — JIT справился более чем отлично. Понятно, что это не совсем универсально (в случае если JIT откажется инлайнить — то будет уже совсем не всё так красиво ).
PS: Я имел ввиду, что с точки зрения производительности — на сегодня это один из самых простых и многообещающих способов. С другой стороны рефлексия + кеширование имеет стабильно предсказуемый результат в отличии от закидонов JIT.
IB>Всем спасибо, c рефлешеном, понятно, что можно всё, но производительность страдает,
IB>пока сделал так
С точки зрения производительности, не смотря, что такой паттерн не очень красивый (и имеет свои ограничения), — похожие паттерны уже распознаются JIT.
Ну, например:
public T GetValue<T>() {
if (typeof(T) == typeof(int)) {
return (T)(object)GetIntValue();
}
else if (typeof(T) == typeof(double)) {
return (T)(object)GetDoubleValue();
}
else if (typeof(T) == typeof(string)) {
return (T)(object)GetStringValue();
}
else throw new InvalidOperationException();
}
Такой метод будет раскрываться в GetIntValue/GetDoubleValue/GetStringValue как будто никакого generic метода и нет вовсе, и т.к. T заранее известен — цепочка боксинга/анбоксинга так же подавляется, даже в Debug билдах.
--
С методом "public static void Do<TClass>(TClass @object) where TClass : IBase" немного иначе — в виду того, что на сегодня есть только фич-реквесты для раздельной компиляции специализаций. Тем не менее если метод Do<TClass> заставить инлайнится — то результат будет так же хорошим.
В частности с хинтом AggressiveInlining на Do и AggressiveOptimization на Main (не уверен что они нужны), метод Main примет форму (испытано на .net 5):
IN0015: 000000 sub rsp, 40
G_M59663_IG02: ; offs=000004H, size=0072H, bbWeight=1 PerfScore 20.75, gcrefRegs=00000000 {}, byrefRegs=00000000 {}, byref
IN0001: 000004 mov rcx, 0x257900030B8
IN0002: 00000E mov rcx, gword ptr [rcx]
IN0003: 000011 call Console:WriteLine(String)
IN0004: 000016 mov rcx, 0x257900030C0
IN0005: 000020 mov rcx, gword ptr [rcx]
IN0006: 000023 call Console:WriteLine(String)
IN0007: 000028 mov rcx, 0x257900030C8
IN0008: 000032 mov rcx, gword ptr [rcx]
IN0009: 000035 call Console:WriteLine(String)
IN000a: 00003A mov rcx, 0x257900030B8
IN000b: 000044 mov rcx, gword ptr [rcx]
IN000c: 000047 call Console:WriteLine(String)
IN000d: 00004C mov rcx, 0x257900030C0
IN000e: 000056 mov rcx, gword ptr [rcx]
IN000f: 000059 call Console:WriteLine(String)
IN0010: 00005E mov rcx, 0x257900030C8
IN0011: 000068 mov rcx, gword ptr [rcx]
IN0012: 00006B call Console:WriteLine(String)
IN0013: 000070 call Console:ReadLine():String
IN0014: 000075 nop
G_M59663_IG03: ; offs=000076H, size=0005H, bbWeight=1 PerfScore 1.25, epilog, nogc, extend
IN0016: 000076 add rsp, 40
IN0017: 00007A ret
Как видно — в данном простом случае — JIT справился более чем отлично. Понятно, что это не совсем универсально (в случае если JIT откажется инлайнить — то будет уже совсем не всё так красиво ).
PS: Я имел ввиду, что с точки зрения производительности — на сегодня это один из самых простых и многообещающих способов. С другой стороны рефлексия + кеширование имеет стабильно предсказуемый результат в отличии от закидонов JIT.