Re[81]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 14.09.21 13:49
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

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


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


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

I>>Как забавно — ты снова переключился на другой пример, с иммутабельностью.

НС>Да пофик. Ты опять не понял что я написал.

Разумеется, мне непонятно и я прямо об этом говорю. И непонятно прежде всего потому, что ты соскочил на другой пример.

I>>Цитирую себя "пример про удаление элементов в методе add(который ты старательно "забываешь").


НС>Ты даже не дочитал сообщение до конца

НС>

НС>и чего ты там еще со своимм методом add


Еще раз — пример про add никакого отношения к иммутабельности не имеет.
Выглядит так, будто пример с иммутабельностью тебе не нравится, и другой пример, с add, тебе тоже не нравится.
Свой пример ты приводить отказываешься
И каким чудом мне понять тебя?

I>>Ты бы вместо доказательства попробовал внятно изложить свои мысли, слова пояснять примерами. Глядишь, стало бы понятнее.

НС>Мысль была изложена в самом начале. Не стоит пихать в структуры наследование, когда даже в классах с этим наследованием проблемы. Что тебе в этой простой мысли непонятно?

Всё непонятно — какие именно проблемы в классах. Сначала у тебя была проблемой связь is, а потом выяснилось, что не is, а эмуляция композиции. Что же ты имел ввиду — а хрен его знает.

>>Не надо сочинять — пример с add никакого отношения к иммутабельности не имеет.

НС>А я где то утверждал что имеет? Ты опять споришь с воображаемым собеседником.

Смотрим внимательно http://rsdn.org/forum/flame.comp/8090913.1
Автор: Ikemefula
Дата: 14.09.21

На мой взгляд, здесь ничего про иммутабельность нет, в явном виде речь про другой пример про очиству в методе add
Тем не менее, тебе мерещится именно иммутабельность — http://rsdn.org/forum/flame.comp/8091000.1
Автор: Ночной Смотрящий
Дата: 14.09.21


I>>Снова полезла телепатия.


НС>Нет, факты.


Покажи этот факт, где я пытаюсь чего то приписать тебе. Только не так, как впрошлый раз, где по ссылке был аргумент в мою пользу
Re[82]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ночной Смотрящий Россия  
Дата: 14.09.21 14:39
Оценка: -1
Здравствуйте, Ikemefula, Вы писали:

I>Еще раз — пример про add никакого отношения к иммутабельности не имеет.


Еще раз — ты с кем сейчас споришь?

I>Всё непонятно — какие именно проблемы в классах.


Я отвечал на этот вопрос в топике уже два раза. И даже ссылку потом из педивикии привел.

I>>>Снова полезла телепатия.

НС>>Нет, факты.
I>Покажи этот факт, где я пытаюсь чего то приписать тебе.

Да вот прям тут утверждаешь, что я, якобы, говорил что пример с add имеет отношение к иммутабельности.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[64]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 14.09.21 16:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

V>>Простого двоичного.

S>Смотря как организовано это простое двоичное дерево. Если в нём известны точные типы, то да.
S>А если там опять виртуальный вызов — то всё грустно.

В двоичном дереве все узлы одинаковые, т.е. виртуальность не нужна.


S>В версии с двоичным поиском мы выигрываем за счёт гарантий локальности кэша. То есть весь поиск с четырьмя ветвлениями происходит без какого-либо обмена с памятью; для случайно организованного двоичного дерева это не так.


Ну вот как раз джависты показывали, что после уплотнения GC узлы подобных объектов располагаются в памяти рядом, т.к. доступны по ссылкам только из родительских узлов, т.е. по мере естественного обхода ссылок выстроились в правильный порядок в памяти.


V>>Это еще один пункт к той моей идее, что арность узлов может расти (например, геометрически) при росте дерева вглубину, т.е. при большом кол-ве данных арность узлов-листьев будет расти.

