# App и Perf модули ## `src/app.rs` — GlintApp Точка входа Iced-приложения. Держит состояние и реализует `update`/`view`. ### `GlintApp` ```rust pub struct GlintApp { pub doc: Document<'static>, pub vdom_roots: Vec>, pub rhei: RheiContext, } ``` - `doc` — оригинальный Document (стили, переменные, tracker) - `vdom_roots` — результат последнего evaluate_vdom (_incr) - `rhei` — Rhai-движок с кэшированными AST ### `update(&mut self, message: Message) -> iced::Task` Обработка сообщений от Iced: | Message | Действие | |---------|----------| | `WindowScrolled(y)` | Установить `__scroll_y`, вызвать `on_variable_changed` | | `ScrollableScrolled(id, y)` | Установить `__scroll_{id}`, вызвать `on_variable_changed` | | `EventTriggered(script)` | `execute_action()`, затем diff переменных для поиска изменившихся | | `InputChanged(var, val)` | Установить переменную, вызвать `on_variable_changed` | | `ToggleChanged(var, val)` | Установить `Bool`, вызвать `on_variable_changed` | | `SliderChanged(var, val)` | Установить `Float`, вызвать `on_variable_changed` | После обработки сообщения: 1. `tracker.take_dirty_set()` — получить dirty элементы 2. `evaluate_vdom_incr()` — пересчитать VDOM 3. Сохранить в `self.vdom_roots` **Perf:** VDOM фаза замеряется `PerfScope::new("vdom")`. ### `view(&self) -> iced::Element` Построить Iced-виджеты из `self.vdom_roots`: 1. Собрать scroll_positions из `__scroll_*` переменных 2. Для каждого root: `render_element()` → push в column 3. Наложить global fixed/absolute/sticky слои 4. Вернуть `container(layout).into()` **Perf:** Render фаза замеряется `PerfScope::new("render")`. В конце `perf::print_frame()` — вывод в stderr. --- ## `src/perf.rs` — Performance Monitoring Система замера времени по фазам (VDOM, Style, Render). Включение: флаг `--perf`. ### `PerfReport` ```rust pub struct PerfReport { pub vdom_eval: f64, // ms pub style: f64, // ms pub render: f64, // ms pub total: f64, // ms } ``` Хранится в `thread_local!` `RefCell`. ### `PerfScope` Drop-guard: замеряет время от создания до разрушения. ```rust pub struct PerfScope { name: &'static str, start: Instant, } ``` При `drop()`: добавляет elapsed ms к соответствующему полю `PerfReport`. Имена: `"vdom"`, `"style"`, `"render"`. ### Функции | Функция | Описание | |---------|----------| | `set_enabled(bool)` | Включить/выключить замеры | | `is_enabled() -> bool` | Проверить состояние | | `report_and_reset() -> Option` | Собрать отчёт, проверить >16ms threshold | | `reset()` | Обнулить PerfReport | | `print_frame()` | Вызвать report_and_reset + сброс, напечатать в stderr | ### Пример вывода ``` [perf] VDOM: 6.63ms | Style: 0.26ms | Render: 7.19ms | Total: 14.08ms [perf] VDOM: 13.26ms | Style: 0.52ms | Render: 7.18ms | Total: 20.95ms ⚠️ Frame budget exceeded! 20.95ms > 16ms ``` ### Точки инструментирования | Файл | Фаза | Место | |------|------|-------| | `app.rs:update` | vdom | Вокруг `evaluate_vdom_incr()` | | `app.rs:view` | render | Вся функция `view()` | | `style.rs:compute_cached` | style | Внутри `StyleSheet::compute_cached()` |