- PVSM.RU - https://www.pvsm.ru -
Забавная проблема #22900 [1] на этой неделе привлекла особое внимание пользователей Github.
Подробное описание проблемы — в репозитории редактора кода Visual Studio Code (vscode [2]). Open source разработчик Джо Лисс (Jo Liss) известна как создатель Broccoli и других свободных библиотек. На странице проекта она обратила внимание, что Visual Studio Code использует 13% вычислительных ресурсов процессора, если окно находится в фокусе. Из-за этого впустую расходуется заряд аккумулятора на ноутбуке. Что могло бы быть причиной столь странного поведения программы?
Джо Лисс предположила, что активность CPU связана с рендерингом мерцания курсора — изменение состояния курсора происходит два раза в секунду, то есть каждые 500 мс (2 fps).
Для воспроизведения проблемы следует проделать следующие шаги:
Ему кому-то нужно, вот таймлайн записи в Developer Tools: TimelineRawData-20170321T114212.json.zip [4] (см. скриншот выше).
Если приблизить на один фрейм, то можно заметить, что несмотря на частоту мерцания 2 fps, основной поток выполняет некую работу на 60 fps, то есть рендерит что-то каждые 16 мс.
Если ещё больше приблизить, то становится видна конкретная большая работа, которую выполняет рендеринг курсора на 60 кадрах/с. Это периодические циклы «Update Layer Tree» / «Paint» / «Composite Layers», то есть обновление дерева слоёв
Разработчик обращает внимание, что в других приложениях macOS Sierra 10.12.3, в том числе Chrome и TextEdit, курсор мерцает без заметного потребления ресурсов CPU.
Пользователи редактора Visual Studio Code могут отключить мерцание курсора в программе. В этом случае потребление CPU снижается до 0%. Циклы "Update Layer Tree" / "Paint" / "Composite Layers" всё равно работают, но только каждые 500 мс, а не каждые 16 мс.
"editor.cursorBlinking": "solid"
Этот забавный глюк в Visual Studio Code напоминает классическую проблему с тормозным индикатором [5] в npm. В версии npm 3.5.2 при включенном индикаторе хода выполнения операции эта операция выполнялась примерно на 50% медленнее, чем без индикатора.
$ rm -r node_modules
$ npm set progress=false
$ time npm install
npm install 19.91s user 2.66s system 71% cpu 31.667 total
$ rm -r node_modules
$ npm set progress=true
$ time npm install
npm install 33.26s user 3.19s system 74% cpu 48.733 total
Конечно, потребление ресурсов CPU при мерцании курсора имеет совсем иные причины, чем замедление npm с активным индикатором прогресса. О причинах проблем с курсорос можно догадаться, если посмотреть на почти такой же баг [6] с анимацией ключевого кадра CSS в браузере Chrome. Там разработчики пишут, что в JavaScript мерцающий курсор отнимает нормальные 1,2% ресурсов CPU, а в CSS почему-то в 6 раз больше, то есть 7-8%.
Код вроде корректный:
@keyframes monaco-cursor-blink {
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.cursor-blink {
animation: monaco-cursor-blink 1s step-start 0s infinite;
}
Но проблема в том, что движок Chromium принудительно переводит эту анимацию в 60 fps, заставляя выполнять работу каждые 16 мс.
Так вот, редактор Visual Studio Code, очевидно, использует самый логичный подход для реализации функции мерцающего курсора: это функция step
с анимацией ключевого кадра CSS. А этот баг в Chromium до сих пор не исправили полностью [7], хотя он тянется уже больше двух лет. Так что Chrome осуществляет полный цикл рендеринга каждые 16 мс, как и положено для 60 кадров в секунду. Возможно, теперешнее обсуждение позволит привлечь внимание к старому багу — и у разработчиков наконец-то дойдут руки до него.
Разработчики Visual Studio Code признались [8], что изначально эта функция была реализована на JavaScript, но примерно год назад они переключились на CSS. В текущей реализации если окно не в фокусе, то анимация деактивируется и излишнего потребления ресурсов процессора не происходит, но вот с активным окном действительно проблема. Разработчики считают, что в такой ситуации есть смысл вернуться с CSS обратно на JS.
Коллеги советуют [9] подумать также над тем, чтобы реализовать курсор в виде анимированного gif'а. Можно генерировать такой файл автоматически, в зависимости от цветового оформления редактора. Правда, здесь может быть сложность с зуммированием: всё-таки растровая графика станет расплывчатой при зуммировании.
Но в конце концов разработчики из Microsoft всё-таки решили вернуться на старый добрый JS-метод setInterval для мерцания курсора — и потребление CPU сразу снизилось в несколько раз [10].
Автор: alizar
Источник [11]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/css/250921
Ссылки в тексте:
[1] #22900: https://github.com/Microsoft/vscode/issues/22900
[2] vscode: https://github.com/Microsoft/vscode
[3] 5-7%: https://github.com/Microsoft/vscode/issues/22900#issuecomment-289055579
[4] TimelineRawData-20170321T114212.json.zip: https://github.com/Microsoft/vscode/files/857980/TimelineRawData-20170321T114212.json.zip
[5] проблему с тормозным индикатором: https://github.com/npm/npm/issues/8826#issuecomment-155762361
[6] почти такой же баг: https://bugs.chromium.org/p/chromium/issues/detail?id=500259
[7] до сих пор не исправили полностью: https://bugs.chromium.org/p/chromium/issues/detail?id=361587
[8] признались: https://github.com/Microsoft/vscode/issues/22900#issuecomment-288804251
[9] советуют: https://github.com/Microsoft/vscode/issues/22900#issuecomment-288835419
[10] снизилось в несколько раз: https://github.com/Microsoft/vscode/issues/22900#issuecomment-289058838
[11] Источник: https://geektimes.ru/post/287342/
Нажмите здесь для печати.