V>>Это даст что-то O(log(log(N))
S>Нет, это не даст O(log(log(N)).

Да, наврал, независимо от арности узлов-веток по ним сложность сохраняется, выигрыш только в узлах-листьях.


V>>Например, арность корня может быть небольшой в той моей идее.

V>>Допустим даже 2.
V>>И всегда представлять из себя узел-ветку.
S>Это как раз будет убивать производительность на маленьких коллекциях.

Твои графики имеющейся дотнетной реализации показывают, что не будет.


V>>Вот тот "моноблочный" будет разный для разных глубин, если тебе удастся всё заинлайнить.

S>Совершенно верно. Это именно то, чего я хочу добиться.

Попробуй ввести разные типы (одинаковые внутри) сугубо для эксперимента.
Т.е. тип Node0 порождает Node1, далее Node2 и т.д., чтобы не было псевдорекурсии.

Т.е. рост дерева будет дороже, но можно будет замерить доступ по чтению (если успешно заинлайнится), т.е. чтобы понять — стоит ли вообще копать в эту сторону.


V>>Это понятно, потому что тип известен.

S>Да. И это не помогает — см. график.

Так непонятен график.
Он должен быть линейным в логарифмической шкале для имеющейся реализации.
Что такого может произойти на 256 элементах, что до него рост линейный, потом скачок, потом опять линейный рост?

Может, стоит внимательней взглянуть на происходящее в имеющемся коде?


V>>>>Хранить индекс в узле-ветке можно так, грубо:

V>>>>
V>>>>struct Cell {
V>>>>   int _index;
V>>>>   NodeBase _child;
V>>>>   delegate * <NodeBase, ref T> _getItem;
V>>>>}
V>>>>

S>>>Вот не запуская бенчмарки вижу — не взлетит.

V>>Почему?

S>Потому что не взлетает даже когда у нас "рекурсивный" вызов делается напрямую, по call CONST.

Ну ты же обогнал имеющуюся реализацию?


S>А вы предлагаете добавить косвенный вызов — который не будет предсказываться процессором.


Один косвенный вызов, в отличие от 5-ти для случая виртуального.
Косвенные вызовы тоже умеют обрабатываться предвыборкой до какой-то степени.


S>Плюс к этомк добавляем мелочи типа разрушения локальности индексов. Cell занимает 20 байт на x64, и наши index разбросаны в 320 байтах (если branchfactor == 16).


Ну, в твоей реализации индексы вынесены в отдельный bunch, что можно повторить и в этом случае.
Двоичное ветвление или линейный поиск происходит на индексах, которые в памяти рядом, а доступ к Cell (убрать оттуда поле index) происходит просто по смещению.
И там лишние 8 байт на Cell особой роли играть не будут.


V>>Красно-черный алгоритм.

S>Он же только для бинарных деревьев, разве нет?

Алгоритм можно расширить на n-арное дерево.
Считай, что твой 16-арный узел — это 8 по 2, но не принципиально, пусть там было бы не 16, а 17.
Алгоритм выявляет место, где требуется произвести поворот дерева.


V>>Но твои "игры" с арностью помогли, согласно графикам.

S>Нет. Хорошие графики получены на гомогенных деревьях. Там код this[] не выполнял вообще никаких вызовов:
S>https://github.com/evilguest/atropos/blob/c5d59b008e6da8dc202e816f5c9d3863c78e8b44/Atropos/ListNode.cs#L118-L126

Речь про арность.


V>>Что-то я на скорую руку не увидел графики, а можно повторить ссылку?

S>https://github.com/evilguest/atropos/blob/main/Atropos.Benchmarks/README.md

Запутал.
Тут показывает, что у тебя доступ по this[index] хуже:
https://github.com/evilguest/atropos/blob/main/Atropos.Benchmarks/Atropos.Benchmarks.List.IndexInt.png
И в других сценариях тоже.
Ранее ты показывал график, где твой код эффективней.
Re[66]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 14.09.21 16:11
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Ага, значит TypeHandle может быть как указателем на MethodTable, так и указателем на TypeDesc, в зависимости от типа объекта. Для массивов он указывает на TypeDesc. Тип object[][] — это массив, элементами которого являются object[], для которых TypeHandle=TypeDesc. Эта информация объясняет наш пример, но всё ещё остаются некоторые вопросы. Например: а как же отличить, на что именно указывает TypeHandle? Поможет нам в этом дальнейшее изучение исходников CLI:


S>Всё зависит от второго бита в адресе: нулевое значение определяет MethodTable, а единичное — TypeDesc. Если мы работаем с шестнадцатеричными адресами, то можно легко определить вид TypeHandle по последней цифре:


Это всё тебе потребуется, если ты ручками берёшь св-во TypeHandle.
Но компилятор не берёт ничего ручками, он берёт фиксированное смещение и ничего не делает с адресом VMT, т.е. не накладывает маску в попытке обнулить младший бит.
Re[67]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.09.21 16:16
Оценка:
Здравствуйте, vdimas, Вы писали:

S>>Всё зависит от второго бита в адресе: нулевое значение определяет MethodTable, а единичное — TypeDesc. Если мы работаем с шестнадцатеричными адресами, то можно легко определить вид TypeHandle по последней цифре:


V>Это всё тебе потребуется, если ты ручками берёшь св-во TypeHandle.

V>Но компилятор не берёт ничего ручками, он берёт фиксированное смещение и ничего не делает с адресом VMT, т.е. не накладывает маску в попытке обнулить младший бит.
То есть для массивов это TypeDesc, а для объектов это реальный VMT
и солнце б утром не вставало, когда бы не было меня
Re[83]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 14.09.21 16:30
Оценка:
Здравствуйте, Ночной Смотрящий, Вы писали:

I>>Еще раз — пример про add никакого отношения к иммутабельности не имеет.


НС>Еще раз — ты с кем сейчас споришь?


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

I>>Всё непонятно — какие именно проблемы в классах.


НС>Я отвечал на этот вопрос в топике уже два раза. И даже ссылку потом из педивикии привел.


Если честно, то невнятно как то: про is ты начал и бросил, про композицию начал и бросил, про полиморфизм тоже начал и бросил, сылка мягко говоря неудачная.
Что же, по твоему, гарантирует интерфейс мы так и не узнали, твоих примеров-пояснений не было

I>>Покажи этот факт, где я пытаюсь чего то приписать тебе.


НС>Да вот прям тут утверждаешь, что я, якобы, говорил что пример с add имеет отношение к иммутабельности.


Трудно понять что ты вообще говоришь. С моей точки зрения у тебя add как то связан с иммутабельностью, раз ты перескакиваешь с одного на другое. Например, в контексте про add ты притягиваешь иммутабельность. Читай сам:

Тебе показалось. То что я написал означало, что интерфейсы вполне достаточны для стандартного ОО полиморфизма. С чего ты решил что это утверждение относится и ко всяким интересным вещам типа иммутабельности — я без понятия. Поэтому мне совершенно не интересно доказывать тебе, что интерфейсов достаточно для гарантии иммутабельности и чего ты там еще со своимм методом add мне приписать пытаешься.


Более того, я тебе уже показал, почему я так думаю, цитирую себя:

Смотрим внимательно http://rsdn.org/forum/flame.comp/8090913.1


На мой взгляд, здесь ничего про иммутабельность нет, в явном виде речь про другой пример про очиству в методе add
Тем не менее, тебе мерещится именно иммутабельность — http://rsdn.org/forum/flame.comp/8091000.1
Автор: Ночной Смотрящий
Дата: 14.09.21

Похоже, мои объяснения тебя не устраивают, примеры — не устраивают, свои предоставлять отказываешья. Чего же ты продолжаешь писать сюда? Чего тебе неймется?
У меня, наприме, ООП и её поддержка в разных ЯП обе любимые темы. Вот я и строчку. А ты то чего стараешься, если пояснять, выяснять, приводить примеры тебе впадлу?
Re[74]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 14.09.21 17:13
Оценка:
Здравствуйте, Sinclair, Вы писали:

V>>А как вообще сюда напишешь расширение, если Expression порождает сам компилятор?

S>Вот так: https://github.com/bartdesmet/ExpressionFutures/tree/master/CSharpExpressions

Как я и сказал — переделывать сам компилятор:

the C# compiler changes required to support assignment of lambda expressions containing those language constructs to an Expression<TDelegate> is maintained separately in the ExpressionTrees branch of my Roslyn fork.



S>То есть сами Expression есть, а вот компилятор их порождать не умеет.


О чём и речь.
Потому что у меня изначально, еще с выходом Linq, появилась идея попробовать подставить свои Expression, типа как можно делать свой AsyncMethodBuilder, но я не нашёл как.

У меня были свои наработки по "работающему" AST, свои Add/Mul/Const и т.д.
Что-то вроде:
interface IOperation<TResult> 
{
    TResult Execute();
}

IBinaryOp<TLeft, TRight, TResult> : IOperation<TResult> 
    where TLeft : IOperation<TLeft>
    where TRight: IOperation<TRight>
{
    public TLeft Left {get;}
    public TRight Right {get;}
}

struct Const<T> : IOperation<T>
{
    public readonly T Value;
    public T Execute() => Value;
}

class Variable<T> : IOperation<T>
{
    public T Value;
    public readonly string Name;

    public T Execute() => Value;
}

struct AddIntOp<TLeft, TRight> : IBinaryOp<TLeft, TRight, int> 
    where TLeft : IOperation<int>
    where TRight: IOperation<int>
{
    public TLeft Left {get;}
    public TRight Right {get;}

    public int Execute() => Left.Execute() + Right.Execute();
}


Выражение с параметром
x + 42
порождает тип:
AddInt<Variable<int>, Const<int>>
Т.е. тоже пользовал тот факт, что джит для value-типов генерит уникальный код без боксинга.
Довольно шустро считало, кстате.


V>>Т.е. блоки для Expression нельзя.

S>Да, это хорошо известный факт. Мы это обсуждали в прошлый раз в ветке про linq2d.

Блоки содержатся в объектной иерархии Expression, просто не покрыты компилятором.
И еще много чего содержится, что не покрыто.


S>С точки зрения применения Expression Trees для разнообразной работы вроде "Давайте пользователь соберёт абстрактный pipeline обработки каких-то данных, а я из него сделаю монолитный эффективный метод без лишних аллокаций" это плохо.


Именно.


S>С точки зрения "я хочу писать Queryable Provider" это хорошо. Потому, что мне не нужно писать код для обработки случаев вроде

S>
S>from p in Person where {var s = new StringBuilder(); foreach(var ch in p.Name} if (p.IsLetterOrDigit) s.Append(ch); return s.ToString()=="John";} select p
S>


Но можно сделать так:
    internal record Person(string Name);

    private static bool MyPredicate(string name) {
        var s = new StringBuilder();

        foreach(var ch in name) {
            if(char.IsLetterOrDigit(ch))
                s.Append(ch);
        }

        return s.ToString() == "John";
    }

    private static void Main() {
        Person[] persons = {
            new("++John++"),
            new("Jo--hn"),
            new("Andy")
        };

        var collection = from p in persons.AsQueryable() where MyPredicate(p.Name) select p;

        foreach(var p in collection)
            Console.WriteLine(p);
    }


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


S>Коротко, там есть два основных класса проблем:

S>1. Не все языковые конструкции имеют аналог в виде Expression.

Ну, это понятно, особенно в деле unsafe.
Непонятно, почему поддержаны не все уже имеющиеся виды Expression.


S>2. Не все типы Expression (даже из стандартной библиотеки) можно породить компилятором из лямбда-синтаксиса.


Ага, в моём примере MyPredicate нельзя было объявить локальной статической ф-ией.


S>Вот это решается только коммитом в компилятор шарпа.


О чём и речь — еще пилить и пилить.



S>Актуальность каждой из проблем зависит от решаемой задачи.


А какая вообще у багов "актуальность"? ))
То, что MyPredicate не может быть статической локальной ф-ией — это просто баг, неконсистентность.
Отредактировано 14.09.2021 17:16 vdimas . Предыдущая версия .
Re[65]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 14.09.21 17:46
Оценка:
Здравствуйте, Sinclair, Вы писали:

