Информация об изменениях

Сообщение Re[9]: Минутка WTF-19: Catch me if you can от 19.03.2017 17:30

Изменено 19.03.2017 18:00 vdimas

Re[9]: Минутка WTF-19: Catch me if you can
Здравствуйте, Sinix, Вы писали:

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

S>Могу и буду Аргументацию давай.

Я уже давал:
задача правильно поставленного процесса разработки — это наработка и циркуляция в коллективе удачных практик.

Могу сделать определение более строгим:
те люди, которые под какими-либо предлогами по собственной инициативе начинают мешать наработке и циркуляции удачных практик — они саботажники/вредители.

===========
Умный работодатель от таких избавляется. Я таких наблюдал не раз в своей работе, когда кто-то начинает с важным видом втирать то про "стандарты", то про "правила хорошего тона", что прям можно подумать, вокруг одни дураки или только из яйца вылупились. ))
Впервые, по молодости, натурально остолбеневал... то ли от бесконечной глупости, то ли от бесконечной циничности происходящего.
Обычно всё то, что с таким важным видом втирается, окружающие давно проглотили и неоднократно выкакали.
Т.е. лично я расцениваю подобные закидоны как смесь дикого невежества + необузданного хамства в одном флаконе.

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

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

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

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


S>Пока с одной стороны дизайн с запасом прочности, которого хватило как минимум на пятнадцать лет.


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

Причем, меня тут некоторые не особо углублявшиеся в суть предмета коллеги даже пытались высмеивать:
http://www.rsdn.org/forum/flame.comp/6660730.1

Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях. Я одно время на этом собаку съел, в поисках классов таких алгоритмов, которые, таки, работают в обоих случаях и в попытках сформулировать ограничения на такие алгоритмы.

Полюбуйся, отвечающий там даже топики переименовывал следом, в "Собаку съел". ))

А теперь делает лицо кирпичом и пытается участвовать в обсуждении вопроса, который еще совсем недавно всячески высмеивал.
Сюрр, как по мне. ))
Вот, рядом пытается меня поправлять, не понимая, как и тогда, и половины:
http://www.rsdn.org/forum/dotnet/6729409.1


S>С другой — народ, который матчасть не изучал, проблем до конца не видит, но хочет, чтоб усё было


Да проблема-то простая, хосподя.
Вот такая операция:
memset(address_of(someVar), size_of(someVar), 0) — это грубо запоротая память.

Вот рядом тоже я Влада2 порол точно так же:

А вот за это руки поотрывать и отлучать от программирования на веки вечные (ValueOption[T]):

public GetValueOrDefault() : T { _value }

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

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


Т.е., проблема-то древняя. Я на неё уже 15 лет смотрю, и криво ухмыляюсь.

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


S>Силы не равны, кмк.


Чем больше будет в сторону нейтива, тем равнее будут силы.
Тут ведь всё просто до безобразия — у нейтива есть свои эффективные практики и надо их как-то начинать вносить в дотнет.
Одна из первейших практик — 99% абстракций должны быть абсолютно бесплатны.
Это, считай, закон такой.
Дотнет-то тормозит не столько из-за некачественной оптимизации JIT, сколько из-за порождения развесистого ссылочного графа в памяти.


V>>И плевали все на эти лузерские гайды.

S>Именно это команда .net core и делает. Точнее, делала, а затем мегаавральными темпами последний год исправляла. Не получилось игнорить почему-то

Почему "почему-то"?
Я ведь не зря про 2005-й год сказал.
Они тогда дополнили формат сборок, сильно доработали стандарты метаинформации.
Считай, что 2-й дотнет — это ДРУГАЯ платформа, чем дотнет 1.x.
Вот тогда и надо было с функциональным типом разобраться и с конструкторами структур.
К тому же еще инерционность был небольшая.
После 2-го дотнета стандарт метаинформации, считай, не менялся вовсе.
Потому что поезд тю-тю, уехал. Стало страшно его догонять и прыгать в него на ходу.
Но сейчас приходится делать именно это.


