Анализ производительности .NET: глубинный взгляд на Span.Sort и LINQ
Редакция PROSTO24 продолжает серию исследований производительности ключевых компонентов платформы .NET. Последние тесты выявили неожиданные нюансы в работе механизмов сортировки, в частности Span.Sort и LINQ OrderBy, которые могут существенно влиять на эффективность приложений.
Span.Sort: компараторы-структуры и расход памяти
Ожидалось, что использование перегрузки Span.Sort с компаратором-структурой обеспечит более высокую скорость выполнения по сравнению с компаратором-классом благодаря оптимизации выделения памяти. Однако проведенные бенчмарки на платформах .NET 8, 9 и 10 показали обратный результат. Тесты выявили, что компаратор-структура не только расходует больше оперативной памяти, но и демонстрирует худшие временные показатели, превышая затраты компаратора-класса. С приходом .NET 11 ситуация меняется, но не во всех сценариях, что требует дальнейшего углубленного анализа.
LINQ OrderBy: скрытые ловушки полной сортировки
Еще одна область, где производительность может быть неочевидной, — это использование метода LINQ OrderBy. Исследования показали, что некоторые вызовы после OrderBy осуществляют лишь однократный проход по коллекции, в то время как другие, при внешнем сходстве кода, приводят к полной и ресурсоемкой сортировке всего набора данных. Визуально различить эти сценарии по коду практически невозможно. Для выявления таких «подстав» были проведены контрольные замеры с использованием счетчика обращений к компаратору на четырех различных аппаратных конфигурациях и четырех версиях рантайма, что позволило точно определить, когда происходит полная сортировка, а когда — оптимизированный проход.
Интересно, но результаты по Span.Sort с компараторами-структурами вызывают вопросы. Если на более ранних версиях .NET наблюдается рост потребления памяти и снижение производительности, это может стать серьёзным препятствием для миграции или при разработке новых проектов, где оптимизация критична. Хотелось бы увидеть более глубокий анализ причин такого поведения, а не только констатацию факта. И как быть с уже существующим кодом, который активно использует эти подходы? Переписывать?