V>>Наличие многопоточной очереди лишь одной дисциплины.

V>>И применение очереди этой дисциплины не по месту.
S>То есть к самой ConcurrentQueue вопросов нету. Ну, ок.

Претензии были озвучены:

Например, имеющаяся сейчас в дотнете ConcurrentQueue — тоже только поржать.
В момент роста очереди остальные потоки выполняют строго-блокированное ожидание на SpinWait.

Эта очередь не отвечает гарантиям lock-free, т.к. один поток может заморозить другие.
Re[68]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 14.09.21 18:15
Оценка:
Здравствуйте, Serginio1, Вы писали:

V>>Но компилятор не берёт ничего ручками, он берёт фиксированное смещение и ничего не делает с адресом VMT, т.е. не накладывает маску в попытке обнулить младший бит.

S>То есть для массивов это TypeDesc, а для объектов это реальный VMT

Ну, массивы — это не совсем обычные объекты.
Компилятору не требуется вызывать виртуальные методы для массивов.
А если те приведены к интерфейсу, то в любом случае идёт обращение уже к таблице интерфейсов.
Re[65]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.09.21 04:00
Оценка:
Здравствуйте, vdimas, Вы писали:

V>В двоичном дереве все узлы одинаковые, т.е. виртуальность не нужна.

Да. И, похоже, даже вызовы не нужны.

V>Ну вот как раз джависты показывали, что после уплотнения GC узлы подобных объектов располагаются в памяти рядом, т.к. доступны по ссылкам только из родительских узлов, т.е. по мере естественного обхода ссылок выстроились в правильный порядок в памяти.

Это всё ещё значительно менее плотно, чем int[].

S>>Это как раз будет убивать производительность на маленьких коллекциях.

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

V>Попробуй ввести разные типы (одинаковые внутри) сугубо для эксперимента.

Это и была идея номер 2 в моём ответе.

V>Т.е. рост дерева будет дороже, но можно будет замерить доступ по чтению (если успешно заинлайнится), т.е. чтобы понять — стоит ли вообще копать в эту сторону.

Рост будет стоить ровно столько же.

V>Так непонятен график.

V>Он должен быть линейным в логарифмической шкале для имеющейся реализации.
V>Что такого может произойти на 256 элементах, что до него рост линейный, потом скачок, потом опять линейный рост?
Я полагаю — пересечение границы какого-то из кэшей.

S>>Потому что не взлетает даже когда у нас "рекурсивный" вызов делается напрямую, по call CONST.


V>Ну ты же обогнал имеющуюся реализацию?

Я обогнал на коде без вызовов.

V>Косвенные вызовы тоже умеют обрабатываться предвыборкой до какой-то степени.

Вряд ли.

V>И там лишние 8 байт на Cell особой роли играть не будут.

Да там не нужен этот Cell вообще. Это же B+ дерево — тип у всех детей любой ноды одинаков. Поэтому достаточно хранить ровно одну ссылку на getItem.
Но это всё ещё не поможет — даже когда вместо косвенного вызова внутри getItem стоит прямой вызов на getItem вложенного класса, производительность падает на дно.


V>Алгоритм можно расширить на n-арное дерево.

V>Считай, что твой 16-арный узел — это 8 по 2, но не принципиально, пусть там было бы не 16, а 17.
V>Алгоритм выявляет место, где требуется произвести поворот дерева.
Хм. Сходу не очень понимаю, как будет работать поворот небинарного дерева.

V>Речь про арность.

Речь про лишние вызовы. Они доминируют над арностью.

