Re[51]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 10.09.21 18:08
Оценка: 2 (1)
Здравствуйте, Sinclair, Вы писали:

S>Попробовал на шарплабе — неа, не хочет инлайнить:


У меня заинлайнил BranchNode.this[int index]:
https://sharplab.io/#v2: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=

Span не стоит создавать в цикле.
Re[17]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: alex_public  
Дата: 10.09.21 18:28
Оценка:
Здравствуйте, vfedosov, Вы писали:

V>Я уже в разработке 20 лет и мне не нужно "верить" — я знаю, что типизация нужна. Но для нетривиальных решений. Для описанного скрипта она нахрен не нужна. Она не везде нужна даже в больших проектах. Если у тебя 2 приватные функи объявлены рядом в коде и первая вызывает вторую и ты уверен, что вторая больше никогда не потребуется, то можно обойтись без типизации — ты ничего потеряешь. Проверено многократно. Типизация внутри функции мне также не дает ничего — в основном чисто мусор. Типы ясны из контекста — за редким исключением. Безусловно полезна типизация интерфейсов — особенно на уровне классов, которые доступны из других модулей. Тут вообще без нее никак — иначе проект скатывается в гавно влет. Короче, у любого инструмента есть границы полезности. Для одних проектов хороший инструмент — Шарп, для других Пайтон. Те кто утверждает, что Шарп везде лучше — фанатики. Так же как и те, кто утверждает подобное про Пайтон. Я бы сказал, что пока нет единого языка для всех целей — да он и не факт, что возможен.


Более интересен тот факт, что Питон является пожалуй единственным популярным языком, которому пока не нашли замену.

Если посмотреть на нашу индустрию лет 10 назад, то тогда было ровно 4 (ну я там два похожих за один считаю) важных языка, которые имело смысл изучать. Причём для профессиональной работы было достаточно знания одного из них:

1. C/C++ — для всего инфраструктурного или требовательного к ресурсам ПО.
2. Java/C# — для так называемого энтерпрайза (ключевое требование: чтобы и обезьяна могла написать безопасный код)
3. JavaScript — для веб-фронтенда (думаю не надо уточнять, по каким причинам это Г... заняло всю эту нишу)
4. Python — для автоматизации (всякие там админские и т.п. скрипты), веб-бэкенда, научных/инженерных/аналитических рассчётов.

Да, помимо этого настоящий профессионал должен знать ещё и всяческие не мейнстримовые языки (Лисп, Пролог, Хаскель и т.п.), для развития своего понимания разных подходов к проектированию. И так же в различных областях имеются десятки необходимых для изучения DSL'е (типа HTML, SQL и т.п.), которые тоже необходимо знать. Но это всё является лишь дополнением к хорошему знанию основного инструмента.

Всё выше сказанное — это естественно исключительно моё субъективное видение (хотя оно и хорошо коррелирует с такими источниками, как TIOBE и т.п.). Однако я думаю, что большинство даже на этом специфическом форуме согласится с этой картиной.

Так вот, если взглянуть на эту же область сейчас (в 2021-ом году), то мы увидим, что опять есть ровно 4 языка, занимающие точно такие же ниши (что впрочем не удивительно, т.к. ниши диктуются фундаментальными запросами человечества, а не модой в IT) как и 10 лет назад. Только вот сами языки эти стали совсем другими (речь естественно о выборе языка для нового проекта, т.к. гигабайты легаси написанного на языках из списка выше будут с нами ещё много десятилетий и количество вакансий по ним ещё долго будут опережать все современные языки). Трансформация языков в указанных нишах выглядит так:

C/C++ -> Rust
Java/C# -> Go
JavaScript -> TypeScript
Python -> Python

Каждый из этих языков улучшает ключевую характеристику своего предшественника. Rust — может всё тоже, что и C++, но снижает завышенный уровень квалификации, требующийся для написания безопасного кода. Go — ещё намного проще чем Java и при это одновременно имеет меньше накладных расходов и проблем с развёртыванием. TypeScript пытается сделать из мира-помойки JS что-то похожее на нормальное программирование, хотя не уверен, что такое возможно в принципе.

