diff --git a/Cargo.lock b/Cargo.lock index 1d8b7d874a..744c01f00b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7868,21 +7868,6 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" -[[package]] -name = "performance" -version = "0.1.0" -dependencies = [ - "anyhow", - "collections", - "gpui", - "log", - "schemars", - "serde", - "settings", - "util", - "workspace", -] - [[package]] name = "perplexity" version = "0.1.0" @@ -14275,7 +14260,6 @@ dependencies = [ "outline_panel", "parking_lot", "paths", - "performance", "profiling", "project", "project_panel", diff --git a/Cargo.toml b/Cargo.toml index f546cd30b8..eea71ca376 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,6 @@ members = [ "crates/outline", "crates/outline_panel", "crates/paths", - "crates/performance", "crates/picker", "crates/prettier", "crates/project", @@ -246,7 +245,6 @@ open_ai = { path = "crates/open_ai" } outline = { path = "crates/outline" } outline_panel = { path = "crates/outline_panel" } paths = { path = "crates/paths" } -performance = { path = "crates/performance" } picker = { path = "crates/picker" } plugin = { path = "crates/plugin" } plugin_macros = { path = "crates/plugin_macros" } diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index b726dabf77..2157f97634 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -6,7 +6,7 @@ use std::{ path::{Path, PathBuf}, rc::{Rc, Weak}, sync::{atomic::Ordering::SeqCst, Arc}, - time::{Duration, Instant}, + time::Duration, }; use anyhow::{anyhow, Result}; @@ -142,12 +142,6 @@ impl App { self } - /// Sets a start time for tracking time to first window draw. - pub fn measure_time_to_first_window_draw(self, start: Instant) -> Self { - self.0.borrow_mut().time_to_first_window_draw = Some(TimeToFirstWindowDraw::Pending(start)); - self - } - /// Start the application. The provided callback will be called once the /// app is fully launched. pub fn run(self, on_finish_launching: F) @@ -253,7 +247,6 @@ pub struct AppContext { pub(crate) layout_id_buffer: Vec, // We recycle this memory across layout requests. pub(crate) propagate_event: bool, pub(crate) prompt_builder: Option, - pub(crate) time_to_first_window_draw: Option, } impl AppContext { @@ -307,7 +300,6 @@ impl AppContext { layout_id_buffer: Default::default(), propagate_event: true, prompt_builder: Some(PromptBuilder::Default), - time_to_first_window_draw: None, }), }); @@ -1310,14 +1302,6 @@ impl AppContext { (task, is_first) } - - /// Returns the time to first window draw, if available. - pub fn time_to_first_window_draw(&self) -> Option { - match self.time_to_first_window_draw { - Some(TimeToFirstWindowDraw::Done(duration)) => Some(duration), - _ => None, - } - } } impl Context for AppContext { @@ -1481,15 +1465,6 @@ impl DerefMut for GlobalLease { } } -/// Represents the initialization duration of the application. -#[derive(Clone, Copy)] -pub enum TimeToFirstWindowDraw { - /// The application is still initializing, and contains the start time. - Pending(Instant), - /// The application has finished initializing, and contains the total duration. - Done(Duration), -} - /// Contains state associated with an active drag operation, started by dragging an element /// within the window or by dragging into the app from the underlying platform. pub struct AnyDrag { diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index ed77eebfa8..cb54d9d47a 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -16,7 +16,6 @@ mod blade; #[cfg(any(test, feature = "test-support"))] mod test; -mod fps; #[cfg(target_os = "windows")] mod windows; @@ -52,7 +51,6 @@ use strum::EnumIter; use uuid::Uuid; pub use app_menu::*; -pub use fps::*; pub use keystroke::*; #[cfg(target_os = "linux")] @@ -356,7 +354,7 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { fn on_should_close(&self, callback: Box bool>); fn on_close(&self, callback: Box); fn on_appearance_changed(&self, callback: Box); - fn draw(&self, scene: &Scene, on_complete: Option>); + fn draw(&self, scene: &Scene); fn completed_frame(&self) {} fn sprite_atlas(&self) -> Arc; @@ -381,7 +379,6 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle { } fn set_client_inset(&self, _inset: Pixels) {} fn gpu_specs(&self) -> Option; - fn fps(&self) -> Option; fn update_ime_position(&self, _bounds: Bounds); diff --git a/crates/gpui/src/platform/blade/blade_renderer.rs b/crates/gpui/src/platform/blade/blade_renderer.rs index 3625d42ad1..19db311973 100644 --- a/crates/gpui/src/platform/blade/blade_renderer.rs +++ b/crates/gpui/src/platform/blade/blade_renderer.rs @@ -9,7 +9,6 @@ use crate::{ }; use bytemuck::{Pod, Zeroable}; use collections::HashMap; -use futures::channel::oneshot; #[cfg(target_os = "macos")] use media::core_video::CVMetalTextureCache; #[cfg(target_os = "macos")] @@ -543,12 +542,7 @@ impl BladeRenderer { self.gpu.destroy_command_encoder(&mut self.command_encoder); } - pub fn draw( - &mut self, - scene: &Scene, - // Required to compile on macOS, but not currently supported. - _on_complete: Option>, - ) { + pub fn draw(&mut self, scene: &Scene) { self.command_encoder.start(); self.atlas.before_frame(&mut self.command_encoder); self.rasterize_paths(scene.paths()); @@ -777,10 +771,4 @@ impl BladeRenderer { self.wait_for_gpu(); self.last_sync_point = Some(sync_point); } - - /// Required to compile on macOS, but not currently supported. - #[cfg_attr(any(target_os = "linux", target_os = "windows"), allow(dead_code))] - pub fn fps(&self) -> f32 { - 0.0 - } } diff --git a/crates/gpui/src/platform/fps.rs b/crates/gpui/src/platform/fps.rs deleted file mode 100644 index 9776e0d454..0000000000 --- a/crates/gpui/src/platform/fps.rs +++ /dev/null @@ -1,94 +0,0 @@ -use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; -use std::sync::Arc; - -const NANOS_PER_SEC: u64 = 1_000_000_000; -const WINDOW_SIZE: usize = 128; - -/// Represents a rolling FPS (Frames Per Second) counter. -/// -/// This struct provides a lock-free mechanism to measure and calculate FPS -/// continuously, updating with every frame. It uses atomic operations to -/// ensure thread-safety without the need for locks. -pub struct FpsCounter { - frame_times: [AtomicU64; WINDOW_SIZE], - head: AtomicUsize, - tail: AtomicUsize, -} - -impl FpsCounter { - /// Creates a new `Fps` counter. - /// - /// Returns an `Arc` for safe sharing across threads. - pub fn new() -> Arc { - Arc::new(Self { - frame_times: std::array::from_fn(|_| AtomicU64::new(0)), - head: AtomicUsize::new(0), - tail: AtomicUsize::new(0), - }) - } - - /// Increments the FPS counter with a new frame timestamp. - /// - /// This method updates the internal state to maintain a rolling window - /// of frame data for the last second. It uses atomic operations to - /// ensure thread-safety. - /// - /// # Arguments - /// - /// * `timestamp_ns` - The timestamp of the new frame in nanoseconds. - pub fn increment(&self, timestamp_ns: u64) { - let mut head = self.head.load(Ordering::Relaxed); - let mut tail = self.tail.load(Ordering::Relaxed); - - // Add new timestamp - self.frame_times[head].store(timestamp_ns, Ordering::Relaxed); - // Increment head and wrap around to 0 if it reaches WINDOW_SIZE - head = (head + 1) % WINDOW_SIZE; - self.head.store(head, Ordering::Relaxed); - - // Remove old timestamps (older than 1 second) - while tail != head { - let oldest = self.frame_times[tail].load(Ordering::Relaxed); - if timestamp_ns.wrapping_sub(oldest) <= NANOS_PER_SEC { - break; - } - // Increment tail and wrap around to 0 if it reaches WINDOW_SIZE - tail = (tail + 1) % WINDOW_SIZE; - self.tail.store(tail, Ordering::Relaxed); - } - } - - /// Calculates and returns the current FPS. - /// - /// This method computes the FPS based on the frames recorded in the last second. - /// It uses atomic loads to ensure thread-safety. - /// - /// # Returns - /// - /// The calculated FPS as a `f32`, or 0.0 if no frames have been recorded. - pub fn fps(&self) -> f32 { - let head = self.head.load(Ordering::Relaxed); - let tail = self.tail.load(Ordering::Relaxed); - - if head == tail { - return 0.0; - } - - let newest = - self.frame_times[head.wrapping_sub(1) & (WINDOW_SIZE - 1)].load(Ordering::Relaxed); - let oldest = self.frame_times[tail].load(Ordering::Relaxed); - - let time_diff = newest.wrapping_sub(oldest) as f32; - if time_diff == 0.0 { - return 0.0; - } - - let frame_count = if head > tail { - head - tail - } else { - WINDOW_SIZE - tail + head - }; - - (frame_count as f32 - 1.0) * NANOS_PER_SEC as f32 / time_diff - } -} diff --git a/crates/gpui/src/platform/linux/wayland/window.rs b/crates/gpui/src/platform/linux/wayland/window.rs index e2937ad45d..a0520f6b70 100644 --- a/crates/gpui/src/platform/linux/wayland/window.rs +++ b/crates/gpui/src/platform/linux/wayland/window.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use blade_graphics as gpu; use collections::HashMap; -use futures::channel::oneshot; +use futures::channel::oneshot::Receiver; use raw_window_handle as rwh; use wayland_backend::client::ObjectId; @@ -831,7 +831,7 @@ impl PlatformWindow for WaylandWindow { _msg: &str, _detail: Option<&str>, _answers: &[&str], - ) -> Option> { + ) -> Option> { None } @@ -938,9 +938,9 @@ impl PlatformWindow for WaylandWindow { self.0.callbacks.borrow_mut().appearance_changed = Some(callback); } - fn draw(&self, scene: &Scene, on_complete: Option>) { + fn draw(&self, scene: &Scene) { let mut state = self.borrow_mut(); - state.renderer.draw(scene, on_complete); + state.renderer.draw(scene); } fn completed_frame(&self) { @@ -1018,10 +1018,6 @@ impl PlatformWindow for WaylandWindow { fn gpu_specs(&self) -> Option { self.borrow().renderer.gpu_specs().into() } - - fn fps(&self) -> Option { - None - } } fn update_window(mut state: RefMut) { diff --git a/crates/gpui/src/platform/linux/x11/window.rs b/crates/gpui/src/platform/linux/x11/window.rs index 29fdbb658a..f1aa10f311 100644 --- a/crates/gpui/src/platform/linux/x11/window.rs +++ b/crates/gpui/src/platform/linux/x11/window.rs @@ -1,3 +1,5 @@ +use anyhow::Context; + use crate::{ platform::blade::{BladeRenderer, BladeSurfaceConfig}, px, size, AnyWindowHandle, Bounds, Decorations, DevicePixels, ForegroundExecutor, GPUSpecs, @@ -7,9 +9,7 @@ use crate::{ X11ClientStatePtr, }; -use anyhow::Context; use blade_graphics as gpu; -use futures::channel::oneshot; use raw_window_handle as rwh; use util::{maybe, ResultExt}; use x11rb::{ @@ -1210,10 +1210,9 @@ impl PlatformWindow for X11Window { self.0.callbacks.borrow_mut().appearance_changed = Some(callback); } - // TODO: on_complete not yet supported for X11 windows - fn draw(&self, scene: &Scene, on_complete: Option>) { + fn draw(&self, scene: &Scene) { let mut inner = self.0.state.borrow_mut(); - inner.renderer.draw(scene, on_complete); + inner.renderer.draw(scene); } fn sprite_atlas(&self) -> Arc { @@ -1406,8 +1405,4 @@ impl PlatformWindow for X11Window { fn gpu_specs(&self) -> Option { self.0.state.borrow().renderer.gpu_specs().into() } - - fn fps(&self) -> Option { - None - } } diff --git a/crates/gpui/src/platform/mac/metal_renderer.rs b/crates/gpui/src/platform/mac/metal_renderer.rs index e8d92057af..401734e253 100644 --- a/crates/gpui/src/platform/mac/metal_renderer.rs +++ b/crates/gpui/src/platform/mac/metal_renderer.rs @@ -1,7 +1,7 @@ use super::metal_atlas::MetalAtlas; use crate::{ point, size, AtlasTextureId, AtlasTextureKind, AtlasTile, Bounds, ContentMask, DevicePixels, - FpsCounter, Hsla, MonochromeSprite, PaintSurface, Path, PathId, PathVertex, PolychromeSprite, + Hsla, MonochromeSprite, PaintSurface, Path, PathId, PathVertex, PolychromeSprite, PrimitiveBatch, Quad, ScaledPixels, Scene, Shadow, Size, Surface, Underline, }; use anyhow::{anyhow, Result}; @@ -14,7 +14,6 @@ use cocoa::{ use collections::HashMap; use core_foundation::base::TCFType; use foreign_types::ForeignType; -use futures::channel::oneshot; use media::core_video::CVMetalTextureCache; use metal::{CAMetalLayer, CommandQueue, MTLPixelFormat, MTLResourceOptions, NSRange}; use objc::{self, msg_send, sel, sel_impl}; @@ -106,7 +105,6 @@ pub(crate) struct MetalRenderer { instance_buffer_pool: Arc>, sprite_atlas: Arc, core_video_texture_cache: CVMetalTextureCache, - fps_counter: Arc, } impl MetalRenderer { @@ -252,7 +250,6 @@ impl MetalRenderer { instance_buffer_pool, sprite_atlas, core_video_texture_cache, - fps_counter: FpsCounter::new(), } } @@ -295,8 +292,7 @@ impl MetalRenderer { // nothing to do } - pub fn draw(&mut self, scene: &Scene, on_complete: Option>) { - let on_complete = Arc::new(Mutex::new(on_complete)); + pub fn draw(&mut self, scene: &Scene) { let layer = self.layer.clone(); let viewport_size = layer.drawable_size(); let viewport_size: Size = size( @@ -323,24 +319,13 @@ impl MetalRenderer { Ok(command_buffer) => { let instance_buffer_pool = self.instance_buffer_pool.clone(); let instance_buffer = Cell::new(Some(instance_buffer)); - let device = self.device.clone(); - let fps_counter = self.fps_counter.clone(); - let completed_handler = - ConcreteBlock::new(move |_: &metal::CommandBufferRef| { - let mut cpu_timestamp = 0; - let mut gpu_timestamp = 0; - device.sample_timestamps(&mut cpu_timestamp, &mut gpu_timestamp); - - fps_counter.increment(gpu_timestamp); - if let Some(on_complete) = on_complete.lock().take() { - on_complete.send(()).ok(); - } - if let Some(instance_buffer) = instance_buffer.take() { - instance_buffer_pool.lock().release(instance_buffer); - } - }); - let completed_handler = completed_handler.copy(); - command_buffer.add_completed_handler(&completed_handler); + let block = ConcreteBlock::new(move |_| { + if let Some(instance_buffer) = instance_buffer.take() { + instance_buffer_pool.lock().release(instance_buffer); + } + }); + let block = block.copy(); + command_buffer.add_completed_handler(&block); if self.presents_with_transaction { command_buffer.commit(); @@ -1132,10 +1117,6 @@ impl MetalRenderer { } true } - - pub fn fps(&self) -> f32 { - self.fps_counter.fps() - } } fn build_pipeline_state( diff --git a/crates/gpui/src/platform/mac/window.rs b/crates/gpui/src/platform/mac/window.rs index 2b44153c04..bf83690697 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -783,14 +783,14 @@ impl PlatformWindow for MacWindow { self.0.as_ref().lock().bounds() } - fn is_maximized(&self) -> bool { - self.0.as_ref().lock().is_maximized() - } - fn window_bounds(&self) -> WindowBounds { self.0.as_ref().lock().window_bounds() } + fn is_maximized(&self) -> bool { + self.0.as_ref().lock().is_maximized() + } + fn content_size(&self) -> Size { self.0.as_ref().lock().content_size() } @@ -974,6 +974,8 @@ impl PlatformWindow for MacWindow { } } + fn set_app_id(&mut self, _app_id: &str) {} + fn set_background_appearance(&self, background_appearance: WindowBackgroundAppearance) { let mut this = self.0.as_ref().lock(); this.renderer @@ -1004,6 +1006,30 @@ impl PlatformWindow for MacWindow { } } + fn set_edited(&mut self, edited: bool) { + unsafe { + let window = self.0.lock().native_window; + msg_send![window, setDocumentEdited: edited as BOOL] + } + + // Changing the document edited state resets the traffic light position, + // so we have to move it again. + self.0.lock().move_traffic_light(); + } + + fn show_character_palette(&self) { + let this = self.0.lock(); + let window = this.native_window; + this.executor + .spawn(async move { + unsafe { + let app = NSApplication::sharedApplication(nil); + let _: () = msg_send![app, orderFrontCharacterPalette: window]; + } + }) + .detach(); + } + fn minimize(&self) { let window = self.0.lock().native_window; unsafe { @@ -1080,41 +1106,15 @@ impl PlatformWindow for MacWindow { self.0.lock().appearance_changed_callback = Some(callback); } - fn draw(&self, scene: &crate::Scene, on_complete: Option>) { + fn draw(&self, scene: &crate::Scene) { let mut this = self.0.lock(); - this.renderer.draw(scene, on_complete); + this.renderer.draw(scene); } fn sprite_atlas(&self) -> Arc { self.0.lock().renderer.sprite_atlas().clone() } - fn set_edited(&mut self, edited: bool) { - unsafe { - let window = self.0.lock().native_window; - msg_send![window, setDocumentEdited: edited as BOOL] - } - - // Changing the document edited state resets the traffic light position, - // so we have to move it again. - self.0.lock().move_traffic_light(); - } - - fn show_character_palette(&self) { - let this = self.0.lock(); - let window = this.native_window; - this.executor - .spawn(async move { - unsafe { - let app = NSApplication::sharedApplication(nil); - let _: () = msg_send![app, orderFrontCharacterPalette: window]; - } - }) - .detach(); - } - - fn set_app_id(&mut self, _app_id: &str) {} - fn gpu_specs(&self) -> Option { None } @@ -1125,10 +1125,6 @@ impl PlatformWindow for MacWindow { let _: () = msg_send![input_context, invalidateCharacterCoordinates]; } } - - fn fps(&self) -> Option { - Some(self.0.lock().renderer.fps()) - } } impl rwh::HasWindowHandle for MacWindow { diff --git a/crates/gpui/src/platform/test/window.rs b/crates/gpui/src/platform/test/window.rs index 815f4dbee2..1464dd8e73 100644 --- a/crates/gpui/src/platform/test/window.rs +++ b/crates/gpui/src/platform/test/window.rs @@ -251,12 +251,7 @@ impl PlatformWindow for TestWindow { fn on_appearance_changed(&self, _callback: Box) {} - fn draw( - &self, - _scene: &crate::Scene, - _on_complete: Option>, - ) { - } + fn draw(&self, _scene: &crate::Scene) {} fn sprite_atlas(&self) -> sync::Arc { self.0.lock().sprite_atlas.clone() @@ -284,10 +279,6 @@ impl PlatformWindow for TestWindow { fn gpu_specs(&self) -> Option { None } - - fn fps(&self) -> Option { - None - } } pub(crate) struct TestAtlasState { diff --git a/crates/gpui/src/platform/windows/window.rs b/crates/gpui/src/platform/windows/window.rs index f03e6a3857..1a059491a2 100644 --- a/crates/gpui/src/platform/windows/window.rs +++ b/crates/gpui/src/platform/windows/window.rs @@ -660,8 +660,8 @@ impl PlatformWindow for WindowsWindow { self.0.state.borrow_mut().callbacks.appearance_changed = Some(callback); } - fn draw(&self, scene: &Scene, on_complete: Option>) { - self.0.state.borrow_mut().renderer.draw(scene, on_complete) + fn draw(&self, scene: &Scene) { + self.0.state.borrow_mut().renderer.draw(scene) } fn sprite_atlas(&self) -> Arc { @@ -679,10 +679,6 @@ impl PlatformWindow for WindowsWindow { fn update_ime_position(&self, _bounds: Bounds) { // todo(windows) } - - fn fps(&self) -> Option { - None - } } #[implement(IDropTarget)] diff --git a/crates/gpui/src/window.rs b/crates/gpui/src/window.rs index 7d7ddc32e4..dce136bddd 100644 --- a/crates/gpui/src/window.rs +++ b/crates/gpui/src/window.rs @@ -11,9 +11,9 @@ use crate::{ PromptLevel, Quad, Render, RenderGlyphParams, RenderImage, RenderImageParams, RenderSvgParams, Replay, ResizeEdge, ScaledPixels, Scene, Shadow, SharedString, Size, StrikethroughStyle, Style, SubscriberSet, Subscription, TaffyLayoutEngine, Task, TextStyle, TextStyleRefinement, - TimeToFirstWindowDraw, TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, - WeakView, WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, - WindowDecorations, WindowOptions, WindowParams, WindowTextSystem, SUBPIXEL_VARIANTS, + TransformationMatrix, Underline, UnderlineStyle, View, VisualContext, WeakView, + WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControls, WindowDecorations, + WindowOptions, WindowParams, WindowTextSystem, SUBPIXEL_VARIANTS, }; use anyhow::{anyhow, Context as _, Result}; use collections::{FxHashMap, FxHashSet}; @@ -545,8 +545,6 @@ pub struct Window { hovered: Rc>, pub(crate) dirty: Rc>, pub(crate) needs_present: Rc>, - /// We assign this to be notified when the platform graphics backend fires the next completion callback for drawing the window. - present_completed: RefCell>>, pub(crate) last_input_timestamp: Rc>, pub(crate) refreshing: bool, pub(crate) draw_phase: DrawPhase, @@ -824,7 +822,6 @@ impl Window { hovered, dirty, needs_present, - present_completed: RefCell::default(), last_input_timestamp, refreshing: false, draw_phase: DrawPhase::None, @@ -1494,29 +1491,13 @@ impl<'a> WindowContext<'a> { self.window.refreshing = false; self.window.draw_phase = DrawPhase::None; self.window.needs_present.set(true); - - if let Some(TimeToFirstWindowDraw::Pending(start)) = self.app.time_to_first_window_draw { - let (tx, rx) = oneshot::channel(); - *self.window.present_completed.borrow_mut() = Some(tx); - self.spawn(|mut cx| async move { - rx.await.ok(); - cx.update(|cx| { - let duration = start.elapsed(); - cx.time_to_first_window_draw = Some(TimeToFirstWindowDraw::Done(duration)); - log::info!("time to first window draw: {:?}", duration); - cx.push_effect(Effect::Refresh); - }) - }) - .detach(); - } } #[profiling::function] fn present(&self) { - let on_complete = self.window.present_completed.take(); self.window .platform_window - .draw(&self.window.rendered_frame.scene, on_complete); + .draw(&self.window.rendered_frame.scene); self.window.needs_present.set(false); profiling::finish_frame!(); } @@ -3798,12 +3779,6 @@ impl<'a> WindowContext<'a> { pub fn gpu_specs(&self) -> Option { self.window.platform_window.gpu_specs() } - - /// Get the current FPS (frames per second) of the window. - /// This is only supported on macOS currently. - pub fn fps(&self) -> Option { - self.window.platform_window.fps() - } } #[cfg(target_os = "windows")] diff --git a/crates/performance/Cargo.toml b/crates/performance/Cargo.toml deleted file mode 100644 index 33f4bdc565..0000000000 --- a/crates/performance/Cargo.toml +++ /dev/null @@ -1,36 +0,0 @@ -[package] -name = "performance" -version = "0.1.0" -edition = "2021" -publish = false -license = "GPL-3.0-or-later" - -[lints] -workspace = true - -[lib] -path = "src/performance.rs" -doctest = false - -[features] -test-support = [ - "collections/test-support", - "gpui/test-support", - "workspace/test-support", -] - -[dependencies] -anyhow.workspace = true -gpui.workspace = true -log.workspace = true -schemars.workspace = true -serde.workspace = true -settings.workspace = true -workspace.workspace = true - -[dev-dependencies] -collections = { workspace = true, features = ["test-support"] } -gpui = { workspace = true, features = ["test-support"] } -settings = { workspace = true, features = ["test-support"] } -util = { workspace = true, features = ["test-support"] } -workspace = { workspace = true, features = ["test-support"] } diff --git a/crates/performance/LICENSE-GPL b/crates/performance/LICENSE-GPL deleted file mode 120000 index 89e542f750..0000000000 --- a/crates/performance/LICENSE-GPL +++ /dev/null @@ -1 +0,0 @@ -../../LICENSE-GPL \ No newline at end of file diff --git a/crates/performance/src/performance.rs b/crates/performance/src/performance.rs deleted file mode 100644 index 43e97a0dd3..0000000000 --- a/crates/performance/src/performance.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::time::Instant; - -use anyhow::Result; -use gpui::{ - div, AppContext, InteractiveElement as _, Render, StatefulInteractiveElement as _, - Subscription, ViewContext, VisualContext, -}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; -use settings::{Settings, SettingsSources, SettingsStore}; -use workspace::{ - ui::{Label, LabelCommon, LabelSize, Tooltip}, - ItemHandle, StatusItemView, Workspace, -}; - -const SHOW_STARTUP_TIME_DURATION: std::time::Duration = std::time::Duration::from_secs(5); - -pub fn init(cx: &mut AppContext) { - PerformanceSettings::register(cx); - - let mut enabled = PerformanceSettings::get_global(cx) - .show_in_status_bar - .unwrap_or(false); - let start_time = Instant::now(); - let mut _observe_workspaces = toggle_status_bar_items(enabled, start_time, cx); - - cx.observe_global::(move |cx| { - let new_value = PerformanceSettings::get_global(cx) - .show_in_status_bar - .unwrap_or(false); - if new_value != enabled { - enabled = new_value; - _observe_workspaces = toggle_status_bar_items(enabled, start_time, cx); - } - }) - .detach(); -} - -fn toggle_status_bar_items( - enabled: bool, - start_time: Instant, - cx: &mut AppContext, -) -> Option { - for window in cx.windows() { - if let Some(workspace) = window.downcast::() { - workspace - .update(cx, |workspace, cx| { - toggle_status_bar_item(workspace, enabled, start_time, cx); - }) - .ok(); - } - } - - if enabled { - log::info!("performance metrics display enabled"); - Some(cx.observe_new_views::(move |workspace, cx| { - toggle_status_bar_item(workspace, true, start_time, cx); - })) - } else { - log::info!("performance metrics display disabled"); - None - } -} - -struct PerformanceStatusBarItem { - display_mode: DisplayMode, -} - -#[derive(Copy, Clone, Debug)] -enum DisplayMode { - StartupTime, - Fps, -} - -impl PerformanceStatusBarItem { - fn new(start_time: Instant, cx: &mut ViewContext) -> Self { - let now = Instant::now(); - let display_mode = if now < start_time + SHOW_STARTUP_TIME_DURATION { - DisplayMode::StartupTime - } else { - DisplayMode::Fps - }; - - let this = Self { display_mode }; - - if let DisplayMode::StartupTime = display_mode { - cx.spawn(|this, mut cx| async move { - let now = Instant::now(); - let remaining_duration = - (start_time + SHOW_STARTUP_TIME_DURATION).saturating_duration_since(now); - cx.background_executor().timer(remaining_duration).await; - this.update(&mut cx, |this, cx| { - this.display_mode = DisplayMode::Fps; - cx.notify(); - }) - .ok(); - }) - .detach(); - } - - this - } -} - -impl Render for PerformanceStatusBarItem { - fn render(&mut self, cx: &mut gpui::ViewContext) -> impl gpui::IntoElement { - let text = match self.display_mode { - DisplayMode::StartupTime => cx - .time_to_first_window_draw() - .map_or("Pending".to_string(), |duration| { - format!("{}ms", duration.as_millis()) - }), - DisplayMode::Fps => cx.fps().map_or("".to_string(), |fps| { - format!("{:3} FPS", fps.round() as u32) - }), - }; - - use gpui::ParentElement; - let display_mode = self.display_mode; - div() - .id("performance status") - .child(Label::new(text).size(LabelSize::Small)) - .tooltip(move |cx| match display_mode { - DisplayMode::StartupTime => Tooltip::text("Time to first window draw", cx), - DisplayMode::Fps => cx - .new_view(|cx| { - let tooltip = Tooltip::new("Current FPS"); - if let Some(time_to_first) = cx.time_to_first_window_draw() { - tooltip.meta(format!( - "Time to first window draw: {}ms", - time_to_first.as_millis() - )) - } else { - tooltip - } - }) - .into(), - }) - } -} - -impl StatusItemView for PerformanceStatusBarItem { - fn set_active_pane_item( - &mut self, - _active_pane_item: Option<&dyn ItemHandle>, - _cx: &mut gpui::ViewContext, - ) { - // This is not currently used. - } -} - -fn toggle_status_bar_item( - workspace: &mut Workspace, - enabled: bool, - start_time: Instant, - cx: &mut ViewContext, -) { - if enabled { - workspace.status_bar().update(cx, |bar, cx| { - bar.add_right_item( - cx.new_view(|cx| PerformanceStatusBarItem::new(start_time, cx)), - cx, - ) - }); - } else { - workspace.status_bar().update(cx, |bar, cx| { - bar.remove_items_of_type::(cx); - }); - } -} - -/// Configuration of the display of performance details. -#[derive(Clone, Default, Serialize, Deserialize, JsonSchema, Debug)] -pub struct PerformanceSettings { - /// Display the time to first window draw and frame rate in the status bar. - /// - /// Default: false - pub show_in_status_bar: Option, -} - -impl Settings for PerformanceSettings { - const KEY: Option<&'static str> = Some("performance"); - - type FileContent = Self; - - fn load(sources: SettingsSources, _: &mut AppContext) -> Result { - sources.json_merge() - } -} diff --git a/crates/workspace/src/status_bar.rs b/crates/workspace/src/status_bar.rs index f214132a5e..24340e4f38 100644 --- a/crates/workspace/src/status_bar.rs +++ b/crates/workspace/src/status_bar.rs @@ -153,17 +153,6 @@ impl StatusBar { cx.notify(); } - pub fn remove_items_of_type(&mut self, cx: &mut ViewContext) - where - T: 'static + StatusItemView, - { - self.left_items - .retain(|item| item.item_type() != TypeId::of::()); - self.right_items - .retain(|item| item.item_type() != TypeId::of::()); - cx.notify(); - } - pub fn add_right_item(&mut self, item: View, cx: &mut ViewContext) where T: 'static + StatusItemView, diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index 16894d8cbe..de8bc1f767 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -75,7 +75,6 @@ outline.workspace = true outline_panel.workspace = true parking_lot.workspace = true paths.workspace = true -performance.workspace = true profiling.workspace = true project.workspace = true project_panel.workspace = true diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index 7a60ddde5c..0801da6174 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -267,7 +267,6 @@ fn init_ui( welcome::init(cx); settings_ui::init(cx); extensions_ui::init(cx); - performance::init(cx); cx.observe_global::({ let languages = app_state.languages.clone(); @@ -317,7 +316,6 @@ fn init_ui( } fn main() { - let start_time = std::time::Instant::now(); menu::init(); zed_actions::init(); @@ -329,9 +327,7 @@ fn main() { init_logger(); log::info!("========== starting zed =========="); - let app = App::new() - .with_assets(Assets) - .measure_time_to_first_window_draw(start_time); + let app = App::new().with_assets(Assets); let (installation_id, existing_installation_id_found) = app .background_executor()