V>>В реальных приложухах за счёт этого до 3-4-х раз идёт улучшение эффективности, когда вообще всё перерабатывается через такой же трюк.

S>В смысле, +300% end-to-end throughput за счёт избавления от виртуальных вызовов? Я таки хочу на это посмотреть. Кинь ссылочку, плиз

Нет, не виртуальных. Я заменил все эти List<> на работу с голыми массивами.
Когда массив оборачивается структурой, получается такая же скорость.
(если найду, кину ссылку)
И там же писал о том, что пришлось сделать клоны основных коллекций в виде value-type и многие относительно большие объекты тоже сделать в виде value-type (по ref пуляшь и огонь, всё чудесно работает), но при этом так же пришлось в ручном режиме соблюдать определённую гигиену такого кода. Потому что именно из-за дыры в пустой инициализации структур.


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

S>Липперт скорее популяризатор, чем проектировщик базовых вещей.

Именно. Я его за популяризаторство того самого "псевдоинженерного подхода", которые во все времена резко высмеивался, и ругаю.
Вот этот его сироп из разряда: "Здесь может показаться, что эффективней было бы сделать так-то и так-то, но давайте на минуточку представим... и бла-бла-бла", песня льётся соловьём. Поубивал бы. )) Столько хороших людей испортил в 2000-е. Ты вспомни что тут на сайте в середине 2000-х творилось — это же было торжество отсутствия здравого смысла. Это была жесть как она есть.

А еще знаешь, что в них всех все годы бесило? — показушность.
Им надо было показать, как у них всё хорошо получается.
Я терпеть этого в колегах не могу, если честно.
Потому что каждый божий раз, когда я такое вижу вживую, я при этом обязательно вижу, что человек работает "на отгребись" (в оригинале нецензурщина). Причем, стоит только попытаться таким людям показать, что, вообще-то, вот тут у тебя всё по наилегчайшему пути и вообще не фонтан, есть же вот известные практики, дающие намного больше толку в рантайме (мы же для рантайма ПО пишем), так там всегда мега-агрессия.

Вот именно такие люди разрабатывали дотнет. Агрессивные инженеры. А инженер не должен быть агрессивным, он должен быть непременно сомневающимся, всегда ищущим альтернативы. Это главное правило. Как только инженер уверен в своей правоте на все сто — уноси хоронить, вноси следующего.

В этом смысле Липперта надо было хоронить еще в 2004-м, там диагноз уже был слишком очевиден, ИМХО.


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

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

И что ты хочешь услышать в ответ?
Это ж как раз именно такие практики, которые повышают детерминированность программ.
В функциональном программировании, в С++, в D и во всех этих новых языках есть такая практика — "осмысленное" конструирование значения.


S>Нужен нормальный пайплайн для трансляции в натив с девиртуализацией и инлайном виртуальных вызовов/делегатов.


Факт наличия других независимых задач ортогонален. как бы. ))


S>Вот это даст эффект. Всё остальное — полумеры.


Э нет. Полумеры — это озвученное тобой. Если в памяти так и будет граф, если 70-80% памяти дотнетной программы (даже после конвертации в .Net Native) будут занимать ссылки, то это всё так и будет заметно отставать.

Насчет делегатов — да. Но для этого нужен полноценный функциональный тип, а его нет.


S>М.б. потому что мы таки работаем на реальных проектах и таки видим реальные проблемы, которые реально имеет смысл фиксить?


А я на нереальных, что ле, работал?
Просто, может, у вас проекты такие, что эффективность не нужна.
Ну граф и граф...
Ну и что, что полезных данных только 20% в памяти... ))

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


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


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

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


V>>Разве сам не увидел, что тут вина разработчиков ImmutableArray лишь в том, что они "побежали впереди паровоза"?