Частично по этому (хотя были и другие причины) языки уже не столь разделены по нишам. Rust стал хорошо себя чувствовать в веб-фронтенде (когда-то эксклюзивной ниши JS), Go часто используют для написания системных утилит (т.к. в отличие от Java/C# для этого можно просто кинуть один бинарник, как когда-то делали с питон/перл скриптами), JS/TS стал хорошо себя чувствовать в бэкенде. Но это всё так сказать не основные направления использования этих базовых современных языков.

И только древнющему Питону так и не нашлась современная замена. Одно время были надежды на язык Julia. Но время показало, что это получился просто бесплатный и опенсорсный вариант Матлаба, который способен заменить Питон только в одной очень узкой области (и то этого скорее всего не произойдёт, т.к. будет сказываться "давление" остальной индустрии). Более того, за эти 10 лет, Питон только нарастил популярность (в основном за счёт бурного развития "его области" аналитических вычислений, которую сейчас принято называть Data Science). И на горизонте не видно вообще никаких потенциальных его заменителей.

Вот это действительно очень примечательный факт. Хотя и не скажу что позитивный — я бы предпочёл иметь на примете какого-то модного потенциального заменителя Питона, потому как улучшать в Питоне вообще то можно очень много чего.
Re[51]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 10.09.21 18:39
Оценка:
Здравствуйте, Sinclair, Вы писали:

Вариант на FindChildV, который немного подшаманил.

https://sharplab.io/#v2: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

Где только возможно стоит использовать readonly-модификатор метода, ReadOnlySpan.
Одно плохо, кривая сигнатура MemoryMarshal.CreateReadOnlySpan:
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ReadOnlySpan<T> CreateReadOnlySpan<T>(ref T reference, int length) => new ReadOnlySpan<T>(ref reference, length);

Должно было быть так:
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static ReadOnlySpan<T> CreateReadOnlySpan<T>(in T reference, int length) => new ReadOnlySpan<T>(Unsafe.AsRef(reference), length);


Потому что в readonly-методах приходится делать так:
internal readonly ReadOnlySpan<Box<N, T>> Children => MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(_children._data0), _childrenCount);


Что лечится своим каким-нить хелпером
public static SpanHelper {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ReadOnlySpan<T> CreateReadOnlySpan<T>(in T reference, int length) => MemoryMarshal.CreateReadOnlySpan(Unsafe.AsRef(reference), length);
}


readonly ref модификатор "in" можно опускать, что делает код чище:
int data = 42;
var span = SpanHelper.CreateReadOnlySpan(data, 1);
Отредактировано 10.09.2021 19:14 vdimas . Предыдущая версия . Еще …
Отредактировано 10.09.2021 18:40 vdimas . Предыдущая версия .
Re[52]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 10.09.21 19:14
Оценка:
Здравствуйте, vdimas, Вы писали:

Интереса ради разобрал ассемблер по ссылке:
// выделили память на стеке (что-то дохрена)
    L0000: sub rsp, 0x28

// в rcx пришло this
// rax=_indicies.Pointer (i.e. Bunch<int>._data0)
    L0004: lea rax, [rcx+8]

// r8d = _indicies.Length
    L0008: mov r8d, [rcx]

// for(i = 0;
    L000b: xor r9d, r9d
    L000e: jmp short L0013

// ===================== начало цикла ==============
// i++
    L0010: inc r9d

//  ? i < indices.Length
    L0013: cmp r9d, r8d

// выход из цикла по i==indicies.Length
    L0016: jge short L0021

// лишнее преобразование... всё-таки, в x64 Span.Length должно быть int64, т.е. nint.
    L0018: movsxd r10, r9d

