Я прошу прощения за такой заголовок, потому что современное ПО может быть медленным по множеству разных причин. Слепое использование одного объяснения без малейшего расследования — это программный аналог карго-культа. В этом посте рассматривается один пример того, почему современное ПО может быть мучительно медленным.
Я всего лишь хотел записать сорокасекундную озвучку простенького видео, поэтому запустил стандартное приложение Запись голоса (Voice Recorder) операционной системы Windows и нажал на кнопку записи. Казалось, что ничего не произошло.
Позже я проверил и оказалось, что программа выполняет запись. Я немного поэкспериментировал и выяснил, что в первый раз, когда я начинал запись после запуска Записи голоса, её реакции иногда предшествовала долгая задержка. Двадцатисекундная задержка при записи сорокасекундного клипа — довольно низкий КПД. Это расстроило меня настолько, что я захотел разобраться, почему так получается, и запустил трассировку ETW.
Современное ПО любит использовать дополнительные процессы, поэтому меня не удивило то, что самым нагруженным процессом был не SoundRec.exe, а «RuntimeBroker.exe <Microsoft.WindowsSoundRecorder>». Взглянув на его использование процессора, я заметил, что нагрузка повышается, как только я запускаю Запись голоса, даже до того, как я нажму на кнопку записи.
RuntimeBroker сильно нагружал процессор и тратил бОльшую часть своего времени в одном потоке, который активно выполнял запросы результатов просмотра какой-то папки:
Следующим я посмотрел на график файлового ввода-вывода, чтобы понять, что за папку он сканирует. Результаты оказались немного разрозненными (возможно, иногда сканирование завершалось слишком рано?), но выяснилось, что RuntimeBroker сканировал (в том же потоке) часть моей папки с документами или её целиком.
Тем временем, ещё один поток RuntimeBroker тратил немного времени в propsys.dll!TryGetFileTypeAssocFromStateRepository.
Я предположил, что цель всего этого заключалась в том, чтобы найти все аудиофайлы в моей папке документов, чтобы заполнить список предыдущих записей. И когда я начал следить за этим, то выяснил, что при запуске Записи голоса программа после существенной паузы заполняет список записей. Если я нажимал кнопку записи после заполнения списка, запись начиналась мгновенно.
<сарказм>Очевидно, в этом случае ошибку совершил пользователь. Если бы я терпеливо подождал, пока мой медленный компьютер будет готов, то при начале записи программа была бы быстрой и отзывчивой.</сарказм>
Безумие этой задержки из-за сканирования папки с документами в том, что Запись голоса, похоже, игнорирует все аудиофайлы, не находящиеся в папке Аудиозаписи. Всё это сканирование происходит впустую?
По поводу всего этого у меня есть некоторые соображения…
Я недостаточно знаю о WinRT и RuntimeBroker, чтобы осознанно говорить о причинах проблемы, но уверенно скажу, что если приложение-диктофон не способно мгновенно записывать голос на современном оборудовании, то в архитектуре определённо имеются изъяны.
Всё тестирование выполнялось на Windows 10, 21H2. В Windows 11 приложение Запись голоса заменено на Windows Sound Recorder, код которого полностью переписан. Похоже, в переписанной версии этого бага нет, так что ура, прогресс, но я опасаюсь за мир ПО, в котором приложения не исправляются, а переписываются.
Я всего лишь хотел записать сорокасекундную озвучку простенького видео, поэтому запустил стандартное приложение Запись голоса (Voice Recorder) операционной системы Windows и нажал на кнопку записи. Казалось, что ничего не произошло.
Позже я проверил и оказалось, что программа выполняет запись. Я немного поэкспериментировал и выяснил, что в первый раз, когда я начинал запись после запуска Записи голоса, её реакции иногда предшествовала долгая задержка. Двадцатисекундная задержка при записи сорокасекундного клипа — довольно низкий КПД. Это расстроило меня настолько, что я захотел разобраться, почему так получается, и запустил трассировку ETW.
Современное ПО любит использовать дополнительные процессы, поэтому меня не удивило то, что самым нагруженным процессом был не SoundRec.exe, а «RuntimeBroker.exe <Microsoft.WindowsSoundRecorder>». Взглянув на его использование процессора, я заметил, что нагрузка повышается, как только я запускаю Запись голоса, даже до того, как я нажму на кнопку записи.
RuntimeBroker сильно нагружал процессор и тратил бОльшую часть своего времени в одном потоке, который активно выполнял запросы результатов просмотра какой-то папки:
Следующим я посмотрел на график файлового ввода-вывода, чтобы понять, что за папку он сканирует. Результаты оказались немного разрозненными (возможно, иногда сканирование завершалось слишком рано?), но выяснилось, что RuntimeBroker сканировал (в том же потоке) часть моей папки с документами или её целиком.
Тем временем, ещё один поток RuntimeBroker тратил немного времени в propsys.dll!TryGetFileTypeAssocFromStateRepository.
Я предположил, что цель всего этого заключалась в том, чтобы найти все аудиофайлы в моей папке документов, чтобы заполнить список предыдущих записей. И когда я начал следить за этим, то выяснил, что при запуске Записи голоса программа после существенной паузы заполняет список записей. Если я нажимал кнопку записи после заполнения списка, запись начиналась мгновенно.
<сарказм>Очевидно, в этом случае ошибку совершил пользователь. Если бы я терпеливо подождал, пока мой медленный компьютер будет готов, то при начале записи программа была бы быстрой и отзывчивой.</сарказм>
Безумие этой задержки из-за сканирования папки с документами в том, что Запись голоса, похоже, игнорирует все аудиофайлы, не находящиеся в папке Аудиозаписи. Всё это сканирование происходит впустую?
Жалобы и вопросы
По поводу всего этого у меня есть некоторые соображения…
- Команда
dir /s
может отсканировать мою папку с документами менее чем за две секунды. Почему у RuntimeBroker сканирование занимает в 5-10 раз больше времени? В этой папке у меня всего около 44 тысяч документов, что за фильтрация используется, которая добавляет на каждый файл лишние полмиллиона тактов? - Зачем RuntimeBroker сканирует всю папку с документами, если Запись голоса игнорирует аудиофайлы, не находящиеся в подпапке «Аудиозаписи»? Это проблема WinRT или Записи голоса?
- Что происходит у пользователей, не имеющих SSD и 32 ГБ ОЗУ? В моём случае структура папки «Документы» целиком кэширована в память, поэтому для сканирования не требуется активность диска, но некоторым пользователям повезло меньше. Если у этих пользователей больше файлов и они хранятся на жёстком диске, то их остаётся только пожалеть.
- При выполнении операции, не позволяющей пользователю работать с приложением, честнее использовать шкалу прогресса или курсор ожидания. UI Записи голоса всегда реагировал на взаимодействия, но на самом деле это было ложью — кнопка записи должна быть отключена, пока приложение не готово.
- Почему сканирование папки с документами иногда выполняется только для части папки? У RuntimeBroker есть какое-то кэширование?
Я недостаточно знаю о WinRT и RuntimeBroker, чтобы осознанно говорить о причинах проблемы, но уверенно скажу, что если приложение-диктофон не способно мгновенно записывать голос на современном оборудовании, то в архитектуре определённо имеются изъяны.
Всё тестирование выполнялось на Windows 10, 21H2. В Windows 11 приложение Запись голоса заменено на Windows Sound Recorder, код которого полностью переписан. Похоже, в переписанной версии этого бага нет, так что ура, прогресс, но я опасаюсь за мир ПО, в котором приложения не исправляются, а переписываются.