V>>Например, можно везде в linq и прочих методах-расширениях ввести альтернативные сигнатуры сугубо для аргумента ImmutableArray<T>, где проверить его на пустоту ПРАВИЛЬНО.
S>Это решается куда дешевле — аналайзером рослина, который гарантирует, что метод не возвращает и не сохраняет в поля пустой immutable array.

Это не дешевле, это дуля в правом кармане левой рукой. ))
Необходимо дать возможность компилять исходники даже обычным csc.exe из минимального тулчайна.
Поэтому, проще добавить сигнатуры в linq.
Это вообще работа на пару дней от силы.
Ну или можно накатать самому такое же расширение и подключать его в область видимости.
Пруф банален:
    struct ImmutableArray<T>
    {
        internal T[] _array;

        public bool IsEmpty
        {
            get { return _array == null; }
        }

        public ImmutableArray(T[] a)
        {
            _array = a;
        }
    }

    static class ImmutableArrayExtentions
    {
        private static void CheckNotNull<T>(ImmutableArray<T> ar) 
        {
            if (ar.IsEmpty)
                throw new NullReferenceException();
        }

        public static ImmutableArray<T> ToImmutable<T>(this T[] ar)
        {
            return new ImmutableArray<T>(ar);
        }

        public static int Sum(this ImmutableArray<int> source)
        {
            CheckNotNull(source);
            return Enumerable.Sum(source._array);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var ar = new int[] { 1, 2, 3 };
            var imm = ar.ToImmutable();
            var s = imm.Sum();  // ok
            int[] nar = null;
            var nimm = nar.ToImmutable();
            var ns = nimm.Sum();  // exception thrown
        }
    }

Причем, в моём пруфе мы убегаем от лишнего боксинга, заметь.


S>Готовое API для data flow analysis есть, если что. Но этого тоже не было сделано.


data flow analysis не так прост.
Это, собсно, "передовая грань" современного IT как такового.
Так еще своих собак не съели в нужном кол-ве.
Потому что вот это странно:

не сохраняет в поля пустой immutable array

Это с какой радости? Чего-то я не могу сохранить null-ссылку?
За что меня бить по рукам-то?
Re[9]: Минутка WTF-19: Catch me if you can
Здравствуйте, Sinix, Вы писали:

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

S>Могу и буду Аргументацию давай.

Я уже давал:
задача правильно поставленного процесса разработки — это наработка и циркуляция в коллективе удачных практик.

Могу сделать определение более строгим:
те люди, которые под какими-либо предлогами по собственной инициативе начинают мешать наработке и циркуляции удачных практик — они саботажники/вредители.

===========
Умный работодатель от таких избавляется. Я таких наблюдал не раз в своей работе, когда кто-то начинает с важным видом втирать то про "стандарты", то про "правила хорошего тона", что прям можно подумать, вокруг одни дураки или только из яйца вылупились. ))
Впервые, по молодости, натурально остолбеневал... то ли от бесконечной глупости, то ли от бесконечной циничности происходящего.
Обычно всё то, что с таким важным видом втирается, окружающие давно проглотили и неоднократно выкакали.
Т.е. лично я расцениваю подобные закидоны как смесь дикого невежества + необузданного хамства в одном флаконе.

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

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

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

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


S>Пока с одной стороны дизайн с запасом прочности, которого хватило как минимум на пятнадцать лет.


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

Причем, меня тут некоторые не особо углублявшиеся в суть предмета коллеги даже пытались высмеивать:
http://www.rsdn.org/forum/flame.comp/6660730.1

Собсно, вообще таких алгоритмов мало, которые можно выразить в дотнете для value и ref-типов в генериках и они будут корректно работать в обоих случаях. Я одно время на этом собаку съел, в поисках классов таких алгоритмов, которые, таки, работают в обоих случаях и в попытках сформулировать ограничения на такие алгоритмы.

Полюбуйся, отвечающий там даже топики переименовывал следом, в "Собаку съел". ))

А теперь делает лицо кирпичом и пытается участвовать в обсуждении вопроса, который еще совсем недавно всячески высмеивал.
Сюрр, как по мне. ))
Вот, рядом пытается меня поправлять, не понимая, как и тогда, и половины:
http://www.rsdn.org/forum/dotnet/6729409.1


