Skip to content

Commit da196ac

Browse files
committed
perf(flow-chat): stabilize historical session rendering
1 parent 948aa51 commit da196ac

28 files changed

Lines changed: 5214 additions & 374 deletions

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@
7272
"e2e:test:l1": "cross-env BITFUN_E2E_APP_MODE=debug pnpm --dir tests/e2e run test:l1",
7373
"e2e:test:smoke": "cross-env BITFUN_E2E_APP_MODE=debug pnpm --dir tests/e2e run test:smoke",
7474
"e2e:test:chat": "cross-env BITFUN_E2E_APP_MODE=debug pnpm --dir tests/e2e run test:chat",
75-
"e2e:test:perf:debug": "cross-env BITFUN_E2E_APP_MODE=debug pnpm --dir tests/e2e run test:perf",
76-
"e2e:test:perf:release-fast": "cross-env BITFUN_E2E_APP_MODE=release-fast pnpm --dir tests/e2e run test:perf"
75+
"e2e:test:perf:debug": "cross-env BITFUN_E2E_APP_MODE=debug E2E_LOG_LEVEL=warn pnpm --dir tests/e2e run test:perf",
76+
"e2e:test:perf:release-fast": "cross-env BITFUN_E2E_APP_MODE=release-fast E2E_LOG_LEVEL=warn pnpm --dir tests/e2e run test:perf"
7777
},
7878
"devDependencies": {
7979
"@tauri-apps/cli": "^2.10.0",

src/apps/desktop/src/theme.rs

Lines changed: 150 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Theme System
22
33
use std::sync::{OnceLock, RwLock};
4-
use std::time::Instant;
4+
use std::time::{Duration, Instant};
55

66
use bitfun_core::infrastructure::try_get_path_manager_arc;
77
use bitfun_core::service::config::types::GlobalConfig;
@@ -18,11 +18,106 @@ const AGENT_COMPANION_WINDOW_MAX_WIDTH: f64 = 360.0;
1818
const AGENT_COMPANION_WINDOW_MAX_HEIGHT: f64 = 240.0;
1919
const AGENT_COMPANION_WINDOW_MARGIN: i32 = 64;
2020
const AGENT_COMPANION_WINDOW_EDGE_MARGIN: f64 = 8.0;
21+
#[cfg(target_os = "windows")]
22+
const WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MAX: Duration = Duration::from_millis(150);
23+
#[cfg(target_os = "windows")]
24+
const WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MIN: Duration = Duration::from_millis(16);
25+
#[cfg(target_os = "windows")]
26+
const WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_POLL: Duration = Duration::from_millis(8);
2127

2228
static AGENT_COMPANION_WINDOW_OPS: OnceLock<tokio::sync::Mutex<()>> = OnceLock::new();
2329
static AGENT_COMPANION_WINDOW_LAST_POSITION: OnceLock<RwLock<Option<tauri::LogicalPosition<f64>>>> =
2430
OnceLock::new();
2531

32+
#[cfg(target_os = "windows")]
33+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
34+
enum WindowsMaximizeShowWaitAction {
35+
Ready,
36+
Sleep(Duration),
37+
TimedOut,
38+
}
39+
40+
#[cfg(target_os = "windows")]
41+
fn windows_maximize_show_wait_action(
42+
is_maximized: Option<bool>,
43+
elapsed: Duration,
44+
) -> WindowsMaximizeShowWaitAction {
45+
if is_maximized == Some(true) && elapsed >= WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MIN {
46+
return WindowsMaximizeShowWaitAction::Ready;
47+
}
48+
49+
if elapsed >= WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MAX {
50+
return WindowsMaximizeShowWaitAction::TimedOut;
51+
}
52+
53+
let target_wait = if is_maximized == Some(true) {
54+
WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MIN
55+
} else {
56+
WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MAX
57+
};
58+
WindowsMaximizeShowWaitAction::Sleep(
59+
target_wait
60+
.saturating_sub(elapsed)
61+
.min(WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_POLL),
62+
)
63+
}
64+
65+
#[cfg(target_os = "windows")]
66+
fn read_windows_maximize_state(
67+
window: &tauri::WebviewWindow,
68+
logged_error: &mut bool,
69+
) -> Option<bool> {
70+
match window.is_maximized() {
71+
Ok(is_maximized) => Some(is_maximized),
72+
Err(error) => {
73+
if !*logged_error {
74+
warn!(
75+
"Failed to read main window maximize state during startup show wait: {}",
76+
error
77+
);
78+
*logged_error = true;
79+
}
80+
None
81+
}
82+
}
83+
}
84+
85+
#[cfg(target_os = "windows")]
86+
fn wait_for_windows_maximize_before_show(window: &tauri::WebviewWindow) -> &'static str {
87+
let started_at = Instant::now();
88+
let mut logged_error = false;
89+
90+
loop {
91+
match windows_maximize_show_wait_action(
92+
read_windows_maximize_state(window, &mut logged_error),
93+
started_at.elapsed(),
94+
) {
95+
WindowsMaximizeShowWaitAction::Ready => return "ready",
96+
WindowsMaximizeShowWaitAction::TimedOut => return "timeout",
97+
WindowsMaximizeShowWaitAction::Sleep(duration) => std::thread::sleep(duration),
98+
}
99+
}
100+
}
101+
102+
#[cfg(target_os = "windows")]
103+
async fn wait_for_windows_maximize_before_show_async(
104+
window: &tauri::WebviewWindow,
105+
) -> &'static str {
106+
let started_at = Instant::now();
107+
let mut logged_error = false;
108+
109+
loop {
110+
match windows_maximize_show_wait_action(
111+
read_windows_maximize_state(window, &mut logged_error),
112+
started_at.elapsed(),
113+
) {
114+
WindowsMaximizeShowWaitAction::Ready => return "ready",
115+
WindowsMaximizeShowWaitAction::TimedOut => return "timeout",
116+
WindowsMaximizeShowWaitAction::Sleep(duration) => tokio::time::sleep(duration).await,
117+
}
118+
}
119+
}
120+
26121
fn agent_companion_window_ops() -> &'static tokio::sync::Mutex<()> {
27122
AGENT_COMPANION_WINDOW_OPS.get_or_init(|| tokio::sync::Mutex::new(()))
28123
}
@@ -568,12 +663,18 @@ fn show_main_window_for_startup(
568663
);
569664
}
570665
let show_delay_started_at = Instant::now();
571-
std::thread::sleep(std::time::Duration::from_millis(150));
666+
let show_wait_outcome = wait_for_windows_maximize_before_show(window);
572667
startup_trace.record_elapsed_step(
573668
"native_window",
574669
"windows_show_after_maximize_wait",
575670
show_delay_started_at,
576671
);
672+
debug!(
673+
"Main window startup show step completed: step=wait_for_maximize_state outcome={} duration_ms={} since_create_start_ms={}",
674+
show_wait_outcome,
675+
show_delay_started_at.elapsed().as_millis(),
676+
total_started_at.elapsed().as_millis()
677+
);
577678
}
578679

