first commit, not pretty
This commit is contained in:
141
README.md
Normal file
141
README.md
Normal file
@@ -0,0 +1,141 @@
|
||||
# Teleprof
|
||||
|
||||
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 ~400 LOC with minimal dependencies.
|
||||
|
||||
## Features
|
||||
|
||||
- **Icicle graph** showing call stack hierarchy (top half)
|
||||
- **Thread timeline** showing per-thread activity over time (bottom half)
|
||||
- **Monokai color palette** for easy visual distinction
|
||||
- **Pause mechanism** to freeze your application for inspection
|
||||
- **Ringbuffer storage** (~16MB, 1M events) for recent history
|
||||
- **Lock-free event recording** via MPSC channels
|
||||
|
||||
## Dependencies
|
||||
|
||||
Only 3 dependencies (~15 total including transitive):
|
||||
- `minifb` - Window and framebuffer
|
||||
- `crossbeam-channel` - Lock-free MPSC
|
||||
- `once_cell` - Lazy statics
|
||||
|
||||
## Usage
|
||||
|
||||
### Add to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
teleprof = { path = "../teleprof" } # or from crates.io when published
|
||||
```
|
||||
|
||||
### In your code:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
// Start the profiler window (separate thread)
|
||||
#[cfg(debug_assertions)]
|
||||
teleprof::start();
|
||||
|
||||
// Your application code
|
||||
game_loop();
|
||||
}
|
||||
|
||||
fn game_loop() {
|
||||
loop {
|
||||
// Profile a scope
|
||||
teleprof::span!("game_loop");
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update() {
|
||||
teleprof::span!("update");
|
||||
// Your update code
|
||||
}
|
||||
|
||||
fn render() {
|
||||
teleprof::span!("render");
|
||||
// Your render code
|
||||
}
|
||||
```
|
||||
|
||||
### For closures:
|
||||
|
||||
```rust
|
||||
let work = || {
|
||||
teleprof::span!("my_closure");
|
||||
// work...
|
||||
};
|
||||
```
|
||||
|
||||
## Controls
|
||||
|
||||
- **Space**: Toggle pause (acquires `PAUSE` lock to freeze your app)
|
||||
- **Escape**: Close profiler window
|
||||
|
||||
## How it works
|
||||
|
||||
1. `span!()` macro creates a `SpanGuard` that sends `SpanStart` on creation
|
||||
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)
|
||||
|
||||
## Design Goals
|
||||
|
||||
- **Minimal overhead**: Lock-free event recording
|
||||
- **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
|
||||
|
||||
## Example Output
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Icicle Graph (Call Stack) │
|
||||
│ ┌──────────────────────────┐ │
|
||||
│ │ frame_work │ │
|
||||
│ ├──────────┬───────────────┤ │
|
||||
│ │ physics │ render │ │
|
||||
│ ├────┬─────┤ │ │
|
||||
│ │ w0 │ w1 │ │ │
|
||||
│ └────┴─────┴───────────────┘ │
|
||||
├─────────────────────────────────────┤
|
||||
│ Thread Timeline │
|
||||
│ Main: ████████████████████ │
|
||||
│ Work 0: ░░██████░░░░░░░░░░░ │
|
||||
│ Work 1: ░░░░░░██████░░░░░░░ │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Run the included examples:
|
||||
|
||||
```bash
|
||||
# Multi-threaded physics simulation
|
||||
cargo run --example demo
|
||||
|
||||
# Bouncing ball with color-picking thread (30 FPS)
|
||||
cargo run --example bouncing_ball
|
||||
```
|
||||
|
||||
The bouncing ball example demonstrates:
|
||||
- Main thread running at 30 FPS with clear frame gaps
|
||||
- Background thread spawned on wall collision to pick colors
|
||||
- Clear visual separation between thread activities
|
||||
|
||||
## License
|
||||
|
||||
MIT / Apache-2.0 (choose whichever you prefer)
|
||||
Reference in New Issue
Block a user