// ? indices[i] <= index
// здесь соптимизирована проверка выхода за границы при вызове indices[i]
    L001b: cmp [rax+r10*4], edx

// зацикливание 
    L001f: jle short L0010
// =================== конец цикла ===================

// return (Children[i], i > 0 ? index - indices[i - 1] : index);    L0021: lea r10, [rcx+0x48]
    // r10=_children.Pointer
    L0021: lea r10, [rcx+0x48]

//  ecx = indices.Length (хотя, это значение сидит в r8d)
    L0025: mov ecx, [rcx]

// проверили выход за массив Children[i]
    L0027: cmp r9d, ecx
    L002a: jae short L005f

// rcx=Childer[i]
    L002c: movsxd rcx, r9d
    L002f: mov rcx, [r10+rcx*8]

// ? i > 0
    L0033: test r9d, r9d
    L0036: jg short L003a
    L0038: jmp short L004e

// r10d = i-1
    L003a: lea r10d, [r9-1]

// проверка выхода за диапазон indices[i - 1] (как глупо)
    L003e: cmp r10d, r8d
    L0041: jae short L005f

// r8 = i-1 (опять?)
    L0043: lea r8d, [r9-1]
    L0047: movsxd r8, r8d

// index - indices[i - 1]
    L004a: sub edx, [rax+r8*4]

// return t.Node[i]
    L004e: cmp [rcx], ecx
    L0050: add rcx, 8
    L0054: call BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_Item(Int32)
    L0059: nop
    L005a: add rsp, 0x28
    L005e: ret

// выброс IndexOutOfRangeException
    L005f: call 0x00007ffb4bfba5e0
    L0064: int3


Целевой цикл вылизан по самое нимогу.
Остальное с огрехами.
Re[65]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 11.09.21 01:23
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

I>>Более того, с наследованием интерфейсов ровно те же проблемы.

НС>Проблем с высокой зависимостью наследника от предка там нет.

Никто не запрещает использовать эту технику прямо сейчас.
Особенно когда в интерфейсы ввели дефолтную реализацию, а до этого снабдили язык методами-расширениями.
Re[52]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.09.21 01:27
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Sinclair, Вы писали:


S>>Попробовал на шарплабе — неа, не хочет инлайнить:


V>У меня заинлайнил BranchNode.this[int index]:

