diff --git a/ui/dr-ui/src/lib.rs b/ui/dr-ui/src/lib.rs index 3ef9090..ba2da58 100644 --- a/ui/dr-ui/src/lib.rs +++ b/ui/dr-ui/src/lib.rs @@ -975,13 +975,36 @@ pub fn run(paths: Vec) -> Result<()> { log::debug!("could not set the xdg app id: {e}"); } + // Everything between here and `window.run()` at the bottom happens before + // the event loop exists, and on Android that is not merely a slow start: + // `android_main` calls this, and nothing drains the activity's input + // channel until Slint reaches its first `poll_events` inside `run()`. Five + // seconds of it is an ANR, over a window that has never painted. + // + // So the two phases that touch a driver or a disk are timed, and so is the + // whole of it. There is no profiler on the tablet and no way to attach one + // to a launch: a line in the log file is the only measurement anybody gets, + // and without it the next regression here is guesswork about which of half + // a dozen candidates it was. + let launch_began = std::time::Instant::now(); + // Before the window, and it has to be: this selects the Slint backend, and // creating a window selects one for us. See `shared_gpu`. The device is // shared by demosaic, the adjust pass and the compositor; without one the // app still browses through the preview path, just without develop. + // + // Timed rather than moved: this is a Vulkan instance, an adapter + // enumeration and a device request, none of which can be deferred on the + // desktop because the backend must be chosen before a window exists. On + // Android it could be — nothing shares that device with the compositor + // (TD-1) — but "could be" is not "costs enough to be worth it", and this + // line is what will say which. let gpu = shared_gpu(); + log::info!("gpu opened in {} ms", launch_began.elapsed().as_millis()); + let before_window = std::time::Instant::now(); let window = AppWindow::new()?; + log::info!("window built in {} ms", before_window.elapsed().as_millis()); // The version the About page shows. Taken from the crate rather than // passed in, so it is the version of the code that is running and cannot // be set to something else by a caller. @@ -3152,6 +3175,15 @@ pub fn run(paths: Vec) -> Result<()> { show(&window); } + // The figure that matters, because it is the one the input dispatcher is + // counting against. Anything approaching five seconds here is an ANR on the + // next Android launch whatever the phases above say, and anything that + // pushes it up belongs on a worker. + log::info!( + "startup: {} ms to the event loop", + launch_began.elapsed().as_millis() + ); + window.run()?; Ok(()) }