Здравствуйте, vdimas, Вы писали:
V>Здравствуйте, vdimas, Вы писали:
V>Интереса ради разобрал ассемблер по ссылке:
V>V>// выделили память на стеке (что-то дохрена)
V> L0000: sub rsp, 0x28
V>// в rcx пришло this
V>// rax=_indicies.Pointer (i.e. Bunch<int>._data0)
V> L0004: lea rax, [rcx+8]
V>// r8d = _indicies.Length
V> L0008: mov r8d, [rcx]
V>// for(i = 0;
V> L000b: xor r9d, r9d
V> L000e: jmp short L0013
V>// ===================== начало цикла ==============
V>// i++
V> L0010: inc r9d
V>// ? i < indices.Length
V> L0013: cmp r9d, r8d
V>// выход из цикла по i==indicies.Length
V> L0016: jge short L0021
V>// лишнее преобразование... всё-таки, в x64 Span.Length должно быть int64, т.е. nint.
V> L0018: movsxd r10, r9d
V>// ? indices[i] <= index
V>// здесь соптимизирована проверка выхода за границы при вызове indices[i]
V> L001b: cmp [rax+r10*4], edx
V>// зацикливание
V> L001f: jle short L0010
V>// =================== конец цикла ===================
V>// return (Children[i], i > 0 ? index - indices[i - 1] : index); L0021: lea r10, [rcx+0x48]
V> // r10=_children.Pointer
V> L0021: lea r10, [rcx+0x48]
V>// ecx = indices.Length (хотя, это значение сидит в r8d)
V> L0025: mov ecx, [rcx]
V>// проверили выход за массив Children[i]
V> L0027: cmp r9d, ecx
V> L002a: jae short L005f
V>// rcx=Childer[i]
V> L002c: movsxd rcx, r9d
V> L002f: mov rcx, [r10+rcx*8]
V>// ? i > 0
V> L0033: test r9d, r9d
V> L0036: jg short L003a
V> L0038: jmp short L004e
V>// r10d = i-1
V> L003a: lea r10d, [r9-1]
V>// проверка выхода за диапазон indices[i - 1] (как глупо)
V> L003e: cmp r10d, r8d
V> L0041: jae short L005f
V>// r8 = i-1 (опять?)
V> L0043: lea r8d, [r9-1]
V> L0047: movsxd r8, r8d
V>// index - indices[i - 1]
V> L004a: sub edx, [rax+r8*4]
V>// return t.Node[i]
V> L004e: cmp [rcx], ecx
V> L0050: add rcx, 8
V> L0054: call BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_Item(Int32)
V> L0059: nop
V> L005a: add rsp, 0x28
V> L005e: ret
V>// выброс IndexOutOfRangeException
V> L005f: call 0x00007ffb4bfba5e0
V> L0064: int3
V>
V>Целевой цикл вылизан по самое нимогу.
V>Остальное с огрехами.
L0054 убивает всю производительность. В прошлой инкарнации этот метод был циклом c FindChild до тех пор, пока не дойдём до листа, и дети и индексы были массивами (+1 к косвенности), но при этом this[] работал быстрее, чем у штатного System.Collections.Immutable.ImmutableList.