Не вижу. По ссылке он выглядит так:
    BranchNode`2[[BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_Item(Int32)
    L0000: sub rsp, 0x28
    L0004: lea rax, [rcx+8]
    L0008: mov r8d, [rcx]
    L000b: xor r9d, r9d
    L000e: jmp short L0013
    L0010: inc r9d
    L0013: cmp r9d, r8d
    L0016: jge short L0021
    L0018: movsxd r10, r9d
    L001b: cmp [rax+r10*4], edx
    L001f: jle short L0010
    L0021: lea r10, [rcx+0x48]
    L0025: mov ecx, [rcx]
    L0027: cmp r9d, ecx
    L002a: jae short L005f
    L002c: movsxd rcx, r9d
    L002f: mov rcx, [r10+rcx*8]
    L0033: test r9d, r9d
    L0036: jg short L003a
    L0038: jmp short L004e
    L003a: lea r10d, [r9-1]
    L003e: cmp r10d, r8d
    L0041: jae short L005f
    L0043: lea r8d, [r9-1]
    L0047: movsxd r8, r8d
    L004a: sub edx, [rax+r8*4]
    L004e: cmp [rcx], ecx
    L0050: add rcx, 8
    L0054: call BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_Item(Int32)
    L0059: nop
    L005a: add rsp, 0x28
    L005e: ret
    L005f: call 0x00007ffb4bfba5e0
    L0064: int3
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[52]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.09.21 01:28
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Sinclair, Вы писали:


V>Вариант на FindChildV, который немного подшаманил.


Тоже не лучше — много вызовов в this[int]:
BranchNode`2[[BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_Item(Int32)
    L0000: push rdi
    L0001: push rsi
    L0002: sub rsp, 0x78
    L0006: vzeroupper
    L0009: vmovaps [rsp+0x60], xmm6
    L000f: vmovaps [rsp+0x50], xmm7
    L0015: xor eax, eax
    L0017: mov [rsp+0x28], rax
    L001c: vxorps xmm4, xmm4, xmm4
    L0020: vmovdqa [rsp+0x30], xmm4
    L0026: vmovdqa [rsp+0x40], xmm4
    L002c: mov rsi, rcx
    L002f: mov [rsp+0x38], edx
    L0033: vmovd xmm0, [rsp+0x38]
    L0039: vpbroadcastd ymm6, xmm0
    L003e: xor edi, edi
    L0040: lea rdx, [rsp+0x28]
    L0045: mov rcx, rsi
    L0048: vextractf128 xmm7, ymm6, 1
    L004e: call BranchNode`2[[BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_VectorIndices()
    L0053: xor r8d, r8d
    L0056: cmp dword ptr [rsp+0x30], 0
    L005b: vinsertf128 ymm6, ymm6, xmm7, 1
    L0061: jle short L00a4
    L0063: mov r9, [rsp+0x28]
    L0068: movsxd rcx, r8d
    L006b: shl rcx, 5
    L006f: vmovupd ymm0, [r9+rcx]
    L0075: vpcmpgtd ymm0, ymm0, ymm6
    L0079: vmovmskps r9d, ymm0
    L007d: or r9d, 0xffffff00
    L0084: tzcnt r9d, r9d
    L0089: lea eax, [rdi+r9]
    L008d: cmp eax, [rsi]
    L008f: jge short L00be
    L0091: cmp r9d, 8
    L0095: jl short L00d8
    L0097: add edi, 8
    L009a: inc r8d
    L009d: cmp r8d, [rsp+0x30]
    L00a2: jl short L0063
    L00a4: mov r8d, [rsi]
    L00a7: dec r8d
    L00aa: lea r9, [rsp+0x38]
    L00af: lea rcx, [rsp+0x40]
    L00b4: mov rdx, rsi
    L00b7: call BranchNode`2[[BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].<FindChildV>g__Return|14_0(BranchNode`2<BranchNode`2<LeafNode`1<Int32>,Int32>,Int32> ByRef, Int32, <>c__DisplayClass14_0<BranchNode`2<LeafNode`1<Int32>,Int32>,Int32> ByRef)
    L00bc: jmp short L00ed
    L00be: mov r8d, [rsi]
    L00c1: dec r8d
    L00c4: lea r9, [rsp+0x38]
    L00c9: lea rcx, [rsp+0x40]
    L00ce: mov rdx, rsi
    L00d1: call BranchNode`2[[BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].<FindChildV>g__Return|14_0(BranchNode`2<BranchNode`2<LeafNode`1<Int32>,Int32>,Int32> ByRef, Int32, <>c__DisplayClass14_0<BranchNode`2<LeafNode`1<Int32>,Int32>,Int32> ByRef)
    L00d6: jmp short L00ed
    L00d8: lea rcx, [rsp+0x40]
    L00dd: lea r9, [rsp+0x38]
    L00e2: mov rdx, rsi
    L00e5: mov r8d, eax
    L00e8: call BranchNode`2[[BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].<FindChildV>g__Return|14_0(BranchNode`2<BranchNode`2<LeafNode`1<Int32>,Int32>,Int32> ByRef, Int32, <>c__DisplayClass14_0<BranchNode`2<LeafNode`1<Int32>,Int32>,Int32> ByRef)
    L00ed: mov rcx, [rsp+0x40]
    L00f2: mov edx, [rsp+0x48]
    L00f6: cmp [rcx], ecx
    L00f8: add rcx, 8
    L00fc: call BranchNode`2[[LeafNode`1[[System.Int32, System.Private.CoreLib]], _],[System.Int32, System.Private.CoreLib]].get_Item(Int32)
    L0101: nop
    L0102: vmovaps xmm6, [rsp+0x60]
    L0108: vmovaps xmm7, [rsp+0x50]
    L010e: vzeroupper
    L0111: add rsp, 0x78
    L0115: pop rsi
    L0116: pop rdi
    L0117: ret
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[65]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.09.21 01:38
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Это как примерно описывается в АПИ различных ОС всякие union.

Да, ясно. Хороший трюк.
И вообще, надо этот Pointer<T> взять на вооружение. В Linq2d мне приходится генерировать MSIL руками во многом потому, что не получается породить Expression<Func<int*>>.
При использовании Pointer<T> есть шанс вернуться к Expression, и использовать альтернативные компиляторы их в MSIL для ускорения.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[53]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.09.21 02:19
Оценка:
Здравствуйте, 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.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[52]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.09.21 04:33
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Где только возможно стоит использовать readonly-модификатор метода, ReadOnlySpan.

А зачем? Это внутренний код, я и так могу убедиться, что я при поиске индексы не меняю.

Кажется, я понял, в чём дело. JIT отказывается инлайнить рекурсию.
Если посмотреть на BranchNode<LeafNode<int>, int>.getItem(), то там всё в порядке — всё инлайнится, как и ожидалось.
А вот когда JIT видит внутри BranchNode<LeafNode<int>, int>.getItem()
IL_001b: constrained. !N
IL_0021: callvirt instance !0 class IListNodeBase`1<!T>::get_Item(int32)

и понимает, что N::get_Item — это тоже BranchNode<..., ...>::get_Item, то несмотря на то, что это совсем другой метод, джит решает "ой, не, это рекурсия — её инлайнить бесполезно".

Надо бы найти это место в исходниках JIT и посмотреть, можно ли доработать детектор рекурсии.
Варианты, как это обойти, не фикся джит:
— вернуться к варианту с циклом. Он, в целом, был хорош всем, кроме однотипности узлов. В итоге у меня внутри листьев тратилось место на индексы, увеличивая потребление памяти, и ухудшая характеристики всех модифицирующих операций.
— развернуть рекурсию, добавив 2-3-4 типа BranchNode1, BranchNode2, которые будут отличаться только методом SplitNGrow. Тогда медленный код будет вызываться только при очень больших глубинах дерева (например, миллион элементов требуют всего-то 4х уровней).
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[66]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 11.09.21 05:57
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Никто не запрещает использовать эту технику прямо сейчас.


Да я и не спорю. Я наоборот, рядом говорю что, по факту, у нас ее особо никто и не использует. Ну, покуда используемые библиотеки это позволяют. А они, к счастью, в 2021 году почти всегда позволяют.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[63]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 11.09.21 08:47
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Например в Rust'е нет наследования в классическом его понимание. И при этом полезный код отлично пишется.


_>Наследование применяют для двух целей: полиморфизма и переиспользования кода. Для обеих этих целей в Rust'е есть отдельные инструменты.


Это и есть причины проблем с наследованием Наследование это механизм моделирования отношения is, то есть, subtype. А вот если городить наследование ради переиспользования и полиморфизма, то начинается "адъ и израиль".
Скажем, та же композиция дает гораздо лучший результат при переиспользовании. Более того, переиспользовать можно вообще безо всякого наследования и даже композиции.
Re[65]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 11.09.21 09:05
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

I>>Интерфейсы это слабенько.


НС>Для полиморфизма — более чем достаточно.


Недостаточно, т.к. интерфейс не предоставляет никаких гарантий. Алгебраические типы данных поддерживаются языками которые в мейнстриме не летают. Абстрактные типы данных ровно так же в мейнстриме не летают. То есть, все гарантии обеспечиваешь руками.
И когда некто понаимплементит в одном классе кучку интерфейсов, уследить за свойствами этого решения становится, мягко говоря, проблематично.

I>>Обычно проблемы возникают не с самой связью is, а с реализацией композиции через наследование


НС>Именно.


Ты меняешь показания:
"использование is для логики — та еще кака".

I>>Более того, с наследованием интерфейсов ровно те же проблемы.

НС>Проблем с высокой зависимостью наследника от предка там нет.

Непонятно. Приведи пример для отношения is, subtype то есть.

I>> или так — понареализовывает в классе целую кучу интерфейсов — мутебальных и иммутабельных. Вроде бы наследование нет, но проблемы ровно те же


НС>Какие?


Ломаются гарантии. Ты получил ссылку с типом иммутабельного интерфейса и твой код полагается на это свойство иммутабельности. Например, тебе удобно сравнивать объекты по ссылке ради экономии времени.
Но штука в том, что класс реализовывает дочерний интерфейс, который мутабельный, а значит тебе нельзя полагаться на свойство иммутабельности.
То есть, на самом деле нельзя порождать интерфейсы, которые нарушают свойства предков. А раз так, то у нас и для интерфейсов остаётся тот самый is или subtype.

I>>, как будто оно есть Отсюда ясно, что дело не в наследовании.


НС>Не знаю что тебе ясно, но логика "раз мы не можем отловить всех воров, то вообще их ловить не будем" так себе.


А у тебя выбора нет, т.к. в языках отсутствует проверка внятных гарантий. А это значит, что стоит учитывать такое положение дел при разработке иерархии классов.
То есть, не полагаться на мифические интерфейсы, а явно прописывать гарантии в базовом классе.

>Есть вполне кокретная проблема очень сильной связи между предком и потомком, и ее интерфейсы устраняют. А проблемы иерархического полиморфизма в ОО в целом, разумеется, можно устранить только отказом от такого полиморфизма.


Нужно заменить extends на subtype и все станет хорошо.
Re[67]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.09.21 09:46
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, vdimas, Вы писали:


V>>Никто не запрещает использовать эту технику прямо сейчас.


НС>Да я и не спорю. Я наоборот, рядом говорю что, по факту, у нас ее особо никто и не использует. Ну, покуда используемые библиотеки это позволяют. А они, к счастью, в 2021 году почти всегда позволяют.


Я сам предпочитаю интерфейсы. Но есть куча функционала который есть в базовом классе, наследники наследуют полностью или частично корректируют поведения вызывая внутри base.
И очень редко полностью переопределяют.
Просто лучше делать самый базовый класс полностью абстрактным. А то лезешь в реализацию видишь код, но это не тот код.
И суть полностью абстракного класса это и есть интерфейс
и солнце б утром не вставало, когда бы не было меня
Re[68]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 11.09.21 14:04
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Но есть куча функционала который есть в базовом классе,


Например?

S> Просто лучше делать самый базовый класс полностью абстрактным.


Почему тогда не сделать его интерфейсом?

S>И суть полностью абстракного класса это и есть интерфейс


Но мы сделаем его классом, чтобы никто не догадался?
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[66]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 11.09.21 14:04
Оценка:
Здравствуйте, Ikemefula, Вы писали:

НС>>Для полиморфизма — более чем достаточно.

I>Недостаточно, т.к. интерфейс не предоставляет никаких гарантий.

Вообще никаких? К чему эта софистика? Очевидно что какие то гарантии он дает, но иммутабельность в этот список не входит.

I>Алгебраические типы данных поддерживаются языками которые в мейнстриме не летают.


Это пока. Хотя вон F# почти мейнстрим.

I>И когда некто понаимплементит в одном классе кучку интерфейсов, уследить за свойствами этого решения становится, мягко говоря, проблематично.


У любой технологии есть свои недостатки. Вывод то какой? Не использовать ООП?

I>>>Более того, с наследованием интерфейсов ровно те же проблемы.

НС>>Проблем с высокой зависимостью наследника от предка там нет.
I>Непонятно. Приведи пример для отношения is, subtype то есть.

Зачем мне приводить какой то пример? Тебюе без примера непонятно, что связь базовый класс — наследник намного сильнее, чем интерфейс — реализация?

I>>> или так — понареализовывает в классе целую кучу интерфейсов — мутебальных и иммутабельных. Вроде бы наследование нет, но проблемы ровно те же

НС>>Какие?
I>Ломаются гарантии. Ты получил ссылку с типом иммутабельного интерфейса и твой код полагается на это свойство иммутабельности.

С чего бы? Гарантию иммутабельности ООП в принципе никогда не давал и не дает, хоть с интерфейсами, хоть без. Можно, конечно, что нибудь придумать, но я тогда тебя спрошу — а что насчет какой нибудь другой гарантии? Например, гарантии времени выполнения или гарантии по объему потребляемой памяти, да даже проще — гарантий на диапазон возвращаемых значений или даже на отсутствие там null. Очевидно, что абсолютных гарантий тебе никто не даст, но отсутствие гарантии иммутабельности это далеко не единственный и даже не главный недостаток наследования классов.

НС>>Не знаю что тебе ясно, но логика "раз мы не можем отловить всех воров, то вообще их ловить не будем" так себе.

I>А у тебя выбора нет,

У меня выбор есть

I> т.к. в языках отсутствует проверка внятных гарантий.


А внятными гарантии кто назначает?

I>Нужно заменить extends на subtype и все станет хорошо.


Нет, все не станет.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[69]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.09.21 16:42
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, Serginio1, Вы писали:


S>>Но есть куча функционала который есть в базовом классе,


НС>Например?

Да примеров куча в прикладном коде.
Ну или хотя бы те же Control или wpf https://professorweb.ru/my/WPF/base_WPF/level1/1_7.php
S>> Просто лучше делать самый базовый класс полностью абстрактным.

НС>Почему тогда не сделать его интерфейсом?


S>>И суть полностью абстрактного класса это и есть интерфейс


НС>Но мы сделаем его классом, чтобы никто не догадался?

Нет, что бы сделать наследника реализующий основные методы, а на базе его сделать иерархию, что бы не писать лишний код.
Конечно можно посмотреть на override или virtual но это не сразу в глаза бросается, а абстрактный без кода сразу виден.
Можно посмотреть реализацию и увидеть все возможные реализации.

Еще раз есть куча функционала который есть в базовом классе, наследники наследуют полностью или частично корректируют поведения вызывая внутри base.
И чем в данном случае лучше интерфейсы?
и солнце б утром не вставало, когда бы не было меня
Re[54]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 11.09.21 17:52
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>L0054 убивает всю производительность.


А там разве не рекурсия?
(руки не дошли взять полный код, пока справшиваю словами)

Если рекурсия, то вполне нормально по-максимому заинлайнить тело рекурсивного метода.

Или тебе хотелось автоматического преобразования рекурсии в цикл?
В крайнем случае это можно сделать ручками, но при малой фактической вложенности (единицы десятков, те самые 20-30 максимум) смысла обычно нет.

И да, я когда-то более 15 лет назад сравнивал бинарные деревья с N-арными, ну вот 2-4 элемента в узле давали максимум производительности, т.е. увеличение кол-ва элементов в узле ничего не давало. Гораздо больше дал кастомный аллокатор узлов, но вряд ли это поможет в случае дотнета.

Еще на малой арности эффективно работает балансировка дерева.
(Кстате, не увидел у тебя балансировки, но может не весь код смотрел)

Еще, если заменить в твоей реализации _dataX на inplace-массив, то через одну константу арности можно легко менять кол-во элементов в узле, т.е. задешево сравнить сетку реализаций с отличающейся арностью.

Еще из этой области — когда-то сравнивал различные принципы построения хеш-таблиц:
— хеш-таблица в хеш-таблице (т.е. любой конфликт оборачивается в хеш-таблицу следующего подуровня и т.д. рекурсивно, т.е. тоже получается дерево, просто большой арности узлов, и размер подтаблицы не может быть равен размеру родительской таблицы, т.е. это должно быть другое простое число);
— дефолтные реализации (занятие соседних пустых ячеек);
— в хеш-таблице по данному хеш-коду содержится первый элемент и опционально указатель на сортированный список остальных конфликтных элементов.

Последний вариант показал себя самым эффективным для большинства случаев.

Второй вариант для сравнимой эффективности требует большого запаса по размеру ячеек хеш-таблицы относительно данных, т.е. с приличным превышением.

Первый вариант оказался самый тормозной, хотя всё тестирование ради него затевалось, т.к. оно хорошо подходит под иммутабельные сценарии.
Самое время проверить еще раз этот вариант на актуальной технике и актуальных компиляторах-джитах, сравнить с честными деревьями, типа как у тебя.

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

Наполнение такой таблицы дорогое, т.к. в процессе наполнения происходит подбор коэфициентов хеш-функции для минимизации конфликтов.
Но зато при последующем чтении данных такие таблицы показывают хорошие результаты практически при любых сценариях, например даже в таких, где классические хеш-таблицы с фиксированными хеш-функциями из-за стечения обстоятельств (вернее, данных) вырождаются в своей эффективности до эффективности только механизма, разруливающего конфликты.
Т.е. когда классические (дефолтные) реализации хеш-таблиц де-факто профанируются.
Отредактировано 11.09.2021 18:00 vdimas . Предыдущая версия . Еще …
Отредактировано 11.09.2021 17:55 vdimas . Предыдущая версия .
Отредактировано 11.09.2021 17:52 vdimas . Предыдущая версия .
Re[70]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 11.09.21 17:55
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Ну или хотя бы те же Control или wpf


Т.е. нечто древнее как дерьмо мамонта. О чем и речь.

НС>>Но мы сделаем его классом, чтобы никто не догадался?

S> Нет, что бы сделать наследника реализующий основные методы, а на базе его сделать иерархию, что бы не писать лишний код.

Наследование — далеко не единственный способ сделать это. Есть, к примеру, паттерн Стратегия.

S>Еще раз есть куча функционала который есть в базовом классе


Еще раз — это особенности конкретного дизайна, а не нечто фундаментальное

S>, наследники наследуют полностью или частично корректируют поведения вызывая внутри base.

S>И чем в данном случае лучше интерфейсы?

Я пока не увидел никакого данного случая, одни общие слова.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[71]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.09.21 18:42
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

НС>Здравствуйте, Serginio1, Вы писали:


S>>Ну или хотя бы те же Control или wpf


НС>Т.е. нечто древнее как дерьмо мамонта. О чем и речь.


S>>, наследники наследуют полностью или частично корректируют поведения вызывая внутри base.

S>>И чем в данном случае лучше интерфейсы?

НС>Я пока не увидел никакого данного случая, одни общие слова.

Угу дерьмо манмонта ты так и не увидел?
Тот же Xamarin.Forms тоже мамонты?https://docs.microsoft.com/ru-ru/xamarin/xamarin-forms/internals/class-hierarchy-images/class-diagram-large.png#lightbox
Ты давай отвечай чем в данном случае интерфейсы лучше и паттерн стратегия.
В Delphi есть возможность объявить за реализацию класса свойство класса реализующего этот интерфейс (Implements).
https://www.delphiplus.org/programirovanie-v-srede-delphi-for-net/direktiva-implements.html
Но по сути это аналог множественного наследования в C++
Вот такая возможность с возможностью переопределения методов с возможностью вызова base была бы интересна/
Кстати с помощью Source Generator это легко сделать!
и солнце б утром не вставало, когда бы не было меня
Отредактировано 11.09.2021 19:00 Serginio1 . Предыдущая версия . Еще …
Отредактировано 11.09.2021 18:43 Serginio1 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.