{"id":19112131,"url":"https://github.com/ocaml-multicore/eio-trace","last_synced_at":"2025-04-30T22:06:25.130Z","repository":{"id":217295769,"uuid":"730144862","full_name":"ocaml-multicore/eio-trace","owner":"ocaml-multicore","description":"Trace visualisation tool for Eio programs","archived":false,"fork":false,"pushed_at":"2024-11-30T10:11:55.000Z","size":170,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-30T20:23:21.276Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ocaml-multicore.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":null,"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}},"created_at":"2023-12-11T09:54:16.000Z","updated_at":"2025-03-19T00:22:42.000Z","dependencies_parsed_at":"2024-02-04T14:27:35.612Z","dependency_job_id":"55cf03df-4abe-4e57-8da7-23265810f803","html_url":"https://github.com/ocaml-multicore/eio-trace","commit_stats":null,"previous_names":["ocaml-multicore/eio-trace"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-multicore%2Feio-trace","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-multicore%2Feio-trace/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-multicore%2Feio-trace/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-multicore%2Feio-trace/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ocaml-multicore","download_url":"https://codeload.github.com/ocaml-multicore/eio-trace/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249565250,"owners_count":21292427,"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":[],"created_at":"2024-11-09T04:31:41.654Z","updated_at":"2025-04-18T23:33:25.373Z","avatar_url":"https://github.com/ocaml-multicore.png","language":"OCaml","readme":"# eio-trace\n\neio-trace can be used to record and display traces of programs using the [Eio][] library\n(requires Eio 0.14 or later).\n\n## Installation\n\nTo install eio-trace:\n\n```\nopam install eio-trace\n```\n\n### macOS\n\nThese instructions will walk you through installing the system dependencies necessary in order to install eio-trace's dependencies from OPAM.\n\nThese instructions make use of [Homebrew](https://brew.sh/), adapt them to MacPorts, Fink, etc., if needed.\n\nFirst ensure everything is up-to-date:\n```sh\nbrew update\nbrew upgrade\nopam update\n```\n\nThen install the required packages:\n```sh\nbrew install bash cairo gtk+3 m4 pkg-config libffi\n```\n\nConsider restarting your terminal session at this stage.\n\nYou can now install eio-trace's dependencies.\n\nIf installing `conf-gtk3` fails with a `libffi` version error, run the following before trying again:\n```sh\nexport PKG_CONFIG_PATH=/usr/local/Cellar/libffi/3.4.4/lib/pkgconfig\n```\nUpdate the version number to match the currently installed version of libffi.\n\n## Tracing a program\n\nTo run an Eio program and display the trace:\n\n```\neio-trace run -- myprog ...\n```\n\nYou might like to start by tracing the example that comes with eio-trace:\n\n```\ndune build \u0026\u0026 eio-trace run -- ./_build/default/examples/net/main.exe\n```\n\n\u003cp align='center'\u003e\n  \u003cimg src=\"./doc/net.svg\"/\u003e\n\u003c/p\u003e\n\nScrolling with the mouse or touchpad will zoom in or out of the diagram.\n\nIf the program is still running when the window appears, you can press F5 to update to the latest events.\n\nTo record a trace:\n\n```\neio-trace record -f trace.fxt -- myprog ...\n```\n\nThis runs `myprog ...` with the `OCAML_RUNTIME_EVENTS_START` environment variable set, which causes it to record events to a ring buffer.\neio-trace saves these events to `trace.fxt`.\n\n\nThe trace can be viewed using generic tools such as [Perfetto][], but eio-trace's own visualisation is more useful,\nas it takes advantage of Eio's structured concurrency:\n\n```\neio-trace show trace.fxt\n```\n\nTo convert a trace to SVG format:\n\n```\neio-trace render trace.fxt\n```\n\nYou can also use `--format=png` for PNG output.\n\nTo calculate time spent in GC:\n\n```\neio-trace gc-stats trace.fxt\n\n./trace.fxt:                       \n\nRing   GC/s     App/s    Total/s   %GC\n  0    0.273    2.258    2.530    10.78\n  1    0.304    0.855    1.159    26.22\n  2    0.301    0.859    1.160    25.98\n  3    0.302    0.859    1.161    26.02\n  4    0.301    0.858    1.159    25.96\n  5    0.300    0.866    1.165    25.72\n  6    0.297    0.873    1.170    25.36\n\nAll    2.077    7.427    9.504    21.86\n\nNote: all times are wall-clock and so include time spent blocking.\n```\n\n## Reading traces\n\nEio fibers are shown as horizontal bars.\nGreen regions show when the fiber is running.\nLighter-green regions highlight particular operations.\nDark grey regions indicate that the fiber is suspended (allowing other fibers to run).\nOnly one fiber in a domain can be running at a time.\n\nWhen a new fiber is created, a vertical green line links the parent fiber to the child.\n\nCancellation contexts (including switches) are shown as brackets.\nSwitches can be named using `Switch.run ~name`. Unnamed switches are shown as \"switch\".\nA context being cancelled is indicated by a vertical red line.\n\nDomain-wide events, such as garbage collection and waiting for events,\nare shown as coloured regions behind all the fibers in the domain.\nGC periods are shown in shades of red when running, or yellow when waiting.\nYellow is also used when the domain is waiting for events outside of GC.\nWhen there are multiple domains, they are shown stacked vertically:\n\n\u003cp align='center'\u003e\n  \u003cimg src=\"./doc/gc.svg\"/\u003e\n\u003c/p\u003e\n\nIn the above trace, the upper domain performed GC while suspended\n(the red \"minor\" region in the top right, inside the \"suspend-domain\" region).\nThis is possible because each domain has a \"backup\" thread that handles GC while the domain is suspended.\n\nFor minor GCs:\n1. The domain initiating the GC enters a \"stw_leader\" (stop-the-world) phase and waits for the other domains to stop.\n2. One by one, the other domains stop and enter \"stw_api_barrier\" until all domains have stopped.\n3. All domains perform a minor GC, clearing their minor heaps.\n4. They then enter a \"minor_leave_barrier\" phase, waiting until all domains have finished.\n5. Each domain returns to running application code (including GC finalizers).\n\nPhases that usually involve sleeping are shown with a yellow background, but sometimes they do perform work\n(the trace events don't give us enough information to know in all cases).\n\n## Controls\n\n- Right click for a menu\n- F5 : reload the trace file\n- s : start-time (elapsed time at left edge of window since trace start)\n- d : duration (duration to show in the currently visible area of the window)\n\n`d` is useful for getting two windows to use the same scale, so that they can be compared easily.\n\n## Missed events\n\nIf eio-trace does not read a domain's ring buffer quickly enough then some events will be lost\nand you will see something like this:\n\n```\n+Warning: ring 0 lost 94001 events\n```\n\nThis will likely result in misleading traces.\nThere are several ways to fix this:\n\n- Use e.g. `eio-trace -F 1000` to make eio-trace read the ring more frequently.\n- Set e.g. `OCAMLRUNPARAM=e=20` to increase the size of the rings.\n- If events are being lost at startup, consider adding a short sleep to the start of your program\n  so that eio-trace has time to attach it it.\n\n## Limitations\n\n- OCaml 5.1 can [deadlock when tracing multiple domains](https://github.com/ocaml/ocaml/issues/12897). This was fixed in OCaml 5.2.\n- Events are reported per-domain, but not per-systhread.\n  Events generated in systhreads will get mixed up and cannot be shown correctly.\n  They will either appear attached to whatever fiber happens to be running, or shown as domain-level events.\n- The rendering is not optimised yet and may become quite slow on larger traces.\n\n## Real-world example\n\nThe [OCaml 5 Performance Problems][perf-blog] blog post shows many ways of examining the behaviour of an Eio program\nusing eio-trace and other tools.\n\n[Eio]: https://github.com/ocaml-multicore/eio\n[Perfetto]: https://ui.perfetto.dev/\n[perf-blog]: https://roscidus.com/blog/blog/2024/07/22/performance/\n","funding_links":[],"categories":["\u003ca name=\"OCaml\"\u003e\u003c/a\u003eOCaml"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Focaml-multicore%2Feio-trace","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Focaml-multicore%2Feio-trace","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Focaml-multicore%2Feio-trace/lists"}