Start Debugging
RU
2026-05-01 Обновлено 2026-11-02 csharpdotnetdotnet-8 Edit on GitHub

Производительность .NET 8: UnsafeAccessor и рефлексия

Воспроизводимый benchmark .NET 8: UnsafeAccessor, рефлексия, кешированные рефлексия и делегат, прямые вызовы с наблюдаемой работой.

На этом сайте ИИ-агент Walter используется для исследования тем, написания материалов и обслуживания. Подготовка и проверка материалов

UnsafeAccessor связывается с известным членом без поиска через рефлексию и без MethodInfo.Invoke. Полезное сравнение должно сохранять наблюдаемую работу целевого метода и объяснять каждый путь вызова.

Исправление — 2 ноября 2026 года: прежний репозиторий недоступен. Пример восстановлен с функциональной проверкой, диагностикой аллокаций, кешированными делегатами и одинаковой работой невстраиваемых целевых методов. Старые времена около нуля не доказывают универсальные нулевые расходы и больше не представлены как воспроизводимые измерения.

Загрузка и запуск

Скачайте исходный benchmark-проект. Целевая версия — .NET 8, BenchmarkDotNet закреплён на 0.15.8.

dotnet run -c Release -- --verify
dotnet run -c Release -- --job Dry --filter '*'
dotnet run -c Release -- --filter '*'

Первая команда проверяет, что все пять путей возвращают 59 для входного 42. Вторая проверяет выполнение за одну итерацию. Последнюю используйте для обычных измерений и сохраняйте созданные сведения об окружении и отчёты перед интерпретацией времени.

Что сравнивается

  1. Прямой вызов: вызывает публичный метод.
  2. Unsafe accessor: связывается с приватным методом с той же операцией.
  3. Поиск и вызов через рефлексию: находит и вызывает метод при каждой операции.
  4. Кешированная рефлексия: повторно использует MethodInfo, но всё ещё передаёт массив объектов-аргументов.
  5. Кешированный делегат: повторно использует открытый делегат экземпляра для приватного метода.

Оба целевых метода возвращают сумму входа и поля экземпляра и используют MethodImplOptions.NoInlining. Каждый benchmark возвращает результат. Вход задаётся параметром BenchmarkDotNet, чтобы пример не свёлся к встроенному методу с константным результатом.

MemoryDiagnoser показывает аллокации, включая массив аргументов и boxing при рефлексии. Пути выполняют разную работу; разница во времени не объясняется одной проверкой доступа.

Проверка и интерпретация

Восстановленный проект выполнен на .NET 8.0.33 в macOS arm64. Функциональная проверка и все пять Dry-заданий BenchmarkDotNet прошли. Dry-времена намеренно не публикуются как таблица производительности: они проверяют стенд, а не дают устойчивую наносекундную оценку.

На результат влияют inlining, версия runtime, архитектура, целевая работа, кеширование и аллокации. Очень малое время может означать, что JIT удалил работу или измерение ниже полезного разрешения стенда. Это не доказывает бесплатность каждой операции аксессора.

Аксессору также нужна сигнатура при компиляции. Рефлексия остаётся полезной, если тип или член находится во время выполнения. См. примеры доступа к членам и справочник Microsoft.

Comments

Sign in with GitHub to comment. Reactions and replies thread back to the comments repo.