S>С другой — народ, который матчасть не изучал, проблем до конца не видит, но хочет, чтоб усё было


Да проблема-то простая, хосподя.
Вот такая операция:
memset(address_of(someVar), size_of(someVar), 0) — это грубо запоротая память.

Вот рядом тоже я Влада2 порол точно так же:

А вот за это руки поотрывать и отлучать от программирования на веки вечные (ValueOption[T]):

public GetValueOrDefault() : T { _value }

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

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


Т.е., проблема-то древняя. Я на неё уже 15 лет смотрю, и криво ухмыляюсь.

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


S>Силы не равны, кмк.


Чем больше будет в сторону нейтива, тем равнее будут силы.
Тут ведь всё просто до безобразия — у нейтива есть свои эффективные практики и надо их как-то начинать вносить в дотнет.
Одна из первейших практик — 99% абстракций должны быть абсолютно бесплатны.
Это, считай, закон такой.
Дотнет-то тормозит не столько из-за некачественной оптимизации JIT, сколько из-за порождения развесистого ссылочного графа в памяти.


V>>И плевали все на эти лузерские гайды.

S>Именно это команда .net core и делает. Точнее, делала, а затем мегаавральными темпами последний год исправляла. Не получилось игнорить почему-то

Почему "почему-то"?
Я ведь не зря про 2005-й год сказал.
Они тогда дополнили формат сборок, сильно доработали стандарты метаинформации.
Считай, что 2-й дотнет — это ДРУГАЯ платформа, чем дотнет 1.x.
Вот тогда и надо было с функциональным типом разобраться и с конструкторами структур.
К тому же еще инерционность была небольшая.
После 2-го дотнета стандарт метаинформации, считай, не менялся вовсе.
Потому что поезд тю-тю, уехал. Стало страшно его догонять и прыгать в него на ходу.
Но сейчас приходится делать именно это.


V>>В реальных приложухах за счёт этого до 3-4-х раз идёт улучшение эффективности, когда вообще всё перерабатывается через такой же трюк.

S>В смысле, +300% end-to-end throughput за счёт избавления от виртуальных вызовов? Я таки хочу на это посмотреть. Кинь ссылочку, плиз

Нет, не виртуальных. Я заменил все эти List<> на работу с голыми массивами.
Когда массив оборачивается структурой, получается такая же скорость.
(если найду, кину ссылку)
И там же писал о том, что пришлось сделать клоны основных коллекций в виде value-type и многие относительно большие объекты тоже сделать в виде value-type (по ref пуляешь и огонь, всё чудесно работает), но при этом так же пришлось в ручном режиме соблюдать определённую гигиену такого кода. Потому что именно из-за дыры в пустой инициализации структур.


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

S>Липперт скорее популяризатор, чем проектировщик базовых вещей.

Именно. Я его за популяризаторство того самого "псевдоинженерного подхода", который во все времена резко высмеивался, и ругаю.
Вот этот его сироп из разряда: "Здесь может показаться, что эффективней было бы сделать так-то и так-то, но давайте на минуточку представим... и бла-бла-бла", песня льётся соловьём. Поубивал бы. )) Столько хороших людей испортил в 2000-е. Ты вспомни что тут на сайте в середине 2000-х творилось — это же было торжество отсутствия здравого смысла. Это была жесть как она есть.

А еще знаешь, что в них всех все годы бесило? — показушность.
Им надо было показать, как у них всё хорошо получается.
Я терпеть этого в колегах не могу, если честно.
Потому что каждый божий раз, когда я такое вижу вживую, я при этом обязательно вижу, что человек работает "на отгребись" (в оригинале нецензурщина). Причем, стоит только попытаться таким людям показать, что, вообще-то, вот тут у тебя всё по наилегчайшему пути и вообще не фонтан, есть же вот известные практики, дающие намного больше толку в рантайме (мы же для рантайма ПО пишем), так там всегда мега-агрессия.