V>Запутал.

V>Тут показывает, что у тебя доступ по this[index] хуже:
V>https://github.com/evilguest/atropos/blob/main/Atropos.Benchmarks/Atropos.Benchmarks.List.IndexInt.png
V>И в других сценариях тоже.
V>Ранее ты показывал график, где твой код эффективней.
Я же говорю — был прошлогодний код, который работал на гомогенном дереве. Но в нём были проблемы с выделением лишней памяти в листьях. График, который я показал — оттуда.
Сейчас я пытаюсь реализовать код, в котором нет лишних данных. Технически, это получилось, но вот лишние вызовы портят всю малину.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[66]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.09.21 04:02
Оценка: +1
Здравствуйте, vdimas, Вы писали:

V>Претензии были озвучены:

V>

V>Например, имеющаяся сейчас в дотнете ConcurrentQueue — тоже только поржать.
V>В момент роста очереди остальные потоки выполняют строго-блокированное ожидание на SpinWait.

V>Эта очередь не отвечает гарантиям lock-free, т.к. один поток может заморозить другие.
Ну, в таком случае можно предьявить свою реализацию очереди, не ссылаясь на необходимость переписать полдотнета
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[75]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.09.21 04:10
Оценка:
Здравствуйте, vdimas, Вы писали:

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


V>>>А как вообще сюда напишешь расширение, если Expression порождает сам компилятор?

S>>Вот так: https://github.com/bartdesmet/ExpressionFutures/tree/master/CSharpExpressions

V>Как я и сказал — переделывать сам компилятор:

V>

V>the C# compiler changes required to support assignment of lambda expressions containing those language constructs to an Expression<TDelegate> is maintained separately in the ExpressionTrees branch of my Roslyn fork.



S>>То есть сами Expression есть, а вот компилятор их порождать не умеет.


V>О чём и речь.

V>Потому что у меня изначально, еще с выходом Linq, появилась идея попробовать подставить свои Expression, типа как можно делать свой AsyncMethodBuilder, но я не нашёл как.

V>У меня были свои наработки по "работающему" AST, свои Add/Mul/Const и т.д.

V>Что-то вроде:
V>
V>interface IOperation<TResult> 
V>{
V>    TResult Execute();
V>}

V>IBinaryOp<TLeft, TRight, TResult> : IOperation<TResult> 
V>    where TLeft : IOperation<TLeft>
V>    where TRight: IOperation<TRight>
V>{
V>    public TLeft Left {get;}
V>    public TRight Right {get;}
V>}

V>struct Const<T> : IOperation<T>
V>{
V>    public readonly T Value;
V>    public T Execute() => Value;
V>}

V>class Variable<T> : IOperation<T>
V>{
V>    public T Value;
V>    public readonly string Name;

V>    public T Execute() => Value;
V>}

V>struct AddIntOp<TLeft, TRight> : IBinaryOp<TLeft, TRight, int> 
V>    where TLeft : IOperation<int>
V>    where TRight: IOperation<int>
V>{
V>    public TLeft Left {get;}
V>    public TRight Right {get;}

V>    public int Execute() => Left.Execute() + Right.Execute();
V>}
V>


V>Выражение с параметром

V>x + 42
V>порождает тип:
V>AddInt<Variable<int>, Const<int>>
V>Т.е. тоже пользовал тот факт, что джит для value-типов генерит уникальный код без боксинга.
V>Довольно шустро считало, кстате.
А зачем это всё, после C# 3.0? Уж с add int у них нету проблем.


V>Т.е., я не вижу смысла в таких ограничениях, которые обходится простым оформлением лямбды в виде внешней ф-ии.

По большому счёту, его и нет.

V>Ну, это понятно, особенно в деле unsafe.

V>Непонятно, почему поддержаны не все уже имеющиеся виды Expression.
Есть подозрение, что тупо не выделили ресурсов. Типа "EF работает? Работает. Ну и всё, оставьте лямбды в покое".

V>А какая вообще у багов "актуальность"? ))

Очень простая.
V>То, что MyPredicate не может быть статической локальной ф-ией — это просто баг, неконсистентность.
Если в моём проекте нет нужды использовать в предикате локальную статик функцию, то мне на эту неконсистентность наплевать.
Вот с вашей точки зрения, експрешшны ещё "пилить и пилить", а с моей точки зрения linq2d уже работает прямо сейчас. На позапрошлой версии компилятора.

А с точки зрения производителя, ц каждой неконсистентности есть две оценки: стоимости починки и выигрыша от починки.
Второе напрямую зависит от тяжести последствий, частоты встречаемости, и наличия воркэраундов. К сожалению, на их весах конкретно поддержка локал статик функций приносит примерно 0 пользы при ненулевой себестоимости.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[76]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 16.09.21 03:06
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>А зачем это всё, после C# 3.0?


Пи чём тут C# 3.0?
Экспериментировал я с выходом linq.


S>Уж с add int у них нету проблем.


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



V>>Т.е., я не вижу смысла в таких ограничениях, которые обходится простым оформлением лямбды в виде внешней ф-ии.

S>По большому счёту, его и нет.

Не выспался? ))


V>>То, что MyPredicate не может быть статической локальной ф-ией — это просто баг, неконсистентность.

S>Если в моём проекте нет нужды использовать в предикате локальную статик функцию, то мне на эту неконсистентность наплевать.

Такое ощущение, что ты не понимаешь, что пишешь.

На пальцах: статические локальные ф-ии ввели относительно недавно.
Походу, под эту новую фичу не успели доработать некий внутренний ExpressionBuilder.



S>Вот с вашей точки зрения, експрешшны ещё "пилить и пилить", а с моей точки зрения linq2d уже работает прямо сейчас.


Как ты ставил эксперименты, никто так с Linq не работает.


S>А с точки зрения производителя, ц каждой неконсистентности есть две оценки: стоимости починки и выигрыша от починки.


Рассуждая так, дешевле совсем ничего не делать.


Основная странность тут в том, что похвастаться новой фичей не забыли.

S>Второе напрямую зависит от тяжести последствий, частоты встречаемости, и наличия воркэраундов.




К сожалению, на их весах конкретно поддержка локал статик функций приносит примерно 0 пользы при ненулевой себестоимости.
Re[77]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 16.09.21 06:15
Оценка: +1 :)
Здравствуйте, vdimas, Вы писали:

V>Пи чём тут C# 3.0?

