From 1ff6ef3fa728563edfb8ba3328fa6c86e0890aef Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Fri, 6 Sep 2024 15:35:00 +0200 Subject: [PATCH] Revert FPS counter (#17485) **UPDATE**: Response so far seems to be that this fixes the performance issues on Intel MacBooks. So we're going to go ahead and merge it. This reverts the FPS counter added in 11753914d (#16422) because in this issue someone bisected recent performance regressions down to this commit: - https://github.com/zed-industries/zed/issues/16729 Another issue that's possibly related: - https://github.com/zed-industries/zed/issues/17305#issuecomment-2332316242 We're reverting this in a PR to create a bundle that people can try out. Assets: - Universal Binary: https://github.com/zed-industries/zed/actions/runs/10735702994/artifacts/1900460781 - x86/Intel: https://github.com/zed-industries/zed/actions/runs/10735702994/artifacts/1900461236 - Apple Silicon: https://github.com/zed-industries/zed/actions/runs/10735702994/artifacts/1900460978 Release Notes: - Removed the recently-added FPS counter since the changes it made to the Metal renderer on macOS could lead to performance regressions on Intel MacBooks. Co-authored-by: Bennet --- Cargo.lock | 16 -- Cargo.toml | 2 - crates/gpui/src/app.rs | 27 +-- crates/gpui/src/platform.rs | 5 +- .../gpui/src/platform/blade/blade_renderer.rs | 14 +- crates/gpui/src/platform/fps.rs | 94 --------- .../gpui/src/platform/linux/wayland/window.rs | 12 +- crates/gpui/src/platform/linux/x11/window.rs | 13 +- .../gpui/src/platform/mac/metal_renderer.rs | 37 +--- crates/gpui/src/platform/mac/window.rs | 68 +++---- crates/gpui/src/platform/test/window.rs | 11 +- crates/gpui/src/platform/windows/window.rs | 8 +- crates/gpui/src/window.rs | 33 +-- crates/performance/Cargo.toml | 36 ---- crates/performance/LICENSE-GPL | 1 - crates/performance/src/performance.rs | 189 ------------------ crates/workspace/src/status_bar.rs | 11 - crates/zed/Cargo.toml | 1 - crates/zed/src/main.rs | 6 +- 19 files changed, 60 insertions(+), 524 deletions(-) delete mode 100644 crates/gpui/src/platform/fps.rs delete mode 100644 crates/performance/Cargo.toml delete mode 120000 crates/performance/LICENSE-GPL delete mode 100644 crates/performance/src/performance.rs diff --git a/Cargo.lock b/Cargo.lock index 737c91466722fbbd91bff68dabc2b6beb7c51856..ed9221ee4db14e97c75b23f9a945928d3d794503 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7879,21 +7879,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 68a7167e70450c0737cedb91e40bba85358be084..f008aea827f8c453e0c65c1ec9fb699f47bae39d 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 6d011a767542847a1979778fc69897b5928ad679..5e3922061de303d95660dbb89a5ce67bb1592c92 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 66df136268f21310dce13576a43409b16b418442..342f4278e8e74967d165bbdac5905a4d22dd499a 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 79e182ff061daf6077d442b19e68c446b22de61d..9f229e64fff20b30de537108da03c871d51a37f4 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")] @@ -542,12 +541,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()); @@ -776,10 +770,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 9776e0d454da3efdf323092dd7aa4b8ad9ff8587..0000000000000000000000000000000000000000 --- 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 28b3316c993a356181f09d635e70edab9894d31d..c43c4741acc87b4a9102bc1e7b502289ffb609a4 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) { @@ -1020,10 +1020,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 29fdbb658aac5afe36293c0b9735bdefe0941725..f1aa10f31152ea9108e0f7430605d382cdb45a2a 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 e8d92057af11956942f90e00002c05d446b1a560..401734e2536c1bf1faf5eaf61fab77c5c4acf199 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 c05c6f32995f26cde057d347851d0641725dbcd8..67e8512abce6ae3b4988dbf2238617e5b3a1374f 100644 --- a/crates/gpui/src/platform/mac/window.rs +++ b/crates/gpui/src/platform/mac/window.rs @@ -784,14 +784,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() } @@ -975,6 +975,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 @@ -1005,6 +1007,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 { @@ -1081,41 +1107,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 } @@ -1126,10 +1126,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 815f4dbee2ea056de7ac7420d8fab4e92d17d699..1464dd8e73b384715e0674c35a1453b4e57844fa 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 f03e6a38572c2b74f94809b1c4c3d62d1f110775..1a059491a2a4adf29681598b40c4f6ad411d268c 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 1c47b98606b310ab960f02ef503930c49b351ddb..1ba9a794e1f8d6c95638a4fa7e29cad7806aaa7f 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!(); } @@ -3799,12 +3780,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 33f4bdc565237ee8a42559ecee7864a521083957..0000000000000000000000000000000000000000 --- 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 89e542f750cd3860a0598eff0dc34b56d7336dc4..0000000000000000000000000000000000000000 --- 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 43e97a0dd38fb99b89fe70a5cd0e83f7bd05ca98..0000000000000000000000000000000000000000 --- 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 29ba4352edf2f6d392062dca2f723fc72afe6466..ea92451bf0243c17cb1c4e0c41d82705ff10ce20 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 b9d751a4bf311652aec7ac9cd346b0a8d0ed4fc5..d48f75ed460ba04e0c086a4ae1f089909ec5183f 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 0081f23329a3535caef4fb5e7919c4fc6a503d81..090b1ca428c8b531dcfd5a51ee8f1964d5b15dff 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -268,7 +268,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(); @@ -318,7 +317,6 @@ fn init_ui( } fn main() { - let start_time = std::time::Instant::now(); menu::init(); zed_actions::init(); @@ -330,9 +328,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()