tracy-profiler: Haskell bindings for Tracy frame profiler

[ bsd3, library, profiling ] [ Propose Tags ] [ Report a vulnerability ]

Flags

Manual Flags

NameDescriptionDefault
enable

Enable to actually call the Tracy functions and produce data. Otherwise the wrappers will be no-ops.

Disabled
fibers

Enable if your libtracyclient has this enabled.

Disabled
has_callstack

Enable if your libtracyclient has this enabled.

Disabled
manual_lifetime

Manually manage profiler lifetime. Enable if your libtracyclient has this enabled.

Disabled

Use -f <flag> to enable a flag, or -f -<flag> to disable that flag. More info

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

  • No Candidates
Versions [RSS] 0.1.0.0, 0.1.1.0 (info)
Change log CHANGELOG.md
Dependencies base (>=4.16 && <5), bytestring, text (>=2.0 && <3), unliftio-core, webcolor-labels [details]
License BSD-3-Clause
Copyright 2025 IC Rainbow
Author IC Rainbow
Maintainer aenor.realm@gmail.com
Category Profiling
Home page https://github.com/haskell-game/tracy-profiler#readme
Bug tracker https://github.com/haskell-game/tracy-profiler/issues
Source repo head: git clone https://github.com/haskell-game/tracy-profiler
Uploaded by AlexanderBondarenko at 2025-10-30T22:20:47Z
Distributions
Downloads 4 total (4 in the last 30 days)
Rating (no votes yet) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for tracy-profiler-0.1.1.0

[back to package description]

tracy-profiler

Haskell bindings for Tracy frame profiler.

Setup

Installing

You can install the prebuilt package from your distribution if it has one:

sudo apt install libtracy-dev tracy-capture

Or you can download and build one yourself and point your project to it:

extra-lib-dirs:
- upstream/tracy/build
extra-include-dirs:
- upstream/tracy/public/tracy

This way you can customize configuration. Make sure you update package flags to match.

Either way, you have to ensure that tracy-capture is built with the same version. Otherwise it will connect and immediately refuse to record anything.

Flags

The flags must match whatever the library has been built with.

By default all the instrumentation wrappers do nothing. That means you don't have to ifdef your code to remove the wrappers when they're not needed.

You have to set the enable flag in your project for the data to be collected.

flags:
  tracy-profiler:
    enable: true
    # manual_lifetime: false
    # fibers: false

Instrumentation

Use the functions from System.Tracy and System.Tracy.Zone to collect data:

{-# LANGUAGE CPP #-}               -- __LINE__ and __FILE__ macros
{-# LANGUAGE MagicHash #-}         -- "static strings"#
{-# LANGUAGE OverloadedLabels #-}  -- #fuchsia colors
{-# LANGUAGE OverloadedStrings #-} -- "yes"

module Main where

import qualified System.Tracy as Tracy
import qualified Data.Text as Text

main :: IO ()
main = Tracy.withProfiler $ do
  Tracy.waitConnected_       -- wait for the tracy-capture to connect
  Tracy.messageL "hi there"# -- static strings require no copying to be logged
  mapM_ runFrame [0..600]

runFrame :: Int -> IO ()
runFrame ix = Tracy.withSrcLoc_ __LINE__ __FILE__ "runFrame" #fcc do
  Tracy.frameMark_
  let factorial = product [1 .. toInteger ix]
  let !digits = length (show factorial)
  Tracy.message . Text.pack $
    -- runtime strings will require some memcpy'ng around, use sparingly on hot paths
    "!" <> show ix <> " has " <> show digits <> " digits"
  Tracy.plotInt "digits"# digits

Collecting and viewing

Start tracy-capture before running the test to avoid empty areas where nothing happens:

tracy-capture -fo output.tracy &

Run the code, then upload the collected data to the viewer.

You'll see something like this:

screenshot

Are those are GC pauses we're looking at? 🤔

RTFM

You really should go read the official manual.

Yes, BEFORE you run into corrupted memory, surprising grouppings, or otherwise botched profiling runs.