Тормозит утилита на Windows 11 (.net framework 4.8)

У меня есть несколько утилит, написанных на c# под Framework 4.8. После апгрейда операционки с 10-ки на 11-ую утилиты работают в 3-4 раза медленнее. Кто-нибудь сталкивался с подобным?

Утилиты парсят большие файлы. Диск не шифрованый. Всё остальное работает вроде нормально.

На 10-ке на виртуалке(!) работает в четыре раза быстрее.

P. S. Тестирую на файлах ~600..~800 МБ. Это рабочие файлы, и такой размер исключает влияние неоднородности содержимого. На физическом компе на 11-ой время выполнения ~50 с, на виртуальной машине с 10-ой, которая запускается на этом же компе, ~12 c. Все остальные приложения на физическом компе работают вроде-бы нормально, никаких видимых тормозов нет.

.Net 10 и пр. - это не предмет вопроса.

P. P. S. Скомпилировал в .Net 6 - тотже результат. Виртуальная машина находится на внешнем диске. Скорость работы утилиты на хосте с файлом на внешнем диске чуть меньше, чем на встроенном, что вполне ожидаемо.


Ответы (1 шт):

Автор решения: InterceptorTSK

Точно замерьте производительность.

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

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

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

Иначе говоря, запустите ваше ПО с файликом в 10Мб на десятке 2 [два] раза, и вы должны получить разные числа.

// Десятка:
// Первый запуск 200ms
// Второй запуск 150ms
// Третий запуск 150ms

Очевидно тут то, что на чтение с диска ушло 50ms "сверху".

// Ровно такой же тест проведите на 11:
// Первый запуск 800ms
// Второй запуск 150ms
// Третий запуск 150ms

Так может быть? Конечно может. А может быть как то иначе. Суть проста, получите два числа на десятке, и два числа на 11. Но на маленьком одном и том же файлике. Этим самым вы достаточно просто получите то что нужно, а именно ответ на вопрос - а в каком месте оно тормозит?

Это простейший тест, не требующий перекомпиляций и прочего сложного. Реализуется за пять минут. Получите эти два + два числа.

P.S: Автор задал вопрос, "И зачем всё это?"

Простейший пример, создаём маленький файлик, пусть так:

byte[] bytes = new byte[1024 * 1024 * 10]; // 10 Mb

new System.Random().NextBytes(bytes);

System.IO.File.WriteAllBytes("tmp.bin", bytes);

А теперь стираем вышенакаряченное, файлик уже создан, код выше не нужен. Пишем следующее.

System.Console.ReadLine();

// Это прогревашка, подымает частоту процессора.
long temp = 0;
for (int i = 0; i < 2000000000; i++) temp += i;

// Засекаем время
var sw = new System.Diagnostics.Stopwatch(); sw.Start();

// [1] Это чтец в буфер, IO операция
byte[] bytes = System.IO.File.ReadAllBytes("tmp.bin");

// [2] Это не IO-операция, что то делается с буфером,
// что то считаем, нагрузка на прочитанное из файла
long counter = 0;
for (int i = 0; i < bytes.Length; i++)
    counter += bytes[i];

// Засекаем время
sw.Stop();

// Выводим время
System.Console.WriteLine("{0}, {1}ms",
    counter, sw.ElapsedMilliseconds);

System.Console.ReadLine();

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

А теперь фокус. Перезагружаем комп, запускаем первый раз - получаем время 36ms, запускаем второй, третий, четвёртый раз - получаем время 12ms.

3570k 4c/4t [no-ht, all locked] x64 release
SSD Intel 520 128Mb

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

И ровно эту же программку с этим же файликом нужно запустить на виртуальной системе.

Так вот это пример того, что запуск и повторный запуск может отличаться по времени, и очень сильно.

Что это даёт? А это даёт то, что можно понять время обращения к диску очень простым способом. И время не обращения к диску тоже можно узнать, собственно это повторный запуск, где повторный запуск к диску не обращается.

И тогда можно узнать чистое время работы программки, без IO-операций.

Зная эти времена, можно сравнить эти времена в разных системах.

P.P.S.: Самый первый раз программка запускается без исполнения вообще, т.е. запускаете, и закрываете через крестик. Тем самым сама программка запускает всю обвязку дот.нета и прочее, и сама же помещается в оперативку.

→ Ссылка