### Install and Run Puffin Viewer Source: https://github.com/embarkstudios/puffin/blob/main/puffin_viewer/README.md This snippet shows how to install the puffin_viewer using cargo and then how to run it, connecting to a puffin event stream via a specified URL. ```sh cargo install puffin_viewer --locked puffin_viewer --url 127.0.0.1:8585 ``` -------------------------------- ### Simple Puffin Profiler Window Integration in Egui Rust App Source: https://context7.com/embarkstudios/puffin/llms.txt This example demonstrates how to integrate the Puffin profiler's UI into an egui application with minimal setup. It uses the `puffin::profiler_window` function to display a default profiler view within the application's UI loop, ensuring profiling scopes are enabled and frames are marked. ```rust use puffin_egui::profiler_window; fn main() { puffin::set_scopes_on(true); // In your egui application eframe::run_native( "My App", Default::default(), Box::new(|_cc| Ok(Box::new(MyApp::default()))), ).unwrap(); } struct MyApp; impl eframe::App for MyApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { // Your app UI egui::CentralPanel::default().show(ctx, |ui| { ui.heading("My Application"); }); // Show profiler window profiler_window(ctx); // Mark frame boundary puffin::GlobalProfiler::lock().new_frame(); } } ``` -------------------------------- ### Custom Thread Profiler Setup with Puffin in Rust Source: https://context7.com/embarkstudios/puffin/llms.txt This example demonstrates how to set up a custom profiler instance for a specific thread using Puffin. It involves initializing a `GlobalProfiler` wrapped in a `Mutex` and `OnceLock` for thread-safe access, and then configuring a new thread to use this custom profiler by providing a reporting function. ```rust use puffin::{GlobalProfiler, ThreadProfiler, ThreadInfo, ScopeDetails, StreamInfoRef}; use puffin_http::Server; use std::sync::{OnceLock, Mutex, MutexGuard}; // Create custom profiler instance static WORKER_PROFILER: OnceLock> = OnceLock::new(); fn worker_profiler() -> MutexGuard<'static, GlobalProfiler> { WORKER_PROFILER .get_or_init(|| Mutex::new(GlobalProfiler::default())) .lock() .unwrap() } fn main() -> anyhow::Result<()> { // Main profiler on port 8585 let _main_server = Server::new("127.0.0.1:8585")?; puffin::set_scopes_on(true); // Worker profiler on port 8586 let _worker_server = Server::new_custom( "127.0.0.1:8586", |sink| worker_profiler().add_sink(sink), |id| { worker_profiler().remove_sink(id); } )?; eprintln!("Main profiler: puffin_viewer 127.0.0.1:8585"); eprintln!("Worker profiler: puffin_viewer 127.0.0.1:8586"); // Main thread uses default profiler loop { puffin::profile_scope!("main_thread"); // Spawn worker with custom profiler std::thread::spawn(|| { // Redirect this thread to custom profiler ThreadProfiler::initialize( puffin::now_ns, |info: ThreadInfo, details: &[ScopeDetails], stream: &StreamInfoRef<'_>| { worker_profiler().report(info, details, stream) } ); puffin::profile_scope!("worker_computation"); std::thread::sleep(std::time::Duration::from_millis(10)); // Flush worker profiler worker_profiler().new_frame(); }); std::thread::sleep(std::time::Duration::from_millis(16)); puffin::GlobalProfiler::lock().new_frame(); } } ``` -------------------------------- ### Install GTK3 Development Sources on Ubuntu Source: https://github.com/embarkstudios/puffin/blob/main/puffin_viewer/README.md This command is used on Ubuntu systems to install the necessary GTK3 development sources, which are required for file dialogs within the puffin_viewer. ```sh sudo apt install libgtk-3-dev ``` -------------------------------- ### Rust Profiling Macros and Initialization Source: https://github.com/embarkstudios/puffin/blob/main/README.md Demonstrates the usage of Puffin macros for profiling functions and scopes in Rust. It also shows how to enable the profiler and start a new frame, which are essential for capturing profiling data. ```rust fn my_function() { puffin::profile_function!(); ... if ... { puffin::profile_scope!("load_image", image_name); ... } } // To enable profiling: puffin::set_scopes_on(true); // To start a new frame (call once per frame): puffin::GlobalProfiler::lock().new_frame(); ``` -------------------------------- ### Start Puffin HTTP Server in Rust Source: https://github.com/embarkstudios/puffin/blob/main/puffin_http/README.md This snippet demonstrates how to initialize and start a puffin_http server within a Rust application. It binds the server to the default port and enables Puffin scopes for profiling. Ensure the `puffin_http` crate is added as a dependency. ```rust fn main() { let server_addr = format!("0.0.0.0:{}", puffin_http::DEFAULT_PORT); let _puffin_server = puffin_http::Server::new(&server_addr).unwrap(); eprintln!("Serving demo profile data on {server_addr}. Run `puffin_viewer` to view it."); puffin::set_scopes_on(true); // … } ``` -------------------------------- ### Start HTTP Profiling Server in Rust Source: https://context7.com/embarkstudios/puffin/llms.txt Enable remote profiling by starting an HTTP server using `puffin_http::Server`. This server allows you to stream profiling data over TCP to a standalone viewer for analysis. The default port is 8585. ```rust use puffin_http::Server; fn main() -> anyhow::Result<()> { // Start server on default port (8585) let server_addr = format!("127.0.0.1:{}", puffin_http::DEFAULT_PORT); let _puffin_server = Server::new(&server_addr)?; eprintln!("Run this to view: puffin_viewer {}", server_addr); puffin::set_scopes_on(true); // Application loop loop { puffin::GlobalProfiler::lock().new_frame(); { puffin::profile_scope!("main_loop"); do_work(); } std::thread::sleep(std::time::Duration::from_millis(16)); } } fn do_work() { puffin::profile_function!(); // Spawn thread - data automatically sent to server std::thread::spawn(|| { puffin::profile_scope!("worker_thread"); std::thread::sleep(std::time::Duration::from_millis(5)); }); } ``` -------------------------------- ### Rust Remote Profiling Setup with puffin_http Source: https://github.com/embarkstudios/puffin/blob/main/README.md Shows how to set up a TCP server using `puffin_http` to send profiling data remotely. This allows viewing profile data in the `puffin_viewer` application. It includes enabling scopes and a reminder to call `new_frame()` periodically. ```rust fn main() { let server_addr = format!("127.0.0.1:{}", puffin_http::DEFAULT_PORT); let _puffin_server = puffin_http::Server::new(&server_addr).unwrap(); eprintln!("Run this to view profiling data: puffin_viewer {server_addr}"); puffin::set_scopes_on(true); … // You also need to periodically call // `puffin::GlobalProfiler::lock().new_frame();` // to flush the profiling events. } ``` -------------------------------- ### Setup Custom Frame Sink for Processing Source: https://context7.com/embarkstudios/puffin/llms.txt Demonstrates how to add a custom frame sink to Puffin's GlobalProfiler to process frame data. This allows for custom analytics, exporting data, or reacting to performance metrics like slow frames. It requires the `puffin` crate. ```rust use puffin::{GlobalProfiler, FrameData, FrameSinkId}; use std::sync::Arc; fn setup_custom_sink() { let mut profiler = GlobalProfiler::lock(); // Add custom sink to process frame data let sink_id: FrameSinkId = profiler.add_sink(Box::new(|frame: Arc| { // Process each completed frame let frame_idx = frame.frame_index(); let meta = frame.meta(); println!("Frame {}: {} scopes, {} bytes, {} ms", frame_idx, meta.num_scopes, meta.num_bytes, meta.duration_ns as f64 / 1_000_000.0 ); // Export to file, send to analytics, etc. if meta.duration_ns > 16_000_000 { // > 16ms eprintln!("⚠️ Slow frame detected!"); } })); // Later, remove the sink // profiler.remove_sink(sink_id); } ``` -------------------------------- ### Rust Remote Profiling Setup Source: https://github.com/embarkstudios/puffin/blob/main/puffin/README.md Shows how to set up a Puffin HTTP server for remote profiling. This allows viewing profiling data from a separate viewer application. Ensure `puffin::set_scopes_on(true);` is called and `new_frame()` is periodically invoked. ```rust fn main() { let server_addr = format!("127.0.0.1:{}", puffin_http::DEFAULT_PORT); let _puffin_server = puffin_http::Server::new(&server_addr).unwrap(); eprintln!("Run this to view profiling data: puffin_viewer {}", server_addr); puffin::set_scopes_on(true); … // You also need to periodically call // `puffin::GlobalProfiler::lock().new_frame();` // to flush the profiling events. } ``` -------------------------------- ### Check Client Connection Count with puffin-http Source: https://context7.com/embarkstudios/puffin/llms.txt Monitors the number of connected viewers to the Puffin profiling server using the `puffin-http` crate. This example shows how to check the client count within a loop and conditionally print it. It requires the `puffin`, `puffin-http`, and `anyhow` crates. ```rust use puffin_http::Server; fn main() -> anyhow::Result<()> { let server = Server::new("127.0.0.1:8585")?; puffin::set_scopes_on(true); loop { // Check how many viewers are connected let num_clients = server.num_clients(); if num_clients > 0 { println!("Viewers connected: {}", num_clients); } puffin::profile_scope!("main_loop"); do_work(); puffin::GlobalProfiler::lock().new_frame(); std::thread::sleep(std::time::Duration::from_millis(16)); } } fn do_work() { puffin::profile_function!(); std::thread::sleep(std::time::Duration::from_millis(10)); } ``` -------------------------------- ### Rust Profiling Macros Source: https://github.com/embarkstudios/puffin/blob/main/puffin/README.md Demonstrates the basic usage of Puffin's profiling macros to instrument functions and code scopes. These macros help in identifying performance bottlenecks by recording execution times. The overhead is minimal when the profiler is off. ```rust fn my_function() { puffin::profile_function!(); ... if ... { puffin::profile_scope!("load_image", image_name); ... } } ``` -------------------------------- ### Connect to Remote Puffin Profiler as a Client in Rust Source: https://context7.com/embarkstudios/puffin/llms.txt This Rust code snippet shows how to establish a connection to a remote Puffin profiler server using the `puffin_http::Client`. It includes checking the connection status and provides comments on how to access frame data for visualization with `puffin_egui`. ```rust use puffin_http::Client; use puffin_egui::profiler_ui; fn main() { // Connect to remote profiler let client = Client::new("127.0.0.1:8585".to_owned()); // Check connection status if client.connected() { println!("Connected to {}", client.addr()); } // In your UI code (egui): // Access the frame data let frame_view = client.frame_view(); // Use with puffin_egui for visualization // egui_ctx is your egui::Context // profiler_ui(&mut ui); } ``` -------------------------------- ### Rust: Display puffin profiler window with egui Source: https://github.com/embarkstudios/puffin/blob/main/puffin_egui/README.md This code snippet shows the minimal integration required to display the puffin profiler's UI within an egui application. By calling `puffin_egui::profiler_window()` with the egui context, you can visualize the profiling data generated by puffin. ```rust puffin_egui::profiler_window(egui_ctx); ``` -------------------------------- ### Custom Puffin Profiler UI Integration in Egui Rust App Source: https://context7.com/embarkstudios/puffin/llms.txt This code illustrates a more customized integration of the Puffin profiler UI within an egui application. It uses `GlobalProfilerUi` to manage the profiler's display, allowing the user to toggle its visibility via a menu bar and displaying it in a separate, resizable window titled 'Performance'. ```rust use puffin_egui::{GlobalProfilerUi, profiler_ui}; struct MyApp { profiler_ui: GlobalProfilerUi, show_profiler: bool, } impl Default for MyApp { fn default() -> Self { puffin::set_scopes_on(true); Self { profiler_ui: GlobalProfilerUi::default(), show_profiler: false, } } } impl eframe::App for MyApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { puffin::profile_function!(); // Menu bar egui::TopBottomPanel::top("menu").show(ctx, |ui| { ui.horizontal(|ui| { ui.checkbox(&mut self.show_profiler, "Show Profiler"); }); }); // Main content egui::CentralPanel::default().show(ctx, |ui| { puffin::profile_scope!("main_ui"); ui.heading("Application"); }); // Profiler in custom window if self.show_profiler { egui::Window::new("Performance") .default_size([1200.0, 800.0]) .show(ctx, |ui| { self.profiler_ui.ui(ui); }); } puffin::GlobalProfiler::lock().new_frame(); } } ``` -------------------------------- ### Rust: Profile function and scope with puffin Source: https://github.com/embarkstudios/puffin/blob/main/puffin_egui/README.md This snippet demonstrates how to use puffin's macros to profile specific functions and code blocks. `puffin::profile_function!()` should be placed at the beginning of a function, and `puffin::profile_scope!()` can be used for more granular profiling within a function, optionally including dynamic data. ```rust fn my_function() { puffin::profile_function!(); if ... { puffin::profile_scope!("load_image", image_name); ... } } ``` -------------------------------- ### Custom Scopes with Manual Lifetime using Rayon Source: https://context7.com/embarkstudios/puffin/llms.txt Demonstrates how to use custom profiling scopes with manual lifetime management, specifically with the Rayon parallel processing library. This allows profiling work done by worker threads across their entire segment of work. It requires the `puffin` and `rayon` crates. ```rust use puffin::profile_scope_custom; fn parallel_processing() { use rayon::prelude::*; let items: Vec<_> = (0..1000).collect(); items.par_iter().for_each_init( // Initialize profiler scope for each worker thread || profile_scope_custom!("rayon_worker"), // Scope persists for entire work segment |((_scope), item)| { // All work in this closure is profiled together process_item(*item); } ); } fn process_item(item: i32) { std::thread::sleep(std::time::Duration::from_micros(100)); } ``` -------------------------------- ### Show Profiler Viewport with puffin-egui Source: https://context7.com/embarkstudios/puffin/llms.txt Integrates the Puffin profiler's UI into an egui application. The profiler viewport automatically appears when profiling is enabled and is hidden when disabled by closing the viewport. This requires the `puffin-egui` crate. ```rust use puffin_egui::show_viewport_if_enabled; impl eframe::App for MyApp { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { puffin::profile_function!(); // Your app code egui::CentralPanel::default().show(ctx, |ui| { if ui.button("Enable Profiler").clicked() { puffin::set_scopes_on(true); } }); // Show profiler in separate viewport/window // Automatically appears when profiling is enabled // Closing it disables profiling show_viewport_if_enabled(ctx); puffin::GlobalProfiler::lock().new_frame(); } } ``` -------------------------------- ### Profile Scopes with Dynamic Data in Rust Source: https://context7.com/embarkstudios/puffin/llms.txt Measure specific code blocks using `profile_scope!`. This macro allows for custom scope names and can include dynamic data, such as formatted strings, to provide more context for performance analysis. ```rust use puffin::profile_scope; fn process_frame() { puffin::profile_function!(); { profile_scope!("update_physics"); // Physics code here update_entities(); resolve_collisions(); } { profile_scope!("render", format!("entity_count: {}", entities.len())); // Rendering code with dynamic data render_scene(); } // Named scopes for more granular profiling for mesh in meshes.iter() { profile_scope!("process_mesh", mesh.name); mesh.update(); } } ``` -------------------------------- ### Profile Functions with Dynamic Data in Rust Source: https://context7.com/embarkstudios/puffin/llms.txt Automatically capture the execution time of functions using `profile_function!`. This macro can optionally accept dynamic arguments to enrich the profiling data, helping to identify specific slow cases. ```rust use puffin::profile_function; fn load_texture(path: &str) -> Texture { // Automatically names scope after the function profile_function!(); let data = std::fs::read(path).unwrap(); Texture::from_bytes(&data) } fn parse_config(filename: &str) -> Config { // Add dynamic data to help identify slow cases profile_function!(filename); let content = std::fs::read_to_string(filename).unwrap(); serde_json::from_str(&content).unwrap() } ``` -------------------------------- ### Register Custom User Scopes for Profiling Source: https://context7.com/embarkstudios/puffin/llms.txt Shows how to define and register custom scope details with Puffin's GlobalProfiler. This is useful for integrating external profiling data or marking specific operations that are not directly within Rust code. It requires the `puffin` crate. ```rust use puffin::{GlobalProfiler, ScopeDetails, ScopeType, StreamInfoRef, Stream}; use std::borrow::Cow; fn register_custom_profiling() { let mut profiler = GlobalProfiler::lock(); // Define custom scope details let custom_scopes = vec![ ScopeDetails { scope_id: None, // Will be assigned by puffin function_name: Cow::Borrowed("custom_operation"), file_path: Cow::Borrowed("external_system.rs"), line_nr: 42, scope_name: Some(Cow::Borrowed("external_api")), scope_type: ScopeType::Named, }, ]; // Register and get assigned IDs let scope_ids = profiler.register_user_scopes(&custom_scopes); // Later, report timing data for these scopes // This is advanced usage for integrating external profiling data } ``` -------------------------------- ### Frame Management for Multi-Threaded Profiling in Rust Source: https://context7.com/embarkstudios/puffin/llms.txt Manage profiling frames and collect data from multiple threads using `puffin::GlobalProfiler`. Call `GlobalProfiler::lock().new_frame()` at the beginning of each frame to aggregate all collected profiling data. This is crucial for accurate performance analysis in applications with concurrent operations. ```rust use puffin::GlobalProfiler; fn main() { puffin::set_scopes_on(true); // Game loop loop { // Mark frame boundary - collects all thread data GlobalProfiler::lock().new_frame(); { puffin::profile_scope!("game_update"); update_game_logic(); } { puffin::profile_scope!("render"); render_frame(); } } } fn update_game_logic() { puffin::profile_function!(); // Spawn worker thread std::thread::spawn(|| { puffin::profile_scope!("background_task"); process_async_work(); }); } ``` -------------------------------- ### Enable/Disable Global Profiling in Rust Source: https://context7.com/embarkstudios/puffin/llms.txt Control the global state of the Puffin profiler. When disabled, profiling macros incur minimal overhead (around 1ns per scope check). When enabled, the overhead per scope increases to approximately 50-200ns. ```rust use puffin; // Turn profiling on/off globally puffin::set_scopes_on(true); // Check if profiling is enabled if puffin::are_scopes_on() { println!("Profiling is active"); } // When off, profile macros have only 1ns overhead // When on, each scope costs ~50-200ns ``` -------------------------------- ### Conditional Profiling in Rust with Puffin Source: https://context7.com/embarkstudios/puffin/llms.txt Use `profile_function_if!` and `profile_scope_if!` to conditionally enable profiling for specific code sections. This is useful for reducing overhead in frequently called but often fast operations, or when profiling is only relevant under certain conditions (e.g., processing large batches). ```rust use puffin::{profile_function_if, profile_scope_if}; // Profile only when processing large batches fn process_batch(items: &[Item]) { profile_function_if!(items.len() > 1000); for item in items { // Don't profile for small operations if item.data.len() > 100 { profile_scope_if!(true, "large_item", item.id); item.process(); } else { item.process(); } } } // Avoid profiler overhead for frequent fast calls fn physics_step(num_iterations: usize) { // Only profile when doing expensive work profile_function_if!(num_iterations > 5000); for _ in 0..num_iterations { update_single_step(); } } ```