Skip to content

Commit

Permalink
Memory things.
Browse files Browse the repository at this point in the history
  • Loading branch information
den-mentiei committed Jan 31, 2024
1 parent 40b939a commit a7360b5
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 12 deletions.
10 changes: 8 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
### Removed

## [Unreleased] - 2024-xx-xx
## [0.0.8] - 2024-01-31

### Added

- `#[capture]` attribute to instrument main added.
- `#[instrument("prefix")]` is now supported.
- `emit_alloc!` & `emit_free!` to track allocations.

### Fixed

- `sys` is no longer compiled when we are not `enabled`, but some
other features are set (e.g. `no-exit`).
- `set_thread_name!` wasn't respecting `enabled` feature-gate
properly, sigh.

### Changed

- minor example updates
- `plot!` can now be used in expression position.

## [0.0.7] - 2024-01-19

Expand Down Expand Up @@ -89,7 +94,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Initial implementation of zones, frames, plots & messages

[unreleased]: https://github.com/den-mentiei/tracy-gizmos/compare/v0.0.7...HEAD
[unreleased]: https://github.com/den-mentiei/tracy-gizmos/compare/v0.0.8...HEAD
[0.0.8]: https://github.com/den-mentiei/tracy-gizmos/compare/v0.0.7..v0.0.8
[0.0.7]: https://github.com/den-mentiei/tracy-gizmos/compare/v0.0.6..v0.0.7
[0.0.6]: https://github.com/den-mentiei/tracy-gizmos/compare/v0.0.5..v0.0.6
[0.0.5]: https://github.com/den-mentiei/tracy-gizmos/compare/v0.0.4..v0.0.5
Expand Down
18 changes: 10 additions & 8 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
# TODO

- [ ] what's up with locks & C API
- [ ] xtasks for tests/deploy
- [ ] add examples readme and comment them more
- [ ] add messages example
- [ ] auto-function proc-macro attributes:
- [x] #[instrument]
- [ ] #[instrument(name)]
- [ ] #[instrument(color)]
- [ ] #[instrument(name, color)]
- [ ] #[instrument(name=...)]
- [ ] #[instrument(color=...)]
- [ ] #[instrument(prefix|name=...?, color=...)]
- [ ] + callstacks?! + enabled
- [ ] + parameters to include as dynamic data
- [x] #[instrument]
- [x] #[instrument(prefix)]
- [x] write nice error messages :Errors
- [ ] proc-macro attribute over impl to mark every method
- [ ] ability to skip methods
- [ ] support `plot!` in expr pos
- [ ] add proc-macro attribute tests
- [ ] callstacks! depth is at most 62
- [ ] what's up with locks & C API
- [ ] what's up with alloc & free, named overloads
- [ ] gfx things
- [ ] dbghelp thread-safety on windows
- [x] add examples readme and comment them more
- [x] what's up with alloc & free, named overloads
- [x] fix set thread name feature enabled gate
- [x] support `plot!` in expr pos
- [x] ci on github
- [x] proc-macro attribute to mark main and setup the capture
- [x] rename start & tracy client
Expand Down
3 changes: 3 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Examples

`@Incomplete`
31 changes: 31 additions & 0 deletions examples/examples/memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use std::{
alloc::{alloc, dealloc, Layout},
thread::sleep,
time::Duration,
};

use tracy_gizmos::{
emit_alloc,
emit_free,
};

fn main() {
println!("Connecting to Tracy...");
let tracy = tracy_gizmos::start_capture();

// This could be removed if `no-exit` feature is enabled.
while !tracy.is_connected() {
std::thread::yield_now();
}

for i in 0..10 {
let layout = Layout::array::<u64>(i).unwrap();
let ptr = unsafe { alloc(layout) };
if !ptr.is_null() {
emit_alloc!("global", ptr, layout.size());
sleep(Duration::from_millis(10));
emit_free!("global", ptr);
unsafe { dealloc(ptr, layout) };
}
}
}
6 changes: 4 additions & 2 deletions examples/examples/plots.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::thread::sleep;
use std::time::{SystemTime, UNIX_EPOCH, Duration};
use std::{
thread::sleep,
time::{SystemTime, UNIX_EPOCH, Duration},
};

