Skip to content

Latest commit

 

History

History
70 lines (59 loc) · 2.88 KB

memory profiler.md

File metadata and controls

70 lines (59 loc) · 2.88 KB

Memory Profiler

  • Measuring memory usage in Rust

    • The application does too many short-lived allocations (instead of re-using the buffers) the instrumenting the calls to allocation and deallocation approach.
    • If in a steady state, the application uses too much memory, the heap parsing would work better for pointing out which data structures need the most attention.
  • How to write heap memory profiler?

  • Goals

    • Cope with thousands or even millions of trace events per second
    • Ideally, zero overhead when not used
    • Support for runtime attaching or similar
  • Good to know

    • Prefer to use existing tracing frameworks
    • perf with sdt / uprobe
    • LLVM - Xray
  • Steps

    • Inject custom code into the application
    • Intercept call to heap allocation, deallocation function
    • Backtrace deallocation and allocation
    • Tracing and profiling should be fast, Post process should be delayed.
  • Target functions

// libc functions
malloc, free
realtoc, calloc
posix_memalign, aligned_alloc, vat loc

// libc++ functions
operator new, operator new[]]
operator delete, operator delete[]
Each with a couple of overloads, e.g. std::atign_val_t
  • Approach

    • use the dynamic linker to inject custom library code
    • LD_PRELAOD=$(readlink -f path/to/lib.so) app
    • c++ does not define how the linker works, it works on the linux level
    • replacing library malloc call
  • Good to know before understanding the code below

    • learn about extern
      • Declare anywhere, use that declared part
    • learn about dlsym
    • Static cast vs reinterpret_cast
    • reinterpret_cast is dangerous
      • class object -> func(param one) gets converted to class::func(*this, param)
    • reinterpret_cast can perform dangerous conversions because it can typecast any pointer to any other pointer
    • reinterpret_cast is used when you want to work with bits
    • the result of a reinterpret_cast cannot safely be used for anything other than being cast back to its original type
    • if we use this type of cast then it becomes a non-portable product
#include <dlfcn.h> // dlsym
extern "C" {
    void* malloc(sizt_t size) {
        static void* original_malloc(RTLD_NEXT ,"malloc") ;
        assert(original_malloc);
        auto *original_malloc_fn = reinterpret_cast<decltype(&::malloc)> (original_malloc);
        void •ret = original_malloc_fn(size);
        fprtntf(stderr, "mattoc intercepted: gozu oop\n",
 size, ret);
        return ret;
 }
}