mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-18 18:08:07 +03:00
Integrate profiling into gpui (#8176)
[Profiling](https://crates.io/crates/profiling) crate allows easy integration with various profiler tools. The best thing is - annotations compile to nothing unless you request a specific feature. For example, I used this command to enable Tracy support: ```bash cargo run --features profiling/profile-with-tracy ``` At the same time I had Tracy tool open and waiting for connection. It gathered nice stats from the run: ![zed-profiler](https://github.com/zed-industries/zed/assets/107301/5233045d-078c-4ad8-8b00-7ae55cf94ebb) Release Notes: - N/A
This commit is contained in:
parent
250df707bf
commit
991c9ec441
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -4121,6 +4121,7 @@ dependencies = [
|
|||||||
"pathfinder_geometry",
|
"pathfinder_geometry",
|
||||||
"png",
|
"png",
|
||||||
"postage",
|
"postage",
|
||||||
|
"profiling",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"raw-window-handle 0.5.2",
|
"raw-window-handle 0.5.2",
|
||||||
"raw-window-handle 0.6.0",
|
"raw-window-handle 0.6.0",
|
||||||
@ -6863,6 +6864,25 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "profiling"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58"
|
||||||
|
dependencies = [
|
||||||
|
"profiling-procmacros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "profiling-procmacros"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "project"
|
name = "project"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -11978,6 +11998,7 @@ dependencies = [
|
|||||||
"outline",
|
"outline",
|
||||||
"parking_lot 0.11.2",
|
"parking_lot 0.11.2",
|
||||||
"postage",
|
"postage",
|
||||||
|
"profiling",
|
||||||
"project",
|
"project",
|
||||||
"project_panel",
|
"project_panel",
|
||||||
"project_symbols",
|
"project_symbols",
|
||||||
|
@ -203,6 +203,7 @@ linkify = "0.10.0"
|
|||||||
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
|
||||||
ordered-float = "2.1.1"
|
ordered-float = "2.1.1"
|
||||||
parking_lot = "0.11.1"
|
parking_lot = "0.11.1"
|
||||||
|
profiling = "1"
|
||||||
postage = { version = "0.5", features = ["futures-traits"] }
|
postage = { version = "0.5", features = ["futures-traits"] }
|
||||||
pretty_assertions = "1.3.0"
|
pretty_assertions = "1.3.0"
|
||||||
prost = "0.8"
|
prost = "0.8"
|
||||||
|
@ -51,6 +51,7 @@ parking = "2.0.0"
|
|||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
pathfinder_geometry = "0.5"
|
pathfinder_geometry = "0.5"
|
||||||
postage.workspace = true
|
postage.workspace = true
|
||||||
|
profiling.workspace = true
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
raw-window-handle = "0.6"
|
raw-window-handle = "0.6"
|
||||||
refineable.workspace = true
|
refineable.workspace = true
|
||||||
|
@ -117,6 +117,7 @@ impl PlatformAtlas for BladeAtlas {
|
|||||||
if let Some(tile) = lock.tiles_by_key.get(key) {
|
if let Some(tile) = lock.tiles_by_key.get(key) {
|
||||||
Ok(tile.clone())
|
Ok(tile.clone())
|
||||||
} else {
|
} else {
|
||||||
|
profiling::scope!("new tile");
|
||||||
let (size, bytes) = build()?;
|
let (size, bytes) = build()?;
|
||||||
let tile = lock.allocate(size, key.texture_kind());
|
let tile = lock.allocate(size, key.texture_kind());
|
||||||
lock.upload_texture(tile.texture_id, tile.bounds, &bytes);
|
lock.upload_texture(tile.texture_id, tile.bounds, &bytes);
|
||||||
|
@ -39,6 +39,7 @@ impl BladeBelt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[profiling::function]
|
||||||
pub fn alloc(&mut self, size: u64, gpu: &gpu::Context) -> gpu::BufferPiece {
|
pub fn alloc(&mut self, size: u64, gpu: &gpu::Context) -> gpu::BufferPiece {
|
||||||
for &mut (ref rb, ref mut offset) in self.active.iter_mut() {
|
for &mut (ref rb, ref mut offset) in self.active.iter_mut() {
|
||||||
let aligned = offset.next_multiple_of(self.desc.alignment);
|
let aligned = offset.next_multiple_of(self.desc.alignment);
|
||||||
|
@ -444,6 +444,7 @@ impl BladeRenderer {
|
|||||||
self.gpu.metal_layer().unwrap().as_ptr()
|
self.gpu.metal_layer().unwrap().as_ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[profiling::function]
|
||||||
fn rasterize_paths(&mut self, paths: &[Path<ScaledPixels>]) {
|
fn rasterize_paths(&mut self, paths: &[Path<ScaledPixels>]) {
|
||||||
self.path_tiles.clear();
|
self.path_tiles.clear();
|
||||||
let mut vertices_by_texture_id = HashMap::default();
|
let mut vertices_by_texture_id = HashMap::default();
|
||||||
@ -506,7 +507,10 @@ impl BladeRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&mut self, scene: &Scene) {
|
pub fn draw(&mut self, scene: &Scene) {
|
||||||
let frame = self.gpu.acquire_frame();
|
let frame = {
|
||||||
|
profiling::scope!("acquire frame");
|
||||||
|
self.gpu.acquire_frame()
|
||||||
|
};
|
||||||
self.command_encoder.start();
|
self.command_encoder.start();
|
||||||
self.command_encoder.init_texture(frame.texture());
|
self.command_encoder.init_texture(frame.texture());
|
||||||
|
|
||||||
@ -529,6 +533,7 @@ impl BladeRenderer {
|
|||||||
}],
|
}],
|
||||||
depth_stencil: None,
|
depth_stencil: None,
|
||||||
}) {
|
}) {
|
||||||
|
profiling::scope!("render pass");
|
||||||
for batch in scene.batches() {
|
for batch in scene.batches() {
|
||||||
match batch {
|
match batch {
|
||||||
PrimitiveBatch::Quads(quads) => {
|
PrimitiveBatch::Quads(quads) => {
|
||||||
@ -718,6 +723,7 @@ impl BladeRenderer {
|
|||||||
self.command_encoder.present(frame);
|
self.command_encoder.present(frame);
|
||||||
let sync_point = self.gpu.submit(&mut self.command_encoder);
|
let sync_point = self.gpu.submit(&mut self.command_encoder);
|
||||||
|
|
||||||
|
profiling::scope!("finish");
|
||||||
self.instance_belt.flush(&sync_point);
|
self.instance_belt.flush(&sync_point);
|
||||||
self.atlas.after_frame(&sync_point);
|
self.atlas.after_frame(&sync_point);
|
||||||
self.atlas.clear_textures(AtlasTextureKind::Path);
|
self.atlas.clear_textures(AtlasTextureKind::Path);
|
||||||
|
@ -33,6 +33,7 @@ impl LinuxDispatcher {
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
let (background_sender, background_receiver) = flume::unbounded::<Runnable>();
|
let (background_sender, background_receiver) = flume::unbounded::<Runnable>();
|
||||||
let background_thread = thread::spawn(move || {
|
let background_thread = thread::spawn(move || {
|
||||||
|
profiling::register_thread!("background");
|
||||||
for runnable in background_receiver {
|
for runnable in background_receiver {
|
||||||
let _ignore_panic = panic::catch_unwind(|| runnable.run());
|
let _ignore_panic = panic::catch_unwind(|| runnable.run());
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,10 @@ impl Client for X11Client {
|
|||||||
// into window functions as they may invoke callbacks that need
|
// into window functions as they may invoke callbacks that need
|
||||||
// to immediately access the platform (self).
|
// to immediately access the platform (self).
|
||||||
while !self.platform_inner.state.lock().quit_requested {
|
while !self.platform_inner.state.lock().quit_requested {
|
||||||
let event = self.xcb_connection.wait_for_event().unwrap();
|
let event = {
|
||||||
|
profiling::scope!("Wait for event");
|
||||||
|
self.xcb_connection.wait_for_event().unwrap()
|
||||||
|
};
|
||||||
match event {
|
match event {
|
||||||
xcb::Event::X(x::Event::ClientMessage(ev)) => {
|
xcb::Event::X(x::Event::ClientMessage(ev)) => {
|
||||||
if let x::ClientMessageData::Data32([atom, ..]) = ev.data() {
|
if let x::ClientMessageData::Data32([atom, ..]) = ev.data() {
|
||||||
@ -210,6 +213,7 @@ impl Client for X11Client {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profiling::scope!("Runnables");
|
||||||
if let Ok(runnable) = self.platform_inner.main_receiver.try_recv() {
|
if let Ok(runnable) = self.platform_inner.main_receiver.try_recv() {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
}
|
}
|
||||||
@ -219,6 +223,7 @@ impl Client for X11Client {
|
|||||||
fun();
|
fun();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
|
fn displays(&self) -> Vec<Rc<dyn PlatformDisplay>> {
|
||||||
let setup = self.xcb_connection.get_setup();
|
let setup = self.xcb_connection.get_setup();
|
||||||
setup
|
setup
|
||||||
@ -230,6 +235,7 @@ impl Client for X11Client {
|
|||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
|
fn display(&self, id: DisplayId) -> Option<Rc<dyn PlatformDisplay>> {
|
||||||
Some(Rc::new(X11Display::new(&self.xcb_connection, id.0 as i32)))
|
Some(Rc::new(X11Display::new(&self.xcb_connection, id.0 as i32)))
|
||||||
}
|
}
|
||||||
|
@ -950,6 +950,7 @@ impl<'a> WindowContext<'a> {
|
|||||||
|
|
||||||
/// Produces a new frame and assigns it to `rendered_frame`. To actually show
|
/// Produces a new frame and assigns it to `rendered_frame`. To actually show
|
||||||
/// the contents of the new [Scene], use [present].
|
/// the contents of the new [Scene], use [present].
|
||||||
|
#[profiling::function]
|
||||||
pub fn draw(&mut self) {
|
pub fn draw(&mut self) {
|
||||||
self.window.dirty.set(false);
|
self.window.dirty.set(false);
|
||||||
self.window.drawing = true;
|
self.window.drawing = true;
|
||||||
@ -1092,11 +1093,13 @@ impl<'a> WindowContext<'a> {
|
|||||||
self.window.needs_present.set(true);
|
self.window.needs_present.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[profiling::function]
|
||||||
fn present(&self) {
|
fn present(&self) {
|
||||||
self.window
|
self.window
|
||||||
.platform_window
|
.platform_window
|
||||||
.draw(&self.window.rendered_frame.scene);
|
.draw(&self.window.rendered_frame.scene);
|
||||||
self.window.needs_present.set(false);
|
self.window.needs_present.set(false);
|
||||||
|
profiling::finish_frame!();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dispatch a given keystroke as though the user had typed it.
|
/// Dispatch a given keystroke as though the user had typed it.
|
||||||
@ -1132,6 +1135,7 @@ impl<'a> WindowContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Dispatch a mouse or keyboard event on the window.
|
/// Dispatch a mouse or keyboard event on the window.
|
||||||
|
#[profiling::function]
|
||||||
pub fn dispatch_event(&mut self, event: PlatformInput) -> bool {
|
pub fn dispatch_event(&mut self, event: PlatformInput) -> bool {
|
||||||
self.window.last_input_timestamp.set(Instant::now());
|
self.window.last_input_timestamp.set(Instant::now());
|
||||||
// Handlers may set this to false by calling `stop_propagation`.
|
// Handlers may set this to false by calling `stop_propagation`.
|
||||||
|
@ -77,6 +77,7 @@ num_cpus = "1.13.0"
|
|||||||
outline.workspace = true
|
outline.workspace = true
|
||||||
parking_lot.workspace = true
|
parking_lot.workspace = true
|
||||||
postage.workspace = true
|
postage.workspace = true
|
||||||
|
profiling.workspace = true
|
||||||
project.workspace = true
|
project.workspace = true
|
||||||
project_panel.workspace = true
|
project_panel.workspace = true
|
||||||
project_symbols.workspace = true
|
project_symbols.workspace = true
|
||||||
|
Loading…
Reference in New Issue
Block a user