zapretgui/tests/test_sidebar_startup_delays.py
loop-uh f402387851
All checks were successful
Zapret source guards / validate (push) Successful in 9s
Windows-сборка / Dev Dev 21.1.7.67 опубликован
Запуск: окно появляется один раз и сразу готовым, первые секунды без рывков
Окно показывается после сборки интерфейса, а не до неё: раньше Windows
выводила на экран пустое белое окно, и оно стояло так всё время сборки.
Между показом и первой отрисовкой окно скрыто от экрана средством Windows
(ui/window_first_frame.py), поэтому белой вспышки нет. Боковое меню целиком
и поле поиска строятся до показа, заголовки групп встают на место сразу —
меню больше не достраивается и не съезжает на глазах.

Фоновые задачи запуска идут по одной на общей дорожке StartupLane
(main/post_startup_threading.py), а не в своём потоке у каждой подсистемы:
в первые полторы секунды одновременно работали пять-семь потоков и по
очереди отбирали общий замок Python друг у друга и у окна. Свой поток
остался только у очередей, которые ждут сеть. То, что сразу видно на главной
странице (список профилей), считается первым; подсчёт частоты стратегий
вынесен в отдельный прогрев в конец очереди. Скрытые страницы собираются
заранее, только когда дорожка пуста и обход уже запущен.

Интервал переключения замка Python для видимого окна уменьшен с 1 до 0,5 мс:
Windows не ждёт меньше миллисекунды, поэтому 1 мс длился ~2 мс на каждое
обращение окна к своему коду, а интервал меньше 1 мс CPython округляет до
нуля.

Замеры на win10 (до → после): рывки в первые полторы секунды после
появления окна ~1150 мс → 96 мс; список профилей 960 → 140 мс; сборка
списков адресов 1097 → 18 мс; запуск winws2 1695 → 912 мс; сборка страницы
в GUI-потоке рядом с одним занятым фоновым потоком 2568 → 113 мс.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 01:41:53 +03:00

49 lines
2.2 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import inspect
import unittest
class SidebarStartupDelayTests(unittest.TestCase):
"""Боковое меню не достраивается таймерами после показа окна.
Замер на Windows: 16 пунктов меню, пять скрытых и поле поиска строятся за
~5 мс, пока фоновые потоки молчат. Отложенные на «после показа», они
попадали на одно время с фоновыми задачами запуска и из-за общего замка
Python занимали 116 + 356 + 30 мс, а окно при этом перестраивалось на
глазах у пользователя.
"""
def test_sidebar_has_no_deferred_build_stages(self) -> None:
import ui.navigation.sidebar_builder as sidebar_builder
for name in (
"SIDEBAR_SECONDARY_GROUPS_AFTER_INTERACTIVE_MS",
"SIDEBAR_SECONDARY_GROUP_STEP_MS",
"SIDEBAR_SEARCH_AFTER_INTERACTIVE_MS",
"SIDEBAR_HIDDEN_MODE_ITEMS_AFTER_INTERACTIVE_MS",
"_schedule_sidebar_search_after_interactive",
"_schedule_secondary_sidebar_groups_after_interactive",
"_schedule_hidden_mode_nav_items_after_interactive",
"_install_secondary_sidebar_groups",
"_install_hidden_mode_nav_items",
):
self.assertFalse(hasattr(sidebar_builder, name), name)
def test_init_navigation_does_not_wait_for_interactive_signal(self) -> None:
import ui.navigation.sidebar_builder as sidebar_builder
source = inspect.getsource(sidebar_builder.init_navigation)
self.assertNotIn("startup_interactive_ready", source)
self.assertIn("_install_sidebar_search(window)", source)
def test_startup_log_contract_has_no_sidebar_after_interactive_markers(self) -> None:
from main import startup_log_contract
for marker in startup_log_contract._AFTER_INTERACTIVE_MARKERS:
self.assertNotIn("Sidebar", marker)
self.assertNotIn("HiddenModeNav", marker)
if __name__ == "__main__":
unittest.main()