use tracy_gizmos::{
Color,
Expand Down
24 changes: 24 additions & 0 deletions tracy-gizmos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ use std::marker::PhantomData;
pub use attrs::{instrument, capture};

mod color;
mod memory;
mod plot;

pub use color::*;
Expand Down Expand Up @@ -175,6 +176,7 @@ pub use plot::*;
#[macro_export]
macro_rules! set_thread_name {
($name:literal) => {
// @Bug It doesn't work this way.
#[cfg(feature = "enabled")]
// SAFETY: We null-terminate the string.
unsafe {
Expand All @@ -183,6 +185,7 @@ macro_rules! set_thread_name {
};

($format:literal, $($args:expr),*) => {
// @Bug It doesn't work this way.
#[cfg(feature = "enabled")]
{
let name = format!(concat!($format, '\0'), $($args),*).into_bytes();
Expand Down Expand Up @@ -837,6 +840,7 @@ pub fn app_info(info: &str) {
#[doc(hidden)]
#[cfg(feature = "enabled")]
pub mod details {
use std::ffi::c_void;
use super::*;

#[inline(always)]
Expand Down Expand Up @@ -924,6 +928,26 @@ pub mod details {
Frame(name)
}

#[inline(always)]
pub unsafe fn track_alloc<T>(name: *const u8, ptr: *const T, size: usize) {
track_alloc_impl(name, ptr.cast(), size);
}

#[inline(always)]
unsafe fn track_alloc_impl(name: *const u8, ptr: *const c_void, size: usize) {
sys::___tracy_emit_memory_alloc_named(ptr, size, 0, name.cast());
}

#[inline(always)]
pub unsafe fn track_free<T>(name: *const u8, ptr: *const T) {
track_free_impl(name, ptr.cast());
}

#[inline(always)]
unsafe fn track_free_impl(name: *const u8, ptr: *const c_void) {
sys::___tracy_emit_memory_free_named(ptr, 0, name.cast());
}

// Function name trick only works with an unstable
// feature, which provides const `type_name`. Tracking
// issue on the Rust side:
Expand Down
133 changes: 133 additions & 0 deletions tracy-gizmos/src/memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/// Marks a memory allocation event.
///
/// Tracy can monitor the memory usage of your application. Knowledge
/// about each performed memory allocation enables the following:
/// - memory usafe graph (like in massif, but interactive)
/// - list of active allocations at program exit
/// - memory map visualization
/// - ability to rewidne the view of active allocations
/// and memory map to any point of program exection
/// - memory statistics of each profiling zone
/// - memory allocation hot-spot tree.
///
/// A custom name is required for the allocation, which allows to
/// identify it later in the Trace visualization. It also allow to
/// support multiple memory allocators/pools/arenas.
///
/// # Danger
///
/// Each tracked memory-free event must also have a corresponding
/// allocation event. Tracy will terminate the profiling session if
/// this assumptions is broken. If this ever happens to you, one may
/// want to check for:
/// - mismatched alloc/free
/// - reporting same memory address allocated twise (without a free
/// in-between)
/// - double-free
/// - untracked external allocations, which are freed by application code
///
/// # Examples
///
/// ```no_run
/// # use tracy_gizmos::*;
/// # fn allocate(size: usize) -> *mut u8 { todo!() }
/// # let size: usize = 1024;
/// let mut buf = allocate(size);
/// emit_alloc!("scratch", buf, size);
/// // ... work with buf ...
/// emit_free!("scratch", buf);
/// ```
#[macro_export]
#[cfg(any(doc, feature = "enabled"))]
macro_rules! emit_alloc {
($pool:literal, $ptr:expr, $size:expr) => {
// SAFETY: We null-terminate the string.
unsafe {
$crate::details::track_alloc(
concat!($pool, '\0').as_ptr(),
$ptr,
$size,
);
}
};
}

#[macro_export]
#[cfg(all(not(doc), not(feature = "enabled")))]
macro_rules! emit_alloc {
($pool:literal, $ptr:expr, $size:expr) => {
// Silences unused enabled expression warnings.
_ = $ptr;
_ = $size;
};
}

/// Marks a memory freeing event.
///
/// Tracy can monitor the memory usage of your application. Knowledge
/// about each performed memory allocation enables the following:
/// - memory usafe graph (like in massif, but interactive)
/// - list of active allocations at program exit
/// - memory map visualization
/// - ability to rewidne the view of active allocations
/// and memory map to any point of program exection
/// - memory statistics of each profiling zone
/// - memory allocation hot-spot tree.
///
/// A custom name is required for the allocation, which allows to
/// identify it later in the Trace visualization. It also allow to
/// support multiple memory allocators/pools/arenas.
///
/// # Danger
///
/// Each tracked memory-free event must also have a corresponding
/// allocation event. Tracy will terminate the profiling session if
/// this assumptions is broken. If this ever happens to you, one may
/// want to check for:
/// - mismatched alloc/free
/// - reporting same memory address allocated twise (without a free
/// in-between)
/// - double-free
/// - untracked external allocations, which are freed by application code
///
/// # Examples
///
/// ```no_run
/// # use tracy_gizmos::*;
/// # fn allocate(size: usize) -> *mut u8 { todo!() }
/// # let size: usize = 1024;
/// let mut buf = allocate(size);
/// emit_alloc!("scratch", buf, size);
/// // ... work with buf ...
/// emit_free!("scratch", buf);
/// ```
#[macro_export]
#[cfg(any(doc, feature = "enabled"))]
macro_rules! emit_free {
($pool:literal, $ptr:expr) => {
// SAFETY: We null-terminate the string.
unsafe {
$crate::details::track_free(
concat!($pool, '\0').as_ptr(),
$ptr,
);
}
};
}

#[macro_export]
#[cfg(all(not(doc), not(feature = "enabled")))]
macro_rules! emit_free {
($pool:literal, $ptr:expr) => {
// Silences unused enabled expression warning.
_ = $ptr;
};
}

/// Implementation details, do not relay on anything from this module!
///
/// It is public only due to the usage in public macro bodies.
#[doc(hidden)]
#[cfg(feature = "enabled")]
pub mod details {
}

0 comments on commit a7360b5

Please sign in to comment.