sparkles 0.1.7

Capture execution flow of your Rust application with CPU cycle precision!
Documentation
# .γƒ»γ‚œγ‚œ π•Šβ„™π”Έβ„π•‚π•ƒπ”Όπ•Š γƒ»γ‚œγ‚œγƒ»
<img src="https://img.shields.io/crates/v/sparkles"></img>
<img src="https://img.shields.io/crates/size/sparkles"></img>

Performance-focused library for capturing execution flow of your application.

![img_1.png](https://github.com/skibon02/sparkles/blob/main/img_1.png?raw=true)

**What?**  
Simply add the instant_event! macro to your code with a string literal and you'll be able to view this event later on a timeline with CPU cycle precision.  
**How?**  
Fast. Blazingly fast. πŸš€ Recording a single event incurs an overhead as low as 10ns and consumes only 3 bytes in the trace buffer (in dense tracing conditions).

˚ ༘ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘Λš ༘ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘ΛšΛš ༘ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘Λš ༘ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘ΛšΰΌ˜ β‹†ο½‘Λš ✧ ˚ ༘  
Up to 🫸100_000_000🫷 events per second can be captured in a local environment with no data loss.  
༘ β‹†ο½‘Λš ༘ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘ΛšΰΌ˜ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘ΛšΰΌ˜ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘ΛšΰΌ˜ β‹†ο½‘Λš ✧ ˚ ༘ β‹†ο½‘ΛšΰΌ˜ β‹†ο½‘Λš ✧ ˚

## ✧ Main parts
- **sparkles**: Ready-to-use library for capturing events and saving them to file in lightweight encoded format.
- **sparkles-core**: Common functionality for std and no_std (todo) version of sparkles and protocol packets.
- **sparkles-macro**: instant_event! and range_event_start! macro to encode event name into integer value.
- **sparkles-parser**: Provides easy to use way of converting recorded trace data to Perfetto format as well as library for realtime parsing.

## ✧ How to use
1. Add sparkles as a dependency to your project
```bash
cargo add sparkles 
cargo add sparkles-macro
```
2. Add some instant/range events to your code

```rust
use std::time::Duration;
use sparkles_macro::{instant_event, range_event_start};

// Refer to sparkles/examples/how_to_use.rs
fn main() {
    let finalize_guard = sparkles::init_default();
    let g = range_event_start!("main()");

    let jh = std::thread::Builder::new().name(String::from("joined thread")).spawn(|| {
        for _ in 0..100 {
            instant_event!("^-^");
            std::thread::sleep(Duration::from_micros(1_000));
        }
    }).unwrap();
    
    std::thread::Builder::new().name(String::from("detached thread")).spawn(|| {
        for _ in 0..30 {
            instant_event!("*_*");
            std::thread::sleep(Duration::from_micros(1_000));
        }
    }).unwrap();

    for i in 0..1_000 {
        instant_event!("✨✨✨");
        std::thread::sleep(Duration::from_micros(10));
    }

    jh.join().unwrap();
}
```
3. Run your code. As it finishes, `trace/*.sprk` is generated.
4. Run sparkles-parser in the directory with `trace` folder.
```bash
cargo install sparkles-parser --features bin-deps # Only once
sparkles-parse-and-save
```
5. Go to https://ui.perfetto.dev and drag'n'drop resulting `.perf` file.
6. Observe the result:
![img.png]https://github.com/skibon02/sparkles/blob/main/img.png?raw=true


## ✧ Requirements
🌟 STD support  
🌟 x86/x86_64/aarch64 architecture.  
**OR**  
🌟 Functioning `Instant::now()`

## ✧ Benches
Single event overhead on average x86 machine (Intel i5-12400) is 9ns.


## ✧ Implementation status
Ready:  
🌟 Timestamp provider  
🌟 Event name hashing  
🌟 ~~Perfetto json format compatibility~~ (replaced with protobuf)  
🌟 Ranges (scopes) support  
🌟 Configuration support  
🌟 Perfetto protobuf format support  
🌟 Abstraction over events sending type (UDP/File)  
🌟 Automatic timestamp frequency detection  
🌟 aarch64 support  
🌟 More explicit and recoverable packets with known pattern  
🌟 Resistance to data loss during transmission  
🌟 UDP real-time reader and parser library API  
🌟 Better timestamp speed interpolation in parser  
🌟 Sparkles-parser: read and parse in separate threads  

TODO:  
βš™οΈ Track changes in structs encoded/decoded by `bincode`  
βš™οΈ Include git revision into build  
βš™οΈ Option to run without additional bg thread  
βš™οΈ Defmt support  
βš™οΈ Additional attached binary data  
βš™οΈ Option to limit total consumed TLS buffer allocation  
βš™οΈ Module info support: full module path, line of code  
βš™οΈ Async support  
βš™οΈ NO_STD implementation  
βš™οΈ tags / hierarchy of events  
βš™οΈ Viewer app  
βš™οΈ Multi-app sync  
βš™οΈ Global ranges  
βš™οΈ Measurement overhead self-test

## Known issues and limitations
✧ Converting timestamp to nanosecond time only have local consistency. Long sessions (day and more) can go out of sync with system clock.  
✧ Currently can have only 256 unique event names per thread  
✧ Currently up to 256 opened but not closed ranges at a time are supported (mostly enough)  
✧ No std support for now  
✧ Naive handling for bad network conditions: if at least one packet lost, the whole tracing data packet is dropped.  
✧ Cannot specify UDP address to listen on  
✧ Proper using of sparkles-macro::range_event_start!("name") gives warning
✧ Timestamp wrap-around is not handled well (not an issue for 64-bit systems)

## Crate features
✧ **accurate-timestamps-x86** - Enable serialization for x86/x86_64 timestamps. Trade off timestamp accuracy for higher overhead (slightly).  
✧ **self-tracing** - Add global buffer flushing events

q゚゚ο½₯qο½₯゚゚q  
οΎŸγ€‚SkyGrel19 ✨  
γ€€οΎŸο½₯qο½₯