ВозможностиЦеныДокументацияБлог
Получить mote
← Блог
Разработка·21 августа 2026 г.·5 мин чтения

Как мы добились нулевой загрузки процессора, когда приложение просто открыто

Редактор открыт весь день, но на самом деле печатают в нём лишь часть этого времени. В остальное время mote не планирует ни кадры, ни таймеры, и это контролируется на двух уровнях: проверкой кода и измерениями на реальном устройстве.

m
mote
Результат одного запуска проверки. Документ размером 100 КБ открыт в dev-варианте, а измерения выполнены на реальном GPU: за 10 секунд после появления окна отрисовано 0 кадров, а загрузка CPU в режиме простоя составляет 0,10 %.
Результат одного запуска проверки. Документ размером 100 КБ открыт в dev-варианте, а измерения выполнены на реальном GPU: за 10 секунд после появления окна отрисовано 0 кадров, а загрузка CPU в режиме простоя составляет 0,10 %.

Редактор — приложение, которое дольше всего остаётся открытым на ноутбуке. Но непосредственно на письмо уходит не так много времени. Большую часть времени он просто тихо висит открытым, пока вы занимаетесь другими делами.

Поэтому в mote установили один принцип.

Если документ не меняется и анимации нет, ничего не делать.

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

Если ничего не происходит, кадров тоже 0

По одной лишь загрузке CPU трудно понять, действительно ли приложение бездействует. При каждом измерении значение колеблется, а после округления легко превращается в 0.

Поэтому в mote сначала смотрят на количество кадров. Если в течение 10 секунд после появления окна документ не меняется, число отрисованных кадров должно быть ровно 0. Приложение считает их самостоятельно, и если отрисован хотя бы один кадр, код не объединяется.

Даже если число кадров равно 0, расслабляться нельзя. В невидимой части приложения потоки могут продолжать пробуждаться. Поэтому мы также записываем, сколько раз в секунду пробуждаются все потоки процесса. Пока мы только накапливаем базовые показатели, поэтому разработку не блокируем лишь из-за этого значения.

Единственное исключение — мигание каретки. Мы не используем повторяющийся таймер: после одного мигания следующее действие планируется заново. Как только окно теряет фокус, мигание сразу прекращается. Бюджет загрузки CPU в режиме простоя с учётом каретки составляет 0,3 %.

Мы не рассматриваем производительность в режиме простоя отдельно от всего остального. Если откладывать отрисовку, количество кадров легко свести к 0, но введённые символы могут появляться с задержкой. Поэтому мы одновременно проверяем задержку ввода с клавиатуры, скорость запуска и память. Если превышен хотя бы один лимит, код не объединяется.

Жёсткие показатели в таблице бюджетов — 0 кадров в режиме простоя / 10 s, загрузка CPU в режиме простоя 0,3 %, измеренная снаружи задержка клавиша→пиксель p95 33,4 ms, измеренное внутри время обработки клавиши p95 4 ms, наша доля холодного запуска 10 ms, наша доля памяти 8 MB. В самой нижней строке указаны четыре условия измерения
Жёсткие показатели в таблице бюджетов — 0 кадров в режиме простоя / 10 s, загрузка CPU в режиме простоя 0,3 %, измеренная снаружи задержка клавиша→пиксель p95 33,4 ms, измеренное внутри время обработки клавиши p95 4 ms, наша доля холодного запуска 10 ms, наша доля памяти 8 MB. В самой нижней строке указаны четыре условия измерения

Один раз в коде, один раз на реальном устройстве

Со временем принципы размываются. Поэтому мы проверяем их дважды.

Сначала проверяем код. Мы автоматически ищем повторяющиеся таймеры, бесконечные тики, опросы, которые снова и снова засыпают и пробуждаются, а также код, без необходимости перечитывающий файл целиком. При обнаружении такого кода CI останавливается. Если исключение действительно необходимо, прямо над кодом нужно объяснить, почему эта работа завершается.

