update docs

This commit is contained in:
2025-12-17 00:36:21 +01:00
parent a9d0d7ec42
commit 873e6419b8

View File

@@ -2,64 +2,57 @@
A lightweight, debug-only telemetry profiler for Rust applications. Shows thread activity and call stack hierarchy in real-time.
Inspired by RAD Telemetry - built in ~1200 LOC with 'minimal' dependencies (for a Rust project).
Inspired by RAD Telemetry - built in ~1200 LOC with minimal dependencies.
## Features
- **Icicle graph** showing call stack hierarchy (top half)
- **Thread timeline** showing per-thread activity over time (bottom half)
- **Unified thread tracks** with expandable call stacks (click headers to toggle)
- **Collapsed view** shows when threads are active (easy to spot blocking)
- **Expanded view** shows full call stack hierarchy with flame graph visualization
- **Ongoing span support** for long-running functions (main loops, render threads)
- **Pause mechanism** to freeze your application for inspection (Space bar)
- **Monokai color palette** for easy visual distinction
- **Pause mechanism** to freeze your application for inspection
- **Incremental tree building** - only processes new spans each frame
- **Ringbuffer storage** (~16MB, 1M events) for recent history
- **Lock-free event recording** via MPSC channels
## Dependencies
Only 7 dependencies (~70 total including transitive):
Only 7 direct dependencies (~70 total including transitive):
- `minifb` - Window and framebuffer
- `crossbeam-channel` - Lock-free MPSC
- `once_cell` - Lazy statics
- `fontdue`
- `procmacro2`
- `syn`
- `quote`
- `fontdue` - Font rasterization
- `procmacro2`, `syn`, `quote` - Proc macros
## Usage
### Add to your `Cargo.toml`:
```toml
[dependencies]
teleprof = { path = "../teleprof" }
```
### In your code:
```rust
fn main() {
// Start the profiler window (separate thread)
#[cfg(debug_assertions)]
teleprof::start();
// Your application code
// Name your thread (optional, shows in UI)
#[cfg(debug_assertions)]
teleprof::set_thread_name("main");
game_loop();
}
fn game_loop() {
loop {
// Profile a scope
teleprof::span!("game_loop");
teleprof::span!("main_frame");
update();
render();
// Check if paused (optional)
if teleprof::PAUSE.try_lock().is_err() {
// Wait until unpaused
while teleprof::PAUSE.try_lock().is_err() {
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
}
}
@@ -74,18 +67,13 @@ fn render() {
}
```
### For closures:
```rust
let work = || {
teleprof::span!("my_closure");
// work...
};
```
## Controls
- **Space**: Toggle pause (acquires `PAUSE` lock to freeze your app)
- **Space**: Toggle pause (freezes ongoing spans at current time)
- **Left click + drag**: Box select to zoom (click background not function)
- **Right click + drag**: Pan timeline
- **Scroll**: Zoom timeline horizontally
- **Click track header**: Expand/collapse thread's call stack
- **Escape**: Close profiler window
## How it works
@@ -94,19 +82,20 @@ let work = || {
2. When the guard drops, sends `SpanEnd`
3. Events are sent via lock-free MPSC channel
4. Window thread drains events into a fixed-size ringbuffer
5. Renders icicle graph (call hierarchy) and timeline (per-thread activity)
5. Incrementally builds per-thread call trees (only processes new spans)
6. Renders unified thread tracks with expandable call stacks
## Design Goals
- **Minimal overhead**: Lock-free event recording
- **Minimal overhead**: Lock-free event recording, incremental tree building
- **Debug-only**: Compile out in release builds with `#[cfg(debug_assertions)]`
- **Separate window**: Doesn't interfere with your app's rendering
- **Simple API**: Just `span!("name")` and you're done
- **Handle any thread pattern**: Long-lived, short-lived, thread pools (Rayon, etc.)
## Examples
Run the included examples:
```bash
# Multi-threaded physics simulation
cargo run --example demo
@@ -122,4 +111,4 @@ The bouncing ball example demonstrates:
## License
???
???