Оптимизация путем работы с небезопасным программированием
Очень интересует ответы на некоторые вопросы:
- Правда ли, что если итерировать простой массив чисел и получать его элементы через индексацию немного не оптимизировано, чем получить указатель на этот массив и итерировать его игнорируя исключение
IndexOutOfRangeException(То есть, мы пропускаем некоторые проверки)
К примеру:
int[] array = new int[3] { 1, 2, 3 };
fixed (int* ptrValue = &array[0])
{
for (int iterator = 0; iterator < array.Length; iterator++)
Console.Write($"{*(iterator + ptrValue)} ");
}
- Какой код оптимизированнее и почему?
internal readonly struct ValueFirst<T>
{
internal readonly T[] _pointer;
public ValueFirst(T[] values)
{
_pointer = values;
}
public ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_pointer), (uint)index);
}
}
или
internal readonly struct ValueSecond<T>
{
internal readonly T[] _pointer;
public ValueSecond(T[] values)
{
_pointer = values;
}
public T this[int index]
{
get => _pointer[index];
}
}
Ответы (1 шт):
Автор решения: Qwer
→ Ссылка
Сложно ответить ибо "немного не оптимизировано" понятие расплывчатое. Оптимизация должна быть уместной, и думать о ней стоит ТОЛЬКО когда упёрлись в неприемлемую производительность программы.
Здесь поможет ответить BenchmarkDotNet, но, учитывая что индексатор в ValueFirst по сути транслируется в это:
IL_0000: ldarg.0 IL_0001: ldfld !0[] valuetype ValueFirst`1<!T>::_pointer IL_0006: call !!0& [System.Memory]System.Runtime.InteropServices.MemoryMarshal::GetArrayDataReference<!T>(!!0[]) IL_000b: ldarg.1 IL_000c: conv.u IL_000d: call !!0& [System.Runtime]System.Runtime.CompilerServices.Unsafe::Add<!T>(!!0&, native uint) IL_0012: ret
а индексатор в ValueSecond в это:
IL_0000: ldarg.0
IL_0001: ldfld !0[] valuetype ValueSecond`1<!T>::_pointer
IL_0006: ldarg.1
IL_0007: ldelem !T
IL_000c: ret
предположу, что 2-й вариант будет работать быстрее, так как в нём нет вызовов методов.