heaptrack

repository·master·Indexed 26 days ago

https://github.com/kde/heaptrack

A high-performance heap memory profiler for Linux that traces memory allocations to identify leaks, allocation hotspots, and temporary allocations. It includes a data collector, a GUI analyzer (heaptrack_gui), and a command-line analyzer (heaptrack_print). The project also includes robin-map, a header-only C++ library providing high-performance maps and sets with various growth policies.

Tokens
3.5K
Snippets
8
Records
16
Agent score
38%

What's inside heaptrack

  1. Compile heaptrack from source

    master

    Heaptrack consists of the heaptrack data collector and the heaptrack_gui analyzer. To compile on Linux, ensure you have the required dependencies (CMake, C++11 compiler, zlib, elfutils, etc.) installed.

    Note: If you are on an embedded device, you may only want to build the heaptrack collector to save resources, then analyze the data on a modern Linux machine with the GUI.

    cd heaptrack
    mkdir build
    cd build
    cmake -DCMAKE_BUILD_TYPE=Release ..
    make -j$(nproc)
  2. Anonymize heaptrack data for bug reports

    master

    When submitting bug reports to KDE, you can anonymize your heaptrack data files using the provided tools/anonymize script to protect sensitive information.

    tools/anonymize heaptrack.APP.PID.gz heaptrack.bug_report_data.gz
  3. Use heterogeneous lookups in robin-map

    master

    Heterogeneous lookups allow you to use types different from the Key type for find and erase operations without constructing a full Key object.

    To enable this, the KeyEqual type must have a using is_transparent = void; member. You can use std::equal_to<> to automatically deduce and forward parameters, or provide a custom comparator.

    Note: The Hash function must also be able to handle the alternative types.

    struct equal_employee {
        using is_transparent = void;
        
        bool operator()(const employee& empl, int empl_id) const {
            return empl.m_id == empl_id;
        }
        // ... other overloads
    };
    
    // Usage:
    // Use a custom KeyEqual which has an is_transparent member type
    tsl::robin_map<employee, int, hash_employee, equal_employee> map2;
    map2.insert({employee(4, "Johnny Doe"), 2004});
    auto it = map2.find(4); // Works with int key
  4. Compile heaptrack_gui on macOS using Homebrew

    master

    To build the GUI and heaptrack_print on macOS, use Homebrew to install the KDE and Qt 5 dependencies. You must also perform manual symlinking steps for KDE Frameworks to work correctly in the macOS Application Support directory.

    # Install Qt 5
    brew install qt@5
    
    # Prepare KDE tap
    brew tap kde-mac/kde https://invent.kde.org/packaging/homebrew-kde.git
    "$(brew --repo kde-mac/kde)/tools/do-caveats.sh"
    
    # Install dependencies
    brew install kde-mac/kde/kf5-kcoreaddons kde-mac/kde/kf5-kitemmodels kde-mac/kde/kf5-kconfigwidgets \
                 kde-mac/kde/kf5-kio kde-mac/kde/kdiagram \
                 extra-cmake-modules ki18n threadweaver \
                 boost zstd gettext
    
    # Run manual symlinking steps
    ln -sfv "$(brew --prefix)/share/kf5" "$HOME/Library/Application Support"
    ln -sfv "$(brew --prefix)/share/knotifications5" "$HOME/Library/Application Support"
    ln -sfv "$(brew --prefix)/share/kservices5" "$HOME/Library/Application Support"
    ln -sfv "$(brew --prefix)/share/kservicetypes5" "$HOME/Library/Application Support"
    
    # Compile
    cd heaptrack
    mkdir build
    cd build
    CMAKE_PREFIX_PATH=/opt/homebrew/opt/qt@5 PATH=$PATH:/opt/homebrew/opt/gettext/bin cmake ..
    cmake -DCMAKE_BUILD_TYPE=Release ..
    make heaptrack_gui heaptrack_print
  5. Profile on embedded machines with remote interpretation

    master

    On embedded systems where debug symbols are unavailable, record a raw trace file first, then move it to a development machine with the necessary symbols (SDK/sysroot) for interpretation.

    1. Record the raw trace on the embedded device using --raw.
    2. Interpret the raw file on your development machine using --sysroot.
    3. Analyze the interpreted data.

    You can use --debug-paths to provide additional directories containing debug information, or --extra-paths to load debug information from specific build folders (e.g., for sideloaded binaries).

  6. Install robin-map

    master

    robin-map is a header-only C++ library. You can use it by adding the include/ directory to your include path.

    If using CMake, you can add the project as a subdirectory and link against the tsl::robin_map target:

    add_subdirectory(third-party/robin-map)
    target_link_libraries(your_target PRIVATE tsl::robin_map)

    Alternatively, if installed via make install, use find_package(tsl-robin-map REQUIRED). The library is also available via package managers like vcpkg, conan, Debian, Ubuntu, and Fedora.

    # Example where the robin-map project is stored in a third-party directory
    add_subdirectory(third-party/robin-map)
    target_link_libraries(your_target PRIVATE tsl::robin_map)
  7. Profile Rust applications with heaptrack

    master

    Heaptrack supports Rust binaries and demangles Rust symbols if rustc_demangle is available.

    Requirements:

    1. Debug Symbols: Ensure debug symbols are enabled in your Cargo.toml:

      [profile.release]
      debug = true

      Note: If using a Workspace, add this to the Workspace Cargo.toml.

    2. Execution: Do NOT run heaptrack cargo run, as this profiles Cargo instead of your app. Instead:

      • Run the compiled binary directly: heaptrack ./target/release/my-rust-app
      • Or use the unofficial cargo-heaptrack crate: cargo heaptrack.

    GUI Tip: To open Rust source files directly from the GUI, launch heaptrack_gui from the root of your project (or workspace root) so that file paths remain relative and correct.

    # Cargo.toml
    [profile.release]
    debug = true
    # Correct way to run
    heaptrack ./target/release/my-rust-app
  8. Use heaptrack to profile an application

    master

    To profile an application from the start, run heaptrack followed by your application and its parameters. This will generate a trace file in /tmp/heaptrack.APP.PID.gz. Once the application finishes, use heaptrack --analyze to investigate the data.

    Alternatively, you can attach to an already running process using its PID:

  9. Manage large heaptrack profiles

    master

    Large profiles (e.g., from hour-long runs) can be slow to load in the GUI because the data cannot be seeked efficiently.

    Mitigation strategies:

    1. Frequent restarts: Restart heaptrack profiling every N minutes to generate smaller, fresh profile files.
    2. Trimming: Use the unofficial tool heaptrack-trim to extract a subset of a large profile before attempting to load it into the GUI.
  10. Avoid performance pitfalls in robin-map

    master

    1. Bad Hashes and Exponential Growth

    Using the default power_of_two_growth_policy with an identity hash (common for arithmetic types) can lead to massive collisions. If collisions exceed a threshold, the table expands, but if the hash function is poor, this expansion may not resolve collisions, leading to exponential storage growth. Solution: Use a better hash function or switch to tsl::robin_pg_map/set (prime growth policy).

    2. Slow Erasure with Low Load Factors

    Standard erase(iterator) is expensive when the load factor is low because it must walk to the next non-empty bucket to return a valid iterator. Solution: Use void erase_fast(iterator) if you do not need the returned iterator. This avoids the cost of finding the next element.

  11. Handle issues with old gold linker backtraces

    master

    If libunwind produces bogus backtraces due to an old version of the gold linker, heaptrack_gui may crash with out-of-memory errors when parsing the data. You can identify this by checking heaptrack_print output for broken backtraces.

    Solution: Relink both your application and libunwind using ld.bfd instead of ld.gold.

  12. Run heaptrack on ASAN-instrumented executables

    master

    If you attempt to run heaptrack on an application built with Address Sanitizer (ASAN), you may encounter the fatal error: ASan runtime does not come first in initial library list [...].

    To resolve this, use the --asan flag.

    Note: This only works for binaries built with gcc (linking to libasan.so). Binaries built with clang's ASAN are currently not supported.