{"id":13434327,"url":"https://github.com/janestreet/magic-trace","last_synced_at":"2025-05-13T19:14:00.567Z","repository":{"id":37474639,"uuid":"452433468","full_name":"janestreet/magic-trace","owner":"janestreet","description":"magic-trace collects and displays high-resolution traces of what a process is doing","archived":false,"fork":false,"pushed_at":"2025-04-13T23:24:56.000Z","size":36937,"stargazers_count":4897,"open_issues_count":48,"forks_count":103,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-04-27T20:03:12.759Z","etag":null,"topics":["intel","introspection","performance-tools","profile","tracing","visualizer","x86"],"latest_commit_sha":null,"homepage":"https://magic-trace.org","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/janestreet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-01-26T20:41:33.000Z","updated_at":"2025-04-27T03:13:07.000Z","dependencies_parsed_at":"2024-12-03T14:01:18.925Z","dependency_job_id":"60e962fe-4d33-41be-ac03-c07a426442bb","html_url":"https://github.com/janestreet/magic-trace","commit_stats":{"total_commits":307,"total_committers":19,"mean_commits":"16.157894736842106","dds":0.6449511400651466,"last_synced_commit":"48b61efe9bc3933815148599204544c1b2d7c769"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janestreet%2Fmagic-trace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janestreet%2Fmagic-trace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janestreet%2Fmagic-trace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janestreet%2Fmagic-trace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janestreet","download_url":"https://codeload.github.com/janestreet/magic-trace/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010813,"owners_count":21998995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["intel","introspection","performance-tools","profile","tracing","visualizer","x86"],"created_at":"2024-07-31T02:01:53.370Z","updated_at":"2025-05-13T19:14:00.547Z","avatar_url":"https://github.com/janestreet.png","language":"OCaml","readme":"\u003ch1 align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/assets/logo-dark.svg?sanitize=true\"\u003e\n    \u003cimg src=\"docs/assets/logo-light.svg?sanitize=true\" width=\"150px\"\u003e\n  \u003c/picture\u003e\n  \u003cbr\u003e\n  magic-trace\n\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/janestreet/magic-trace/actions?query=workflow%3Abuild\" alt=\"Linux Build Status\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/actions/workflow/status/janestreet/magic-trace/build.yml?branch=master\u0026logo=github\u0026style=flat-square\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/janestreet/magic-trace/releases/latest\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/tag/janestreet/magic-trace?label=version\u0026style=flat-square\"/\u003e\n  \u003c/a\u003e\n  \u003ca href=\"LICENSE.md\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/janestreet/magic-trace?style=flat-square\"/\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# Overview\n\nmagic-trace collects and displays high-resolution traces of what a process is doing. People have used it to:\n\n- figure out why an application running in production handles some requests slowly while simultaneously handling a sea of uninteresting requests,\n- look at what their code is *actually* doing instead of what they *think* it's doing,\n- get a history of what their application was doing before it crashed, instead of a mere stacktrace at that final instant,\n- ...and much more!\n\nmagic-trace:\n\n- has [2%-10% overhead](https://github.com/janestreet/magic-trace/wiki/Overhead),\n- doesn't require application changes to use,\n- traces *every function call* with ~40ns resolution, and\n- renders a timeline of call stacks going back (a configurable) ~10ms.\n\nYou use it like [`perf`](https://en.wikipedia.org/wiki/Perf_(Linux)): point it to a process and off it goes. The key difference from `perf` is that instead of sampling call stacks throughout time, magic-trace uses [Intel Processor Trace](https://man7.org/linux/man-pages/man1/perf-intel-pt.1.html) to snapshot a ring buffer of *all control flow* leading up to a chosen point in time[^1]. Then, you can explore an interactive timeline of what happened.\n\nYou can point magic-trace at a function such that when your application calls it, magic-trace takes a snapshot. Alternatively, attach it to a running process and detach it with \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eC\u003c/kbd\u003e, to see a trace of an arbitrary point in your program.\n\n[^1]: `perf` can do this too, but that's not how most people use it. In fact, if you peek under the hood you'll see that magic-trace uses `perf` to drive Intel PT.\n\n# Testimonials\n\n\u003e \"Magic-trace is one of the simplest command-line debugging tools I have ever used.\"\n- Francis Ricci, Jane Street\n\n\u003e \"Magic-trace is not just for performance. The tool gives insight directly into what happens in your program, when, and why. Consider using it for all your introspective goals!\"\n- Andrew Hunter, Jane Street\n\n\u003e I use perf a ton, and I think that both perf and magic-trace give perspectives that the other doesn't. The benefit I got from magic-trace was entirely based on the fact that it works in slices at any zoom level, so I was able to see all the function calls that a 70ns function was performing, which was invisible in perf.\n- Doug Patti, Jane Street\n\n[more testimonials...](https://github.com/janestreet/magic-trace/wiki/Unsolicited-reviews)\n\n# Install\n\n1. Make sure the system you want to trace is [supported](https://github.com/janestreet/magic-trace/wiki/Supported-platforms,-programming-languages,-and-runtimes). The constraints that most commonly trip people up are: VMs are mostly not supported, Intel only (Skylake[^3] or later), Linux only.\n\n2. Grab a release binary from the [latest release page](https://github.com/janestreet/magic-trace/releases/latest).\n\n   1. If downloading the prebuilt binary (not package), `chmod +x magic-trace`[^4]\n   1. If downloading the package, run `sudo dpkg -i magic-trace*.deb`\n\n   Then, test it by running `magic-trace -help`, which should bring up some help text.\n\n[^3]: Strictly speaking, anything newer than Broadwell, but this is not a platform we regularly test on, and timing resolution is worse (~1us).\n[^4]: https://github.com/actions/upload-artifact/issues/38\n\n# Getting started\n\n1. [Here](https://raw.githubusercontent.com/janestreet/magic-trace/master/demo/demo.c)'s a sample C program to try out. It's a slightly modified version of the example in `man 3 dlopen`. Download that, build it with `gcc demo.c -ldl -o demo`, then leave it running `./demo`. We're going to use that program to learn how `dlopen` works.\n\n2. Run `magic-trace attach -pid $(pidof demo)`. When you see the message that it's successfully attached, wait a couple seconds and \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eC\u003c/kbd\u003e `magic-trace`. It will output a file called `trace.fxt.gz` in your working directory.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/stage-1.gif\"\u003e\n\u003c/p\u003e\n\n3. Open [magic-trace.org](https://magic-trace.org/), click _\"Open trace file\"_ in the top-left-hand and give it the trace file generated in the previous step.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/stage-2.gif\"\u003e\n\u003c/p\u003e\n\n4. That should have expanded into a trace. Zoom in until you can see an individual loop through `dlopen`/`dlsym`/`cos`/`printf`/`dlclose`.\n    - \u003ckbd\u003eW\u003c/kbd\u003e zooms into wherever your mouse cursor is pointed (you'll need to zoom in a bunch to see anything useful),\n    - \u003ckbd\u003eS\u003c/kbd\u003e zooms out,\n    - \u003ckbd\u003eA\u003c/kbd\u003e moves left,\n    - \u003ckbd\u003eD\u003c/kbd\u003e moves right, and\n    - scroll wheel moves your viewport up and down the stack. You'll only need to scroll to see particularly deep stack traces, it's probably not useful for this example.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/stage-3.gif\"\u003e\n\u003c/p\u003e\n\n5. Click and drag on the white space around the call stacks to measure. Plant flags by clicking in the timeline along the top. Using the measurement tool, measure how long it takes to run `cos`. On my screen it takes ~5.7us.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/assets/stage-4.gif\"\u003e\n\u003c/p\u003e\n\nCongratulations, you just magically traced your first program!\n\nIn contrast to traditional `perf` workflows, magic-trace excels at hypothesis generation. For example, you might notice that taking 6us to run `cos` is a really long time! If you zoom in even more, you'll see that there's actually five pink \"\\[untraced\\]\" cells in there. If you re-run magic-trace with root and pass it `-trace-include-kernel`, you'll see stacktraces for those. They're page fault handlers! The demo program actually calls `cos` twice. If you zoom in even more near the end of the 6us `cos` call, you'll see that the second call takes *far* less time and does not page fault.\n\n# How to use it\n\nmagic-trace continuously records control flow into a ring buffer. Upon some sort of trigger, it takes a snapshot of that buffer and reconstructs call stacks.\n\nThere are two ways to take a snapshot:\n\nWe just did this one: \u003ckbd\u003eCtrl\u003c/kbd\u003e+\u003ckbd\u003eC\u003c/kbd\u003e magic-trace. If magic-trace terminates without already having taken a snapshot, it takes a snapshot of the end of the program.\n\nYou can also trigger snapshots when the application calls a function. To do so, pass magic-trace\nthe `-trigger` flag.\n\n- `-trigger '?'` brings up a fuzzy-finding selector that lets you choose from all\n  symbols in your executable,\n- `-trigger SYMBOL` selects a specific, fully mangled, symbol you know ahead of time, and\n- `-trigger .` selects the default symbol `magic_trace_stop_indicator`.\n\nStop indicators are powerful. Here are some ideas for where you might want to place one:\n\n- If you're using an asynchronous runtime, any time a scheduler cycle takes too long.\n- In a server, when a request takes a surprisingly long time.\n- After the garbage collector runs, to see what it's doing and what it interrupted.\n- After a compiler pass has completed.\n\nYou may leave the stop indicator in production code. It doesn't need to do anything in particular, magic-trace just needs the name. It is just an empty, but not inlined, function. It will cost ~10us to call, but *only when magic-trace actually uses it to take a snapshot*.\n\n# Documentation\n\nMore documentation is available on [the magic-trace wiki](https://github.com/janestreet/magic-trace/wiki).\n\n# Discussion\n\nJoin us [on Discord](https://discord.gg/vkzPYeZ292) to chat synchronously, or the [GitHub discussion group](https://github.com/janestreet/magic-trace/discussions) to do so asynchronously.\n\n# Contributing\n\nIf you'd like to contribute:\n\n1. [read the build instructions](https://github.com/janestreet/magic-trace/wiki/Build-instructions),\n1. [set up your editor](https://ocaml.org/learn/tutorials/up_and_running.html#Editor-support-for-OCaml),\n1. [take a quick tour through the codebase](https://github.com/janestreet/magic-trace/wiki/A-quick-tour-of-the-codebase), then\n1. [hit up the issue tracker](https://github.com/janestreet/magic-trace/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) for a good starter project.\n\n# Privacy policy\n\nmagic-trace does not send your code or derivatives of your code (including traces) anywhere.\n\n[magic-trace.org](https://magic-trace.org) is a [lightly modified fork of Perfetto](https://github.com/janestreet/magic-trace/wiki/About-the-UI), and runs entirely in your browser. As far as we can tell, it does not send your trace anywhere. If you're worried about that changing one day, [set up your own local copy of the Perfetto UI](https://github.com/janestreet/magic-trace/wiki/Setting-up-a-local-copy-of-the-UI) and use that instead.\n\n# Acknowledgements\n\n[Tristan Hume](https://github.com/trishume) is the original author of magic-trace. He wrote it while working at [Jane Street](https://www.janestreet.com/join-jane-street/), who currently maintains it.\n\nIntel PT is the foundational technology upon which magic-trace rests. We'd like to thank the people at Intel for their years-long efforts to make it available, despite its slow uptake in the greater software community.\n\nmagic-trace would not be possible without `perf`s extensive support for Intel PT. `perf` does most of the work in interpreting Intel PT's output, and magic-trace likely wouldn't exist were it not for their efforts. Thank you, `perf` developers.\n\n[magic-trace.org](https://magic-trace.org) is a fork of [Perfetto](https://github.com/janestreet/magic-trace/wiki/About-the-UI), with minor modifications. We'd like to thank the people at Google responsible for it. It's a high quality codebase that solves a hard problem well.\n\nThe ideas behind magic-trace are in no way unique. We've written down a list of [prior art](https://github.com/janestreet/magic-trace/wiki/Prior-art) that has influenced its design.\n","funding_links":[],"categories":["OCaml","Ocaml","Profiling","Linux","Terminal","magic-trace","Operating Systems","General utilites"],"sub_categories":["Performance","Smart Shell","Example","Browsers Addons"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanestreet%2Fmagic-trace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanestreet%2Fmagic-trace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanestreet%2Fmagic-trace/lists"}