Вот именно такие люди разрабатывали дотнет. Агрессивные инженеры. А инженер не должен быть агрессивным, он должен быть непременно сомневающимся, всегда ищущим альтернативы. Это главное правило. Как только инженер уверен в своей правоте на все сто — уноси хоронить, вноси следующего.

В этом смысле Липперта надо было хоронить еще в 2004-м, там диагноз уже был слишком очевиден, ИМХО.


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

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

И что ты хочешь услышать в ответ?
Это ж как раз именно такие практики, которые повышают детерминированность программ.
В функциональном программировании, в С++, в D и во всех этих новых языках есть такая практика — "осмысленное" конструирование значения.


S>Нужен нормальный пайплайн для трансляции в натив с девиртуализацией и инлайном виртуальных вызовов/делегатов.


Факт наличия других независимых задач ортогонален, как бы. ))


S>Вот это даст эффект. Всё остальное — полумеры.


Э нет. Полумеры — это озвученное тобой. Если в памяти так и будет граф, если 70-80% памяти дотнетной программы (даже после конвертации в .Net Native) будут занимать ссылки, то это всё так и будет заметно отставать.

Насчет делегатов — да. Но для этого нужен полноценный функциональный тип, а его нет.


S>М.б. потому что мы таки работаем на реальных проектах и таки видим реальные проблемы, которые реально имеет смысл фиксить?


А я на нереальных, что ле, работал?
Просто, может, у вас проекты такие, что эффективность не нужна.
Ну граф и граф...
Ну и что, что полезных данных только 20% в памяти... ))

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


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


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

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


V>>Разве сам не увидел, что тут вина разработчиков ImmutableArray лишь в том, что они "побежали впереди паровоза"?

V>>Например, можно везде в linq и прочих методах-расширениях ввести альтернативные сигнатуры сугубо для аргумента ImmutableArray<T>, где проверить его на пустоту ПРАВИЛЬНО.
S>Это решается куда дешевле — аналайзером рослина, который гарантирует, что метод не возвращает и не сохраняет в поля пустой immutable array.

Это не дешевле, это дуля в правом кармане левой рукой. ))
Необходимо дать возможность компилять исходники даже обычным csc.exe из минимального тулчайна.
Поэтому, проще добавить сигнатуры в linq.
Это вообще работа на пару дней от силы.
Ну или можно накатать самому такое же расширение и подключать его в область видимости.
Пруф банален:
    struct ImmutableArray<T>
    {
        internal T[] _array;

        public bool IsEmpty
        {
            get { return _array == null; }
        }

        public ImmutableArray(T[] a)
        {
            _array = a;
        }
    }

    static class ImmutableArrayExtentions
    {
        private static void CheckNotNull<T>(ImmutableArray<T> ar) 
        {
            if (ar.IsEmpty)
                throw new NullReferenceException();
        }

        public static ImmutableArray<T> ToImmutable<T>(this T[] ar)
        {
            return new ImmutableArray<T>(ar);
        }

        public static int Sum(this ImmutableArray<int> source)
        {
            CheckNotNull(source);
            return Enumerable.Sum(source._array);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            var ar = new int[] { 1, 2, 3 };
            var imm = ar.ToImmutable();
            var s = imm.Sum();  // ok
            int[] nar = null;
            var nimm = nar.ToImmutable();
            var ns = nimm.Sum();  // exception thrown
        }
    }

Причем, в моём пруфе мы убегаем от лишнего боксинга, заметь.


S>Готовое API для data flow analysis есть, если что. Но этого тоже не было сделано.


data flow analysis не так прост.
Это, собсно, "передовая грань" современного IT как такового.
Так еще своих собак не съели в нужном кол-ве.
Потому что вот это странно:

не сохраняет в поля пустой immutable array

Это с какой радости? Чего-то я не могу сохранить null-ссылку?
За что меня бить по рукам-то?