Здравствуйте, vdimas, Вы писали:
V>И это не самый эффективный способ итерации по массивам и вообще по данным — не зря сейчас рекомендуют получать Span, и итерироваться уже по нему.
Вся разница итерации по массиву и span — это учет дополнительного смещения при считывании адреса элемента для случая с массивами, в span этого нет, потому что там уже сделана поправка на это.
add eax, [rdx+r10*4]
; vs
add eax, [rcx+r10*4+0x10]
^^^^^
А с учетом оптимизации
JIT: Enable strength reduction by default, в .NET 9 теперь разницы уже нет никакой.
Где для случая
public static int Sum_Array(int[] data)
{
var r = 0;
foreach (var v in data)
r += v;
return r;
}
public static int Sum_Span(Span<int> data)
{
var r = 0;
foreach (var v in data)
r += v;
return r;
}
JIT приводит код в такое представление:
public static int Sum_Array_Optimized(int[] data)
{
var r = 0;
var count = data.Length;
if (count > 0)
{
ref var p = ref MemoryMarshal.GetArrayDataReference(data);
for (; count != 0; p = ref Unsafe.Add(ref p, 1), count--)
r += p;
}
return r;
}
public static int Sum_Span_Optimized(Span<int> data)
{
var r = 0;
ref var p = ref MemoryMarshal.GetReference(data);
var count = data.Length;
for (; count != 0; p = ref Unsafe.Add(ref p, 1), count--)
r += p;
return r;
}
И получаем идентичный выхлоп для всех 4 случаев
Sample:Sum_Array(int[]):int
G_M000_IG01: ;; offset=0x0000
G_M000_IG02: ;; offset=0x0000
xor eax, eax
mov edx, dword ptr [rcx+0x08]
test edx, edx
jle SHORT G_M000_IG05
G_M000_IG03: ;; offset=0x0009
add rcx, 16
align [0 bytes for IG04]
G_M000_IG04: ;; offset=0x000D
add eax, dword ptr [rcx]
add rcx, 4
dec edx
jne SHORT G_M000_IG04
G_M000_IG05: ;; offset=0x0017
ret
; Total bytes of code 24
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>