Detailed changes
@@ -7780,21 +7780,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"
@@ -14169,7 +14154,6 @@ dependencies = [
"outline_panel",
"parking_lot",
"paths",
- "performance",
"profiling",
"project",
"project_panel",
@@ -71,7 +71,6 @@ members = [
"crates/outline",
"crates/outline_panel",
"crates/paths",
- "crates/performance",
"crates/picker",
"crates/prettier",
"crates/project",
@@ -244,7 +243,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" }
@@ -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<F>(self, on_finish_launching: F)
@@ -253,7 +247,6 @@ pub struct AppContext {
pub(crate) layout_id_buffer: Vec<LayoutId>, // We recycle this memory across layout requests.
pub(crate) propagate_event: bool,
pub(crate) prompt_builder: Option<PromptBuilder>,
- pub(crate) time_to_first_window_draw: Option<TimeToFirstWindowDraw>,
}
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<Duration> {
- match self.time_to_first_window_draw {
- Some(TimeToFirstWindowDraw::Done(duration)) => Some(duration),
- _ => None,
- }
- }
}
impl Context for AppContext {
@@ -1481,15 +1465,6 @@ impl<G: Global> DerefMut for GlobalLease<G> {
}
}
-/// 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 {
@@ -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<dyn FnMut() -> bool>);
fn on_close(&self, callback: Box<dyn FnOnce()>);
fn on_appearance_changed(&self, callback: Box<dyn FnMut()>);
- fn draw(&self, scene: &Scene, on_complete: Option<oneshot::Sender<()>>);
+ fn draw(&self, scene: &Scene);
fn completed_frame(&self) {}
fn sprite_atlas(&self) -> Arc<dyn PlatformAtlas>;
@@ -381,7 +379,6 @@ pub(crate) trait PlatformWindow: HasWindowHandle + HasDisplayHandle {
}
fn set_client_inset(&self, _inset: Pixels) {}
fn gpu_specs(&self) -> Option<GPUSpecs>;
- fn fps(&self) -> Option<f32>;
#[cfg(any(test, feature = "test-support"))]
fn as_test(&mut self) -> Option<&mut TestWindow> {
@@ -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")]
@@ -556,12 +555,7 @@ impl BladeRenderer {
self.pipelines.destroy(&self.gpu);
}
- pub fn draw(
- &mut self,
- scene: &Scene,
- // Required to compile on macOS, but not currently supported.
- _on_complete: Option<oneshot::Sender<()>>,
- ) {
+ pub fn draw(&mut self, scene: &Scene) {
self.command_encoder.start();
self.atlas.before_frame(&mut self.command_encoder);
self.rasterize_paths(scene.paths());
@@ -790,10 +784,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
- }
}
@@ -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<Fps>` for safe sharing across threads.
- pub fn new() -> Arc<Self> {
- 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
- }
-}
@@ -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;
@@ -827,7 +827,7 @@ impl PlatformWindow for WaylandWindow {
_msg: &str,
_detail: Option<&str>,
_answers: &[&str],
- ) -> Option<oneshot::Receiver<usize>> {
+ ) -> Option<Receiver<usize>> {
None
}
@@ -934,9 +934,9 @@ impl PlatformWindow for WaylandWindow {
self.0.callbacks.borrow_mut().appearance_changed = Some(callback);
}
- fn draw(&self, scene: &Scene, on_complete: Option<oneshot::Sender<()>>) {
+ 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) {
@@ -1009,10 +1009,6 @@ impl PlatformWindow for WaylandWindow {
fn gpu_specs(&self) -> Option<GPUSpecs> {
self.borrow().renderer.gpu_specs().into()
}
-
- fn fps(&self) -> Option<f32> {
- None
- }
}
fn update_window(mut state: RefMut<WaylandWindowState>) {
@@ -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<oneshot::Sender<()>>) {
+ 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<dyn PlatformAtlas> {
@@ -1399,8 +1398,4 @@ impl PlatformWindow for X11Window {
fn gpu_specs(&self) -> Option<GPUSpecs> {
self.0.state.borrow().renderer.gpu_specs().into()
}
-
- fn fps(&self) -> Option<f32> {
- None
- }
}
@@ -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<Mutex<InstanceBufferPool>>,
sprite_atlas: Arc<MetalAtlas>,
core_video_texture_cache: CVMetalTextureCache,
- fps_counter: Arc<FpsCounter>,
}
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<oneshot::Sender<()>>) {
- 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<DevicePixels> = 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(
@@ -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<Pixels> {
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,48 +1107,18 @@ impl PlatformWindow for MacWindow {
self.0.lock().appearance_changed_callback = Some(callback);
}
- fn draw(&self, scene: &crate::Scene, on_complete: Option<oneshot::Sender<()>>) {
+ 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<dyn PlatformAtlas> {
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<crate::GPUSpecs> {
None
}
-
- fn fps(&self) -> Option<f32> {
- Some(self.0.lock().renderer.fps())
- }
}
impl rwh::HasWindowHandle for MacWindow {
@@ -251,12 +251,7 @@ impl PlatformWindow for TestWindow {
fn on_appearance_changed(&self, _callback: Box<dyn FnMut()>) {}
- fn draw(
- &self,
- _scene: &crate::Scene,
- _on_complete: Option<futures::channel::oneshot::Sender<()>>,
- ) {
- }
+ fn draw(&self, _scene: &crate::Scene) {}
fn sprite_atlas(&self) -> sync::Arc<dyn crate::PlatformAtlas> {
self.0.lock().sprite_atlas.clone()
@@ -282,10 +277,6 @@ impl PlatformWindow for TestWindow {
fn gpu_specs(&self) -> Option<GPUSpecs> {
None
}
-
- fn fps(&self) -> Option<f32> {
- None
- }
}
pub(crate) struct TestAtlasState {
@@ -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<oneshot::Sender<()>>) {
- 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<dyn PlatformAtlas> {
@@ -675,10 +675,6 @@ impl PlatformWindow for WindowsWindow {
fn gpu_specs(&self) -> Option<GPUSpecs> {
Some(self.0.state.borrow().renderer.gpu_specs())
}
-
- fn fps(&self) -> Option<f32> {
- None
- }
}
#[implement(IDropTarget)]
@@ -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};
@@ -544,8 +544,6 @@ pub struct Window {
hovered: Rc<Cell<bool>>,
pub(crate) dirty: Rc<Cell<bool>>,
pub(crate) needs_present: Rc<Cell<bool>>,
- /// We assign this to be notified when the platform graphics backend fires the next completion callback for drawing the window.
- present_completed: RefCell<Option<oneshot::Sender<()>>>,
pub(crate) last_input_timestamp: Rc<Cell<Instant>>,
pub(crate) refreshing: bool,
pub(crate) draw_phase: DrawPhase,
@@ -822,7 +820,6 @@ impl Window {
hovered,
dirty,
needs_present,
- present_completed: RefCell::default(),
last_input_timestamp,
refreshing: false,
draw_phase: DrawPhase::None,
@@ -1492,29 +1489,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!();
}
@@ -3737,12 +3718,6 @@ impl<'a> WindowContext<'a> {
pub fn gpu_specs(&self) -> Option<GPUSpecs> {
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<f32> {
- self.window.platform_window.fps()
- }
}
#[cfg(target_os = "windows")]
@@ -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"] }
@@ -1 +0,0 @@
-../../LICENSE-GPL
@@ -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::<SettingsStore>(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<Subscription> {
- for window in cx.windows() {
- if let Some(workspace) = window.downcast::<Workspace>() {
- 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::<Workspace>(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>) -> 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<Self>) -> 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<Self>,
- ) {
- // This is not currently used.
- }
-}
-
-fn toggle_status_bar_item(
- workspace: &mut Workspace,
- enabled: bool,
- start_time: Instant,
- cx: &mut ViewContext<Workspace>,
-) {
- 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::<PerformanceStatusBarItem>(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<bool>,
-}
-
-impl Settings for PerformanceSettings {
- const KEY: Option<&'static str> = Some("performance");
-
- type FileContent = Self;
-
- fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
- sources.json_merge()
- }
-}
@@ -153,17 +153,6 @@ impl StatusBar {
cx.notify();
}
- pub fn remove_items_of_type<T>(&mut self, cx: &mut ViewContext<Self>)
- where
- T: 'static + StatusItemView,
- {
- self.left_items
- .retain(|item| item.item_type() != TypeId::of::<T>());
- self.right_items
- .retain(|item| item.item_type() != TypeId::of::<T>());
- cx.notify();
- }
-
pub fn add_right_item<T>(&mut self, item: View<T>, cx: &mut ViewContext<Self>)
where
T: 'static + StatusItemView,
@@ -72,7 +72,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
@@ -268,7 +268,6 @@ fn init_ui(
welcome::init(cx);
settings_ui::init(cx);
extensions_ui::init(cx);
- performance::init(cx);
cx.observe_global::<SettingsStore>({
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()