579680
let show_started_at = Instant::now();
@@ -915,7 +1016,13 @@ pub async fn show_main_window(app: tauri::AppHandle) -> Result<(), String> {
9151016
step_started_at.elapsed().as_millis()
9161017
);
9171018

918-
tokio::time::sleep(std::time::Duration::from_millis(150)).await;
1019+
let wait_started_at = Instant::now();
1020+
let show_wait_outcome = wait_for_windows_maximize_before_show_async(&main_window).await;
1021+
debug!(
1022+
"Main window show step completed: step=wait_for_maximize_state outcome={} duration_ms={}",
1023+
show_wait_outcome,
1024+
wait_started_at.elapsed().as_millis()
1025+
);
9191026
}
9201027

9211028
let step_started_at = Instant::now();
@@ -954,3 +1061,43 @@ pub async fn show_main_window(app: tauri::AppHandle) -> Result<(), String> {
9541061
);
9551062
Ok(())
9561063
}
1064+
1065+
#[cfg(test)]
1066+
mod tests {
1067+
use super::*;
1068+
1069+
#[cfg(target_os = "windows")]
1070+
#[test]
1071+
fn windows_maximize_show_wait_releases_when_maximized() {
1072+
assert_eq!(
1073+
windows_maximize_show_wait_action(Some(true), Duration::ZERO),
1074+
WindowsMaximizeShowWaitAction::Sleep(WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_POLL)
1075+
);
1076+
assert_eq!(
1077+
windows_maximize_show_wait_action(Some(true), WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MIN),
1078+
WindowsMaximizeShowWaitAction::Ready
1079+
);
1080+
}
1081+
1082+
#[cfg(target_os = "windows")]
1083+
#[test]
1084+
fn windows_maximize_show_wait_polls_until_max_wait() {
1085+
assert_eq!(
1086+
windows_maximize_show_wait_action(Some(false), Duration::from_millis(20)),
1087+
WindowsMaximizeShowWaitAction::Sleep(WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_POLL)
1088+
);
1089+
assert_eq!(
1090+
windows_maximize_show_wait_action(None, Duration::from_millis(148)),
1091+
WindowsMaximizeShowWaitAction::Sleep(Duration::from_millis(2))
1092+
);
1093+
}
1094+
1095+
#[cfg(target_os = "windows")]
1096+
#[test]
1097+
fn windows_maximize_show_wait_times_out_at_original_bound() {
1098+
assert_eq!(
1099+
windows_maximize_show_wait_action(Some(false), WINDOWS_STARTUP_MAXIMIZE_SHOW_WAIT_MAX),
1100+
WindowsMaximizeShowWaitAction::TimedOut
1101+
);
1102+
}
1103+
}

0 commit comments

Comments
 (0)