V>Экспериментировал я с выходом linq.
Ну вот он и вышел в C# 3.0. Зачем иметь свои IOperation<Result>, когда есть Expression<Func<Result>>?
Зачем AddIntOp<TLeft, TRight>, когда можно просто сделать Expression.Add(Expression.Variable(typeof(int), "x"), Expression.Constant(42))?
Вызываем на нём Compile(), и получаем полноценный бинарный код, ничуть не хуже, чем у AddIntOp.Execute().

V>Специально не делал то замечание, что сейчас арифметические операторы можно делать в генериках.

V>С тобой же не раз обсуждали способы решения этой задчи.
Это вообще ортогональная задача. Арифметические операторы в интерфейсах позволяют нам делать арифметические функции типа T Sum(IEnumerable<T> operands).
Деревья выражений и без этого позволяли нам строить код динамически.

V>Такое ощущение, что ты не понимаешь, что пишешь.


V>На пальцах: статические локальные ф-ии ввели относительно недавно.

V>Походу, под эту новую фичу не успели доработать некий внутренний ExpressionBuilder.
Эмм, по-моему, кто-то отстаёт от дискуссии. Некий внутренний ExpressionBuilder "не успели" доработать до примерно всего, что появилось после C# 3.0.
Это выглядит не как "неуспевание", а как намеренное решение не копать в эту сторону.
При этом важно понимать, что "внутренняя целостность" сама по себе имеет исключительно академическую ценность.
В реальных проектах решения принимаются исходя из практической, а не академической ценности. Вот, скажем, неумение использовать в деревьях выражений статик локалы аффектит примерно 0 человек в мире.
И для тех, кто на это напоролся, есть простой рецепт: перенесите статик локал в простой приватный статик. Всё, вопрос закрыт.
Альтернатива — давайте расширим библиотеку, расширим компилятор, допишем тесты. А, да, самое главное — ресурсы ограничены, поэтому чтобы сделать это, придётся не сделать что-то другое.
Ну вот и не нашлось никакой фичи в бэклоге, которая была бы нужна меньше, чем эта. Увы.

V>Как ты ставил эксперименты, никто так с Linq не работает.

Ну, "если вы хотите добиться успеха, вы должны быть готовы делать то, чего не хотят делать другие". Мне важно то, что "торчит наружу". Поэтому какие-то внутренние проблемы linq2d имеют низкую важность.
Вот отсутствие в ExpressionTrees тупл-инициализаторов торчит прямо наружу, и это мешает потенциальным клиентам linq2d.

V>Рассуждая так, дешевле совсем ничего не делать.

Нет. Отсутствие некоторых фич приносит прямой или косвенный убыток. Или, наоборот, допиливание каких-то фич может принести пользу большому количеству людей.
Так и принимаются продуктовые решения — постоянно приходится чем-то жертвовать.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[78]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 16.09.21 13:39
Оценка: -1
Здравствуйте, Sinclair, Вы писали:

V>>Экспериментировал я с выходом linq.

S>Ну вот он и вышел в C# 3.0. Зачем иметь свои IOperation<Result>, когда есть Expression<Func<Result>>?

Потому что мои Op выполняются, считай, сразу, без стадии компиляции в CIL на моей стороне.


S>Вызываем на нём Compile(), и получаем полноценный бинарный код, ничуть не хуже, чем у AddIntOp.Execute().


Берём серверную сторону, сервак работает 24x7.
Серверная сторона не для красного словца — та задача изначально под серверную сторону потребовалась.

Compile каждый раз порождает новый код, который остаётся в памяти процесса и нет способа этот мусор собрать.
Перезагрузки доменов теперь тоже нет.

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

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


V>>Специально не делал то замечание, что сейчас арифметические операторы можно делать в генериках.

V>>С тобой же не раз обсуждали способы решения этой задчи.
S>Это вообще ортогональная задача. Арифметические операторы в интерфейсах позволяют нам делать арифметические функции типа T Sum(IEnumerable<T> operands).

Через тип-словарик это можно было делать и раньше, но конкретно в этой задаче генерик-реализация экономила мало, бо в том "калькуляторе" использовалось два числовых типа всего — целочисленный long и double. Int — это я просто суть происходящего показывал на пальцах. И обслуживать те типы "раздельно" тоже было удобно, бо напрямую long и double не взаимодействуют в арифметических операциях, а только через предварительную промежуточную операцию приведения long к double, т.е. простой if в коде парсера-билдера оперирует не-генерик типами, а обычными, что тоже где-то удобно, в отсутствии протягиваемого для type-билдера лишней пары генерик-параметров (T и TOpProvider where TOpProvider : IOpProvider<T>).


V>>На пальцах: статические локальные ф-ии ввели относительно недавно.

V>>Походу, под эту новую фичу не успели доработать некий внутренний ExpressionBuilder.
S>Эмм, по-моему, кто-то отстаёт от дискуссии.

Да нет, это ты ответвился от сути моих замечаний.
Замечаний два, они взаимосвязаны:
— Expression вшит в C# и нет возможности подставить некий свой expression builder для ламбд;
— сам ExpressionBuilder обслуживает не все виды лямбд, хотя именно для их обслуживания создавался.


S>Некий внутренний ExpressionBuilder "не успели" доработать до примерно всего, что появилось после C# 3.0.


Разве?
Вот списочек:
https://docs.microsoft.com/ru-ru/dotnet/csharp/whats-new/csharp-8


S>Это выглядит не как "неуспевание", а как намеренное решение не копать в эту сторону.


А что там надо копать для использования объявленного в методе вложенного статического метода?
Чем этот статический метод отличается от обычного?
Насколько я знаю — только именем со специальными префиксами, что-то типа "SomeClass::SomeMethod<>InternalMethod".

Т.е., переименуй SomeClass::SomeMethod<>InternalMethod в SomeClass::SomeMethod_InternalMethod и всё работает.


S>При этом важно понимать, что "внутренняя целостность" сама по себе имеет исключительно академическую ценность.


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

Этот факап не фатален, конечно, просто показывает, что у дотнета, оказывается, нет няньки.
Т.е., опен-сорсная реализация не означала отказ от няньчанья, но, похоже, с дотнетом происходит именно это.
Например, гугл строго няньчится со своим Хромом, хотя проект и в опен-сорсе.


S>В реальных проектах решения принимаются исходя из практической, а не академической ценности.


В реальных коммерческих проектах всегда весы — трудоёмкость vs получаемые плюшки.
Т.е. задачи сортируются не только по степени их важности, но и по соотношению цена:качество.
Чем лучше это соотношение, тем больший балл прибавляется к приоритету задачи.

