Giter Site home page Giter Site logo

tracking-allocator's Introduction

tracking-allocator

A GlobalAlloc-compatible allocator implementation that provides the ability to track allocation events.

examples

As allocators are specialized bits of code, we've included an example in the examples/ folder to show how to use tracking_allocator, rather than putting abbreviated snippets in the README. It is extensively documented, and explains the finer points of using this crate, and what can be acheived with it.

The actual Rust-level documentation is present, and should hopefully be clear and concise, but the example is meant to be how you learn to use the crate, with the Rust-level documentation as a rote "what's that type signature again?" style of reference.

When running the example, you should end up seeing output similar to this:

allocation -> addr=0x55e882b744f0 size=80 group_id=Some(0) tags=None
deallocation -> addr=0x55e882b74490
allocation -> addr=0x55e882b74550 size=12 group_id=Some(1) tags=None
allocation -> addr=0x55e882b74570 size=96 group_id=Some(1) tags=None
deallocation -> addr=0x55e882b74550
deallocation -> addr=0x55e882b74570

tracking-allocator's People

Contributors

jswrenn avatar tobz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

tracking-allocator's Issues

Consider using a drop guard when enabling tracking.

In certain cases, leaving tracking enabled before main exits can lead to reentrancy of the tracking infrastructure as cleanup routines as triggered. As a concrete example, if println! is used in the allocation tracker implementation, this causes a panic at program exit:

  • implicit cleanup routine for stdio runs at end of main
  • this routine takes a lock and mutably borrows some internal state from a RefCell
  • a deallocation happens, which drops us into allocation tracking
  • as we println! in the allocation tracker, this drops us back into the print infrastructure
  • the locks guarding stdout/stderr are reentrant, so we still able to take them
  • the code again tries to mutably borrow some internal state, but alas, it is already borrowed
  • gasp! le panic.

While printing directly in the allocation tracker implementation is not advised, this still represents a general issue where we likely shouldn't be tracking anything past actual program code, which using a drop guard should achieve: we can clear the tracker implementation right before any runtime boilerplate cleanup runs.

Use size of wrapped allocation when calling `AllocationTracker` methods.

Right now, we explicitly use the wrapped object's layout for reporting, which is technically correct from a "show me the allocation as it was requested". However, for workloads with many smaller allocations, we could be using a significantly higher amount of memory by virtue of our wrapper header.

Given that the intent is to report allocations faithfully, and as precisely as we reasonably can, we should likely switch to using the size of the wrapped allocation overall.

Write loom test for token registry update behavior.

We changed the token registry update logic to avoid using arc-swap as it involved allocations on the read path which could lead to reentrant brokenness. However, the code we switched to is a lot lower-level and more unsafe and gnarly.

Luckily, it really just depends on normal atomics so it's likely a ripe candidate to test with loom for correctness.

Program hangs and do not close if we use println! inside enable/disable tracking section without calling println before.

Here is a simple snippet showing the issue :

use std::alloc::System;

#[allow(unused)]
use tracking_allocator::{
    AllocationGroupId, AllocationRegistry, AllocationTracker, Allocator,
};

#[global_allocator]
static GLOBAL: Allocator<System> = tracking_allocator::Allocator::system();

struct StdoutTracker;

impl AllocationTracker for StdoutTracker {
    fn allocated(
        &self,
        addr: usize,
        object_size: usize,
        wrapped_size: usize,
        group_id: AllocationGroupId,
    ) {
        println!(
            "allocation -> addr=0x{:0x} object_size={} wrapped_size={} group_id={:?}",
            addr, object_size, wrapped_size, group_id
        );
    }

    fn deallocated(
        &self,
        addr: usize,
        object_size: usize,
        wrapped_size: usize,
        source_group_id: AllocationGroupId,
        current_group_id: AllocationGroupId,
    ) {
        println!(
            "deallocation -> addr=0x{:0x} object_size={} wrapped_size={} source_group_id={:?} current_group_id={:?}",
            addr, object_size, wrapped_size, source_group_id, current_group_id
        );
    }
}

fn main() {
    AllocationRegistry::set_global_tracker(StdoutTracker)
        .expect("no other global tracker should be set yet");

    // Uncomment this line to see the difference
    // println!("There will be no issue if this line is commented out");

    AllocationRegistry::enable_tracking();

    println!("Will you see me ?");

    AllocationRegistry::disable_tracking();
}

Observed behaviour :

  • program never ends
  • "Will you see me ?" is never printed

If we uncomment the previous println! :

  • program ends
  • "Will you see me ?" is printed

This issue has been reproduced in Rust 1.68.2 on Windows and Linux.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.