Мой поинт в том что вы рекламируете это как библиотеку и у вас ни слова нет про то насколько это хрупкий/ненадежный около-UB/unsafe инструмент. Что бы вы понимали, бинарные сериализаторы, которые делают похожие хаки сериализуя объекты в байт массивы (и десереиализуя) без учета паддингов были не раз причиной CVE.
Вашу задачу невозможно решить в общем случае без около-UB люто unsafe кода (который обязательно выстрелит в виде CVE) в .NET. Как я вам уже написал: Единственное когда это возможно это для структур без падингов и блиттабл полями, но в дотнете нет АПИ через которое вы можете это проверить
Если вы не используете unsafe код, вы никогда не столкнетесь с никакими багами из-за мусора в паддинга (он там может быть даже без интеропа, просто со стека)
Абсолютно бессмысленнго его занулять для структур без StructLayout.Explicit, потому что JIT может легко структуру с зануллеными падингами временно куда-то скопировать на стек только полями и будет опять мусор со стека в полях, короче говоря, это UB.
Никогда не пишите код который считает хэш, сравнивает структуры через memcpy/memcmp идиомы, это отличный способ выстрелить себе в ногу с гранатомета. Единственное когда это возможно это для структур без падингов и блиттабл полями, но в дотнете нет АПИ через которое вы можете это проверить (+ может быть различие на разных архитектурах/платформах)
похоже GC .net останавливает потоки в основном на аккокаторах
это не так. часть методов в дотнет полностью fully interruptible и в какой момент бы поток не приостановился - он будет в сейфпоинте. в других методах используется return address hijacking т.е. любой вызов любого метода становится потенциальным сейфпоинтом.
Плюсы: никаких лишних инструкций в циклах и где либо еще, мгновенная остановка треда в fully-interruptible Минусы: большой (по размеру) GC info (чтобы precise GC знал что сканировать на каждой инструкции fully-interruptible метода. Менее прогнозируемое время до паузы при call hijacking. необходимость сохранять и ресторить return address в стек в каждом методе
Нет. это не GC poll, вы смотрите дебажный асм (даже если запустили в Release, т.к. при отладке вижла всегда сбрасывает код в Tier0-dbg) и условный переход который вы мне показываете это
cmp dword ptr [(reloc 0x7ffe048bca18)], 0
je SHORT G_M000_IG04
G_M000_IG03: ;; offset=0x0021
call CORINFO_HELP_DBG_IS_JUST_MY_CODE
Это подсказка деббагеру что код вошёл в "my code" для фичи "Debug just my code"
Ещё раз повторю - .NET не использует явные сейф поинты (как, например, Java) - у этого подхода свои плюсы/минусы.
Если вы использовали .NET чтобы рассказать как работает GC то ваша интерпретация очень далека от того как он работает - там нет GC_POLL вызовов в коде (за очень редким исключением аля pinvokes) циклах и т.п.
Обычное интерпретирование заданных правил из строки (поведение по-умолчанию)
Динамического создания нового IL метода который оптимизирует какие-то операции конкретно под заданную регулярку.
Тоже самое что 2) только через Source-Gen на этапе компиляции C# кода, а не как в случае 2) - во время работы
В целом рекомендуется использовать 3ий вариант, он самый быстрый и вы не делаете лишней работы во время запуска приложения (= ускорение запуска) + дебажить просто. Есть всякие автоматические инспекции которые помогут привести обычную регулярку к нему
Как видите, никакое сохранение ни в какую переменную само по себе ничего не дает (кроме разве что сохранения аллокации 1 объекта)
Можете обновить часть "На текущий момент async2 остаётся экспериментом, доступным в runtimelab в ветке feature/async2-experiment" -- оно уже переехало в апстрим (main dotnet/runtime) и продолжается разработка уже там (довольно активно).
Есть интерпретатор в моно, но решили его переписать на CoreCLR, чтобы он использовал тот же рантайм и гц. пока в разработке, цель просто заменить существующий моновский (там где он сейчас используется).
Вообще странно, что они не сделали сам тип string как-нибудь так, чтобы если строка короткая, то она пыталась бы храниться на стеке.
Есть подвижки в .NET 10.0 в эту сторону, но чтобы объект можно было аллоцировать на стеке, джит должен сам себе доказать что он никаким образом не убегает в хип
Эфемерные аллокации типа таких не нагружают гц, люди часто с ними борятся непонятно зачем. Гораздо хуже аллокации при которых создаются Gen2 -> Gen0 линки
Забавно что вы написали небезопасный хэшер который считает с мусором в хеше, и потом героически решили это проблему через другую библиотеку, которая в комплект не входит :D кстати у вас там явно баг в коде https://github.com/viruseg/GxHash.128bits.Overloads/blob/master/GxHash.128bits.Overloads/Hash128Methods.cs#L190 - вместо buffer.Length должно было видимо бы asBytes.Length
Мой поинт в том что вы рекламируете это как библиотеку и у вас ни слова нет про то насколько это хрупкий/ненадежный около-UB/unsafe инструмент. Что бы вы понимали, бинарные сериализаторы, которые делают похожие хаки сериализуя объекты в байт массивы (и десереиализуя) без учета паддингов были не раз причиной CVE.
Вашу задачу невозможно решить в общем случае без около-UB люто unsafe кода (который обязательно выстрелит в виде CVE) в .NET. Как я вам уже написал: Единственное когда это возможно это для структур без падингов и блиттабл полями, но в дотнете нет АПИ через которое вы можете это проверить
Если вы не используете unsafe код, вы никогда не столкнетесь с никакими багами из-за мусора в паддинга (он там может быть даже без интеропа, просто со стека)
Абсолютно бессмысленнго его занулять для структур без StructLayout.Explicit, потому что JIT может легко структуру с зануллеными падингами временно куда-то скопировать на стек только полями и будет опять мусор со стека в полях, короче говоря, это UB.
Никогда не пишите код который считает хэш, сравнивает структуры через memcpy/memcmp идиомы, это отличный способ выстрелить себе в ногу с гранатомета. Единственное когда это возможно это для структур без падингов и блиттабл полями, но в дотнете нет АПИ через которое вы можете это проверить (+ может быть различие на разных архитектурах/платформах)
Рекомендую к прочтению статью.
это не так. часть методов в дотнет полностью fully interruptible и в какой момент бы поток не приостановился - он будет в сейфпоинте. в других методах используется return address hijacking т.е. любой вызов любого метода становится потенциальным сейфпоинтом.
Плюсы: никаких лишних инструкций в циклах и где либо еще, мгновенная остановка треда в fully-interruptible
Минусы: большой (по размеру) GC info (чтобы precise GC знал что сканировать на каждой инструкции fully-interruptible метода. Менее прогнозируемое время до паузы при call hijacking. необходимость сохранять и ресторить return address в стек в каждом методе
Нет. это не GC poll, вы смотрите дебажный асм (даже если запустили в Release, т.к. при отладке вижла всегда сбрасывает код в Tier0-dbg) и условный переход который вы мне показываете это
Это подсказка деббагеру что код вошёл в "my code" для фичи "Debug just my code"
Ещё раз повторю - .NET не использует явные сейф поинты (как, например, Java) - у этого подхода свои плюсы/минусы.
нет никаких ассемблерных вставок для GC_POLL в .NET. Покажите мне где вот тут (sharplab) вставка?
Если вы использовали .NET чтобы рассказать как работает GC то ваша интерпретация очень далека от того как он работает - там нет GC_POLL вызовов в коде (за очень редким исключением аля pinvokes) циклах и т.п.
У регулярок есть 3 режима:
Обычное интерпретирование заданных правил из строки (поведение по-умолчанию)
Динамического создания нового IL метода который оптимизирует какие-то операции конкретно под заданную регулярку.
Тоже самое что 2) только через Source-Gen на этапе компиляции C# кода, а не как в случае 2) - во время работы
В целом рекомендуется использовать 3ий вариант, он самый быстрый и вы не делаете лишней работы во время запуска приложения (= ускорение запуска) + дебажить просто. Есть всякие автоматические инспекции которые помогут привести обычную регулярку к нему
Как видите, никакое сохранение ни в какую переменную само по себе ничего не дает (кроме разве что сохранения аллокации 1 объекта)
Ваша реализация всё ещё проигрывает озвученному выше
return value.AsSpan().IndexOfAnyExceptInRange('0', '9') == -1;https://github.com/dotnet/runtime/pull/114675 и https://github.com/dotnet/runtime/pull/114861 - вот переезд + много пулл-реквестов после этого
он переехал. вы ожидали увидеть удаленную ветку? зачем?
Можете обновить часть "На текущий момент async2 остаётся экспериментом, доступным в runtimelab в ветке feature/async2-experiment" -- оно уже переехало в апстрим (main dotnet/runtime) и продолжается разработка уже там (довольно активно).
Подозреваю что статья - GPT перевод https://github.com/dotnet/runtimelab/blob/feature/async2-experiment/docs/design/features/runtime-handled-tasks.md ? :-)
Есть интерпретатор в моно, но решили его переписать на CoreCLR, чтобы он использовал тот же рантайм и гц. пока в разработке, цель просто заменить существующий моновский (там где он сейчас используется).
Их нельзя использовать вместе никак, это два разных рантайма. У вас на выбор 4 опции:
NativeAOT
JIT + R2R (обычно все базовые библиотеки в R2R идут), при этом весь R2R код (если он горячий) по итогу все равно пере-компилируется джитом в Tier1
JIT-only (если насильно отключить R2R).
R2R-only, но тут практически нереально добиться того чтобы джит не вызывался
Ещё есть интерпретатор новый.
Native AOT + ReadyToRun -- не очень понятно то имеется ввиду под этим.
Либо на запись, либо на выполнение, потому что с .NET 7.0 по-умолчанию включен W^X так что если влазить руками - убьет
А где не так? в чём смысл вашего комментария?
Есть подвижки в .NET 10.0 в эту сторону, но чтобы объект можно было аллоцировать на стеке, джит должен сам себе доказать что он никаким образом не убегает в хип
Эфемерные аллокации типа таких не нагружают гц, люди часто с ними борятся непонятно зачем. Гораздо хуже аллокации при которых создаются Gen2 -> Gen0 линки