А здесь ситуация вдвойне забавной получилась, бо поддержка статических локальных методов в expression builder не стоит дороже написания нового кода, который сгенерирует и выдаст новую ошибку компиляции с новым номером при попытке использовать статические локальные методы в expressions.


S>Вот, скажем, неумение использовать в деревьях выражений статик локалы аффектит примерно 0 человек в мире.


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

Рассуждая похожим образом:
— отсутствие linq в дотнете аффектило примерно 0 человек в мире
— отсутствие дотнета аффектило примерно 0 человек в мире
— и т.д.

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


S>И для тех, кто на это напоролся, есть простой рецепт: перенесите статик локал в простой приватный статик. Всё, вопрос закрыт.


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


S>Альтернатива — давайте расширим библиотеку, расширим компилятор, допишем тесты.


Дописать тесты им пришлось в любом случае.
Тесты на правильное генерирование ошибок, хотя бы.


S>А, да, самое главное — ресурсы ограничены, поэтому чтобы сделать это, придётся не сделать что-то другое.


Я думаю, что там всё малость проще.
Вряд ли дотнетные разработчики действительно сошли с ума, скорее, они рассматривают дотнетное сообщество как сборище инфантильных детей.
Им заранее облом отвечать на вопросы из разряда "а почему статические локальные ф-ии в linq использовать можно, а нестатические нет?".
Вот и весь секрет.


S>Ну вот и не нашлось никакой фичи в бэклоге, которая была бы нужна меньше, чем эта. Увы.


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

Среди активных участников наших баталий я выделяю двух коллег, у которых необъяснимый провал в деле формулирования задач.
Как вообще можно работать инженером с низким таким навыком?
(при том, что многие жестко оппонирующие мне умеют это великолепно, тот же НС, т.е. дело тут не в совпадении или нет взглядов).


V>>Как ты ставил эксперименты, никто так с Linq не работает.

S>Ну, "если вы хотите добиться успеха, вы должны быть готовы делать то, чего не хотят делать другие".

Это формула мотивации при полученной высокой оценки трудоёмкости/наукоёмкости некоей задачи.
К делу формулирования задач это перпендикулярно.

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


S>Вот отсутствие в ExpressionTrees тупл-инициализаторов торчит прямо наружу, и это мешает потенциальным клиентам linq2d.


Разве?
Тебе можно вернуть твои же возражения — решается так-то и так-то.
Func<(int, int)> f = ()=>(42, 42);

Expression<Func<(int, int)>> f1 = ()=> ValueTuple.Create(42, 42);


Причём, сравнение ValueTuple появилось только в C# 7.3, т.е., проблема в том, что уже имеющийся Tuple — это класс, поэтому, сделали новый тип ValueTuple<> и сущность tuple literal.
Т.е. этой функциональности в Expression банально нет, её надо пилить.
Я же рассуждал о том, что уже есть, но не доступно.


V>>Рассуждая так, дешевле совсем ничего не делать.

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

Как принимаются решения я уже показывал выше.
Решения принимаются в несколько этапов, происходящих итеративно: из формулирования целей и приоритетов, затем из анализа потенциальной трудоёмкости задач, соотнесения с располагаемыми ресурсами, goto на начало.

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

Поэтому, твои рассуждения "вот это надо, а это не надо" я воспринимаю как отрыв от объективной реальности, сорри (впрочем, как и всегда с тобой).
У каждого "надо" есть цена, где в отсутствии рассмотрения цены рассуждения о надобности профанируются.
Отредактировано 16.09.2021 13:50 vdimas . Предыдущая версия . Еще …
Отредактировано 16.09.2021 13:47 vdimas . Предыдущая версия .
Отредактировано 16.09.2021 13:42 vdimas . Предыдущая версия .
Re[67]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 16.09.21 14:04
Оценка: -1 :)
Здравствуйте, Sinclair, Вы писали:

V>>Эта очередь не отвечает гарантиям lock-free, т.к. один поток может заморозить другие.

S>Ну, в таком случае можно предьявить свою реализацию очереди, не ссылаясь на необходимость переписать полдотнета

Это называется заблудиться в трёх соснах. ))

Я уже подсказал, где можно найти аналогичную реализацию очереди, свой исходник вряд ли имею право дать.
(да и смысла нет, если аналог доступен в открытом доступе)

И что было непонятного в том замечении, что очередь с той дисциплиной потребует переписать механизм тасков?
Это попытка замылить суть вопроса или что?

Альтернативные lock-free очереди с дисциплиной многие-ко-многим на этом сайте тоже публиковались неоднократно, только при чём тут они, если эта дисциплина банально не нужна в деле огранизаций очередей к конкретным потокам?
Re[66]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: vdimas Россия  
Дата: 16.09.21 14:57
Оценка:
Здравствуйте, Sinclair, Вы писали:

V>>Ну вот как раз джависты показывали, что после уплотнения GC узлы подобных объектов располагаются в памяти рядом, т.к. доступны по ссылкам только из родительских узлов, т.е. по мере естественного обхода ссылок выстроились в правильный порядок в памяти.

S>Это всё ещё значительно менее плотно, чем int[].

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

Т.е., тебе пока требуется "просто локальность", а в ней разница в 64 байта или 1кб практически отсутствует в разогретом кеше.


S>>>Это как раз будет убивать производительность на маленьких коллекциях.

V>>Твои графики имеющейся дотнетной реализации показывают, что не будет.
S>Там если присмотреться, то для некоторых размеров мы объезжаем дотнетную реализацию.

Я не вижу на графиках объезжания на малых объемах данных, но ты утверждаешь обратное.


V>>Т.е. рост дерева будет дороже, но можно будет замерить доступ по чтению (если успешно заинлайнится), т.е. чтобы понять — стоит ли вообще копать в эту сторону.

S>Рост будет стоить ровно столько же.

Это с большой копипастой.
Я бы для простоты сделал на виртуальных методах или if-ах с последующим разбоксированием.
Это же все-равно лишь эксперимент для замера эффективности другой функциональности.


V>>Так непонятен график.

V>>Он должен быть линейным в логарифмической шкале для имеющейся реализации.
V>>Что такого может произойти на 256 элементах, что до него рост линейный, потом скачок, потом опять линейный рост?
S>Я полагаю — пересечение границы какого-то из кэшей.

Когда просто по чтению?
Та граница должна будет пересечься и у тебя в каком-то месте.

Можно было бы повторить замеры с предварительным full GC после наполнения дерева.


S>>>Потому что не взлетает даже когда у нас "рекурсивный" вызов делается напрямую, по call CONST.

