Files
feresaria/shell/ferese-settings/src/performance_tests.rs
T

172 lines
6.2 KiB
Rust

//! Opt-in, reproducible category/resize measurements. No hardware settings change.
use super::*;
use cosmic::Application;
use cosmic::iced::advanced::renderer::{Headless, Renderer as _};
use cosmic::iced::advanced::{Layout, Shell, clipboard, layout, mouse, renderer, widget::Tree};
use cosmic::iced::{Color, Event, Font, Pixels, Rectangle, Size, window};
fn fixture() -> App {
let source = std::env::var_os("FERESE_BENCH_CONFIG")
.map(|p| std::fs::read_to_string(p).unwrap())
.unwrap_or_else(|| include_str!("../../../packaging/config.kdl").into());
let (mut app, _) = App::init(
Core::default(),
(
"/unused/settings-performance.kdl".into(),
Snapshot::parse(source),
None,
None,
),
);
app.options_loaded(all_options::catalog());
app.connections.snapshot = Some(connections::performance_snapshot());
app.tray_apps = (0..12)
.map(|i| tray_controls::Application {
id: format!("app-{i}"),
title: format!("Application {i}"),
})
.collect();
app.displays = (0..3)
.map(|i| displays::Display {
connector: format!("DP-{}", i + 1),
identity: format!("Test display {i}"),
profile: None,
logical_width: Some(1920),
focused: i == 0,
current: Some(displays::Mode {
width: 3840,
height: 2160,
refresh: 60000,
}),
modes: vec![
displays::Mode {
width: 3840,
height: 2160,
refresh: 60000,
},
displays::Mode {
width: 2560,
height: 1440,
refresh: 60000,
},
],
})
.collect();
app
}
#[test]
#[ignore = "category/resize profile; requires the matching compositor schema binary"]
fn profile_all_categories_and_resizing() {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
let backend = std::env::var("FERESE_BENCH_BACKEND").unwrap_or_else(|_| "wgpu".into());
let mut renderer = runtime
.block_on(cosmic::Renderer::new(
Font::default(),
Pixels(14.),
Some(&backend),
))
.unwrap();
let scale = 2.;
for page in Page::ALL {
let mut app = fixture();
drop(app.update(Message::Page(page)));
let theme = app.native_palette.native_theme();
let mut tree: Option<Tree> = None;
for frame in 0..18 {
let scenario = if frame == 0 {
"cold"
} else if frame < 4 {
"warm"
} else if frame < 14 {
"resize"
} else {
"switch"
};
if frame >= 14 {
drop(app.update(Message::Page(Page::General)));
drop(app.update(Message::Page(page)));
}
let size = if (4..14).contains(&frame) && frame % 2 == 0 {
Size::new(631., 568.)
} else {
Size::new(1272., 760.)
};
let viewport = Rectangle::with_size(size);
let mut messages = Vec::new();
let started = std::time::Instant::now();
let mut view = app.page_view();
let tree = tree.get_or_insert_with(|| Tree::new(&view));
cosmic::iced::advanced::widget::tree::NAMED
.with(|named| *named.borrow_mut() = tree.take_all_named());
tree.diff(view.as_widget_mut());
let node = view.as_widget_mut().layout(
tree,
&renderer,
&layout::Limits::new(Size::ZERO, size),
);
cosmic::iced::advanced::widget::tree::NAMED.with(|named| named.borrow_mut().clear());
view.as_widget_mut().update(
tree,
&Event::Window(window::Event::RedrawRequested(std::time::Instant::now())),
Layout::new(&node),
mouse::Cursor::Unavailable,
&renderer,
&mut clipboard::Null,
&mut Shell::new(&mut messages),
&viewport,
);
let layout_us = started.elapsed().as_micros();
renderer.reset(viewport);
let started = std::time::Instant::now();
view.as_widget().draw(
tree,
&mut renderer,
&theme,
&renderer::Style {
text_color: Color::WHITE,
icon_color: Color::WHITE,
scale_factor: scale as f64,
},
Layout::new(&node),
mouse::Cursor::Unavailable,
&viewport,
);
let draw_us = started.elapsed().as_micros();
drop(view);
let started = std::time::Instant::now();
let pixels = Headless::screenshot(
&mut renderer,
Size::new((size.width * scale) as u32, (size.height * scale) as u32),
scale,
theme.cosmic().bg_color().into(),
);
let render_us = started.elapsed().as_micros();
if matches!(frame, 0 | 4 | 5)
&& let Some(dir) = std::env::var_os("FERESE_BENCH_IMAGES_DIR")
{
let path = PathBuf::from(dir);
std::fs::create_dir_all(&path).unwrap();
image::save_buffer(
path.join(format!("{page:?}-{frame}.png")),
&pixels,
(size.width * scale) as u32,
(size.height * scale) as u32,
image::ColorType::Rgba8,
)
.unwrap();
}
for message in messages {
drop(app.update(message));
}
eprintln!(
"AUDIT {}",
serde_json::json!({"backend":backend,"page":format!("{page:?}"),"frame":frame,"scenario":scenario,"width":size.width,"layout_us":layout_us,"draw_us":draw_us,"render_us":render_us})
);
}
}
}