Затем проводим измерения на реальном устройстве. При этом соблюдаем четыре условия.

Измерения проводятся на реальном экране с GPU. Указатель находится за пределами окна. Используется настоящая шина сеанса, а кадры учитываются непосредственно в момент отрисовки.

Эти условия появились после реальных сбоев. Однажды только из-за того, что указатель находился над окном, в режиме простоя возникло 150 кадров. В изолированном сеансе запуск задерживался на несколько секунд, потому что инструментарий ожидал ответа. А при использовании счётчика кадров, сообщавшего значения с задержкой, кадры стартового экрана иногда попадали в интервал простоя.

Память мы тоже не оцениваем по абсолютному значению. Объём памяти, занимаемый инструментарием и графическим драйвером, может отличаться на десятки МБ в зависимости от окружения.

Вместо этого за точку отсчёта берётся пустой документ. Мы смотрим только на то, насколько больше памяти используется при открытии документа по сравнению с пустым документом. В недавнем измерении пустой документ использовал 116 МБ, а документ размером 100 КБ — 120 МБ. Дополнительный расход памяти mote составил 4 МБ, что укладывается в бюджет 8 МБ.

С самого начала мы измеряли не так. Однажды казалось, что бюджет памяти превышен, но выяснилось, что выросло базовое потребление памяти средой выполнения, а не приложением. С того дня вместо абсолютного значения мы начали измерять «то, сколько добавила наша функция».

Экран с открытым в режиме live 100 KB-образцом, который используется проверкой, — нижняя строка состояния насчитывает 20 584 слова и 96 513 символов. Разница между этим документом и пустым документом — это та самая «наша доля», о которой говорится в бюджете
Экран с открытым в режиме live 100 KB-образцом, который используется проверкой, — нижняя строка состояния насчитывает 20 584 слова и 96 513 символов. Разница между этим документом и пустым документом — это та самая «наша доля», о которой говорится в бюджете

Во время разработки количество активных таймеров также отображается на экране. Если оно не равно 0, об этом можно узнать сразу, ещё до коммита.

Автоматическое сохранение тоже следует этому принципу. Таймер устанавливается один раз только после изменения документа и удаляется по завершении сохранения. Приложение не пробуждается периодически, чтобы проверить: «Что-нибудь изменилось?»

Эти цифры нужны не для победы над конкурентами

Сначала мы хотели представить производительность в режиме простоя как преимущество перед Typora. Но непосредственные измерения показали, что это не так.

На том же устройстве и в тех же условиях загрузка CPU у Typora в режиме простоя составляла 0,1 %. Практически столько же, сколько у mote. Подтверждённая разница была у Obsidian с 0,8 % и MarkText с 0,6 %.

Мы также однажды указали неверные данные. Некоторое время в документе было написано: «Когда Typora остаётся открытой, она использует CPU». Однако показатель 34,6 %, приведённый в качестве доказательства, относился не к Typora, а к apostrophe. После повторной проверки мы сразу исправили эту фразу.

0 кадров в режиме простоя — это не заявление, направленное против конкурентов. Это дисциплина, которой придерживается сам mote. Если в приложении нет постоянно повторяющейся работы, мы всегда можем объяснить, что именно оно делает в данный момент.

Из-за этого принципа от кое-чего пришлось отказаться

Часто мы не можем воспользоваться удобным способом.

Вместо периодической проверки того, не изменился ли файл извне, приходится получать уведомления об изменениях от операционной системы. Вместо передачи формул в веб-представление мы создали собственный движок компоновки. Анимации тоже не могут работать непрерывно. У каждого движения есть начало и конец, а после завершения оно должно полностью остановиться.

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

Ничего не делать, когда ничего не происходит.

В mote это не функция, а принцип, которому должна соответствовать каждая функция.

← РанееПочему мы выбрали модель «одна покупка — все версии 1.x»Позже →Почему вместо слов «лёгкий» мы публикуем цифры
Следите за новостями через RSS.
Оставьте только текст
Русский
© 2026 mote