V>>Ну ты же обогнал имеющуюся реализацию?
S>Я обогнал на коде без вызовов.

Код без вызовов не объясняет отклонение от log(N).


V>>Косвенные вызовы тоже умеют обрабатываться предвыборкой до какой-то степени.

S>Вряд ли.

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


V>>И там лишние 8 байт на Cell особой роли играть не будут.

S>Да там не нужен этот Cell вообще. Это же B+ дерево — тип у всех детей любой ноды одинаков. Поэтому достаточно хранить ровно одну ссылку на getItem.

А да, в твоей релизации одинаковы.
Тем более.


S>Но это всё ещё не поможет — даже когда вместо косвенного вызова внутри getItem стоит прямой вызов на getItem вложенного класса, производительность падает на дно.


Но в дотнетной реализации именно это?



V>>Алгоритм можно расширить на n-арное дерево.

V>>Считай, что твой 16-арный узел — это 8 по 2, но не принципиально, пусть там было бы не 16, а 17.
V>>Алгоритм выявляет место, где требуется произвести поворот дерева.
S>Хм. Сходу не очень понимаю, как будет работать поворот небинарного дерева.

При повороте дочерний узел заменяет собой родительский узел.
В иммутабельном виде как таковой "замены" нет, есть перестроение подиерархии.
Красно-черные позволяют при перестроении перестраивать ограниченное кол-во узлов, т.к. допускается разница в уровнях в 1 по разным веткам.

А у тебя при росте вложенности потребуется перестроить всё дерево, насколько я сейчас понял.


V>>Речь про арность.

S>Речь про лишние вызовы. Они доминируют над арностью.

Не только...
В мутабельном B+ дереве легко последовательно обойти хранящиеся значения (один из основных кейзов для списка), т.к. все листья соеденены в связанный список.

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


S>Я же говорю — был прошлогодний код, который работал на гомогенном дереве. Но в нём были проблемы с выделением лишней памяти в листьях. График, который я показал — оттуда.

S>Сейчас я пытаюсь реализовать код, в котором нет лишних данных. Технически, это получилось, но вот лишние вызовы портят всю малину.

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

Причём, твой узел заведомо "знает", ссылается ли он на листья или ветки, это один флаг.
Затем можно приводить ссылку на дочерний узел через Unsafe.As<T>(Object).

Смотри какие фокусы выдаёт:
class Box<T>
    where T : struct 
{
    public readonly T Value;

    public Box(T value) => Value = value;
}

class Box {
    public static Box<T> From<T>(T value) where T : struct => new(value);
}

private static void Main() {
    object boxedDouble = Box.From(1.0);
    var boxedLong = Unsafe.As<Box<long>>(boxedDouble);
    var doubleBits = boxedLong.Value;
    var isPositive = (doubleBits & 1L << 63) == 0;
}
Re[79]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.09.21 10:23
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Потому что мои Op выполняются, считай, сразу, без стадии компиляции в CIL на моей стороне.

Ну, ок. Статика. Если удастся сконструировать их статически.

S>>Вызываем на нём Compile(), и получаем полноценный бинарный код, ничуть не хуже, чем у AddIntOp.Execute().


V>Берём серверную сторону, сервак работает 24x7.

V>Серверная сторона не для красного словца — та задача изначально под серверную сторону потребовалась.
V>Compile каждый раз порождает новый код, который остаётся в памяти процесса и нет способа этот мусор собрать.
А зачем делать это каждый раз, когда можно один раз проинициализировать статическое поле результатом Compile, а потом обращаться к нему за стоимость вызова IOperation<int>.Execute или даже быстрее?
V>Перезагрузки доменов теперь тоже нет.
Почему не скомпилировать это в DynamicMethod, который прекрасно соберётся безо всякой выгрузки доменов?

V>Через тип-словарик это можно было делать и раньше, но конкретно в этой задаче генерик-реализация экономила мало, бо в том "калькуляторе" использовалось два числовых типа всего — целочисленный long и double. Int — это я просто суть происходящего показывал на пальцах. И обслуживать те типы "раздельно" тоже было удобно, бо напрямую long и double не взаимодействуют в арифметических операциях, а только через предварительную промежуточную операцию приведения long к double, т.е. простой if в коде парсера-билдера оперирует не-генерик типами, а обычными, что тоже где-то удобно, в отсутствии протягиваемого для type-билдера лишней пары генерик-параметров (T и TOpProvider where TOpProvider : IOpProvider<T>).

Эмм, если где-то есть парсер-билдер, то никакой статики уже не будет.

V>Замечаний два, они взаимосвязаны:

V>- Expression вшит в C# и нет возможности подставить некий свой expression builder для ламбд;
Кстати, где-то пробегал FR по внедрению расширяемого expression builder.
V>- сам ExpressionBuilder обслуживает не все виды лямбд, хотя именно для их обслуживания создавался.


V>https://docs.microsoft.com/ru-ru/dotnet/csharp/whats-new/csharp-8

Нет, "списочек" — вот: https://github.com/bartdesmet/ExpressionFutures/blob/master/CSharpExpressions/README.md

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

А то.

V>Например, гугл строго няньчится со своим Хромом, хотя проект и в опен-сорсе.

Да, есть ещё несколько признаков того, что "няньки нет". Но это будет работать до тех пор, пока это отсутствие няньки не будет приводить к реальному геморрою реальных пользователей языка.

V>В реальных коммерческих проектах всегда весы — трудоёмкость vs получаемые плюшки.

Точно. Именно это я и написал.

V>А здесь ситуация вдвойне забавной получилась, бо поддержка статических локальных методов в expression builder не стоит дороже написания нового кода, который сгенерирует и выдаст новую ошибку компиляции с новым номером при попытке использовать статические локальные методы в expressions.

Возможно. Я в код компилятора не смотрел, не могу сказать, что было дороже.

V>Рассуждая похожим образом:

V>- отсутствие linq в дотнете аффектило примерно 0 человек в мире
V>- отсутствие дотнета аффектило примерно 0 человек в мире
Вот эти натянутые аналогии показывают, что вам пока рано в продакт менеджмент
Отсутствие linq в дотнете аффектило миллионы человек в мире. Хейльсберг в своё время очень убедительно обосновывал, почему был разработан Linq — а ведь это потребовало огромных инвестиций. Уж очень дофига принципиально нового было добавлено в язык.
Отсутствие дотнета аффектило, в первую очередь, позиции Microsoft, которому хотелось делать свою JVM, но Sun не давала им пилить JVM в нужную микрософту сторону.
V>Посмотри в зеркало, плиз, на каждый именно твой пост запросто можно отвечать "это никому не нужно" и "ты всё-равно до этого не доживёшь", бо ты пишешь сюда именно такой материал, заведомо допускающий именно таких оценок.
Ну естественно. По умолчанию, linq2d нафиг никому не упал. Если бы я пробовал продать его идею потенциальному инвестору, то всё закончилось бы ещё до начала.
V>А зачем это делать ручками, если комплятор и так переносит статик локал в простой приватный статик? (в отличие от нестатик локал)
V>Т.е. суть именно в этом — фича уже готова и работает, ничего даже делать не надо.
Так это же везде так — ну возьми, замени (4, 5) на ValueTuple.Create(4, 5) — всё ж готово. Но нет, не делают.

V>Вряд ли дотнетные разработчики действительно сошли с ума, скорее, они рассматривают дотнетное сообщество как сборище инфантильных детей.

V>Им заранее облом отвечать на вопросы из разряда "а почему статические локальные ф-ии в linq использовать можно, а нестатические нет?".
V>Вот и весь секрет.
Вот если честно, меня вопросы внутренних процессов принятия решений не очень интересуют. Мне и так приходится ежедневно принимать рещения, которые снаружи могут выглядеть совершенно нелогичными.

V>Что лишний раз напоминает о том, что ты плохо разбираешься в мотивации других людей.

Почему вы решили, что вы разбираетесь лучше? Мы гадаем на кофейной гуще. У меня версия — feature didn't jump over the bar. Ваша идея — "лень было объяснять разницу между статик локалами и нестатик локалами".
Хотя технически я не вижу разницы между статик и нестатик локалами — всё равно строится замыкание. Если уж делать — то можно поддерживать обоих.
V>Отчасти это объясняет странные пробуксовки в обсуждении с тобой на ровном месте.


V>Разве?

V>Тебе можно вернуть твои же возражения — решается так-то и так-то.
V>
V>Func<(int, int)> f = ()=>(42, 42);

V>Expression<Func<(int, int)>> f1 = ()=> ValueTuple.Create(42, 42);
V>




V>Решения принимаются в несколько этапов, происходящих итеративно: из формулирования целей и приоритетов, затем из анализа потенциальной трудоёмкости задач, соотнесения с располагаемыми ресурсами, goto на начало.

Именно. И вот этот процесс привёл к тем результатам, которые мы и наблюдаем.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[68]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.09.21 10:30
Оценка: +2
Здравствуйте, vdimas, Вы писали:

V>Это называется заблудиться в трёх соснах. ))

V>Я уже подсказал, где можно найти аналогичную реализацию очереди, свой исходник вряд ли имею право дать.
Смешно. Сделайте другой исходник. ГК РФ запрещает относить к служебным произведениям что-то, сделанное вне рамок должностных обязанностей или распоряжений руководства.

V>(да и смысла нет, если аналог доступен в открытом доступе)

Обожаю смотреть, как вы начинаете вертеться, как только речь заходит о реальном коде.

V>И что было непонятного в том замечении, что очередь с той дисциплиной потребует переписать механизм тасков?

V>Это попытка замылить суть вопроса или что?
От критиков ConcurrentQueue не требуется переписать механизм тасков. Если очередь плоха сама по себе — то её можно заменить на ту очередь, которая хорошая сама по себе.
То, что в реализации механизма тасков используется не лучшая реализация очереди для механизма тасков — ортогональный вопрос.


V>Альтернативные lock-free очереди с дисциплиной многие-ко-многим на этом сайте тоже публиковались неоднократно, только при чём тут они, если эта дисциплина банально не нужна в деле огранизаций очередей к конкретным потокам?

Ну, раз они публиковались, то наверняка можно привести на них ссылку. Ну, и убедительно продемонстрировать разницу между "плохим" вариантом и "хорошим" вариантом.
Без этого вся дискуссия — споры футбольных фанатов.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[67]: MS забило на дотнет. Питону - да, сишарпу - нет?
От: Sinclair Россия https://github.com/evilguest/
Дата: 17.09.21 10:49
Оценка:
Здравствуйте, vdimas, Вы писали:


V>Т.е., тебе пока требуется "просто локальность", а в ней разница в 64 байта или 1кб практически отсутствует в разогретом кеше.

Нужен эксперимент.

V>Я не вижу на графиках объезжания на малых объемах данных, но ты утверждаешь обратное.

Надо внимательно смотреть:


V>Это с большой копипастой.

V>Я бы для простоты сделал на виртуальных методах или if-ах с последующим разбоксированием.
Не понимаю смысл.

V>Та граница должна будет пересечься и у тебя в каком-то месте.

Ну, вот другое расположение данных. Более кучное.

V>Можно было бы повторить замеры с предварительным full GC после наполнения дерева.

Можно. Почему бы и нет. Сделайте форк да повторите.


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

Ну так оно ж зависит. Мы же пойдём в неизвестного заранее ребёнка.


V>Но в дотнетной реализации именно это?

Повторюсь: есть подозрение, что в дотнетной реализации срабатывает tailcall. Я её не дизассемблировал — может там вообще вызова нет.
Ну, то есть руками-то я и её могу переписать в такой же цикл, который был у меня в декабре прошлого года.


V>При повороте дочерний узел заменяет собой родительский узел.

Какой именно из дочерних узлов?

V>А у тебя при росте вложенности потребуется перестроить всё дерево, насколько я сейчас понял.

Нет конечно. Рост вложенности — это split, он очень простой. порождаются ровно три узла, независимо от глубины дерева. Это же B-tree, они все работают одинаково.

V>Не только...

V>В мутабельном B+ дереве легко последовательно обойти хранящиеся значения (один из основных кейзов для списка), т.к. все листья соеденены в связанный список.

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

Обход я ещё не оптимизировал; но там скорее всего тоже всё будет не намного дороже. Прямо сейчас итератор сделан тупо через _list[_position], то есть шаг итерации ~ O(log(N)). Можно сделать на immutable stack за O(1).

V>Попробуй опять с гомогенными узлами.

V>Там никакая рекурсия не нужна, вирутальность на верхнем уровне тоже, просто сдвигаешься в цикле до листового узла.
Ещё раз: этот код уже есть. Можно посмотреть на версию от 28 декабря 2020.

V>Причём, твой узел заведомо "знает", ссылается ли он на листья или ветки, это один флаг.

V>Затем можно приводить ссылку на дочерний узел через Unsafe.As<T>(Object).
Ну разве что.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.