Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for Tracy profiler #1153

Open
wants to merge 31 commits into
base: master
Choose a base branch
from

Conversation

dazKind
Copy link
Contributor

@dazKind dazKind commented Sep 8, 2024

Problem Statement

As a Haxe developer I want to be able to reliably profile the performance of my engine & hxcpp apps in a ergonomic, lightweight and battletested manner.

I have looked at HxTelemetry and HxScout and found them lacking in usability and support. The app is constantly crashing for me, like 10 years old and not officially opensource? Also I question the use of the AMF protocol these days.

Solution

This PR adds support for Tracy Profiler

Tracy is a real time, nanosecond resolution, remote telemetry, hybrid frame and sampling profiler for games and other applications.

Anyway, we looked around and we found the Tracy Profiler which seems to satisfy my need perfectly. While I'm happy to run & maintain my own fork for my engine, I think this is something the whole community can benefit from, this is why I'm opening a PR for review & discussion.

Personally this has already helped me in several projects exposing bugs and optimizing a heavily threaded hxcpp app.

image

How to use

To activate the tracy integration, compile your app with:

-D HXCPP_TRACY
-D HXCPP_TELEMETRY
-D HXCPP_STACK_TRACE
-D HXCPP_STACK_LINE

and use the following call at the very end of your mainloop, so it gets called every frame:

cpp.vm.tracy.TracyProfiler.frameMark();

Note: See HaxeFoundation/haxe#11772 or copy that file containing the functions into your project

Then start either Tracy's UI-App or cmdline server listening on localhost and start your hxcpp-made binary.

Some notes about the integration

Haxe-Code

We integrate Tracy into hxcpp as a Telemetry option which utilizes hx::StackPosition and offer a set of static functions to set zones and other tracy functionality. Through this all your haxe-code will be captured in a profiler-session.

There are however native parts of hxcpp that wont be visible by default in Tracy (bc there are no ZoneScopes).

Note: Exceptions are in a few spots in the GC-Code, so GC becomes visible for us.

Note: Hxcpp's native calls will become visible if you use the option to capture callstacks.

Note: We capture source-locations and their filepaths. By default these are relative to your project and thus the sourcecode preview / browsing in Tracy wont work since it expects absolute paths. To solve this you can use -D absolute-path in your builds.

externs

The same is true about externs you might be using in your project. If you want to make these visible, you need to @:include('hx/TelemetryTracy.h') and you gain access to Tracy's C-Macros that you can use in your extern's c/cpp-code. Please refer to the official Tracy documentation: https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf

externs with static/dynamic libs

Another special case are static or dynamic libs your externs might be using. For these you will have to make more changes that are beyond the scope of this doc here, please refer to Tracy's official documentation over here: https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf

Optional Features

Memory Profiling

The following define adds tracking (de-)allocations of hxcpp's small & large object heap.

-D HXCPP_TRACY_MEMORY

Capture Callstacks

By default we only track zones. If you wanna inspect the actual callstack per zone, you should use the following define:

-D HXCPP_TRACY_INCLUDE_CALLSTACKS

Note: This will inflate the telemetry data A LOT and cost more performance. Please be aware.

On Demand Profiling

By default this integration will start sampling & collecting telemetry with the start of your application. You can change this behavior by the following define and your app will only generate telemetry if the Tracy Profiler app is open and reachable.

-D HXCPP_TRACY_ON_DEMAND

Short-lived Application Support

In cases where you dont have a mainloop or a very short-lived application you can use the following define to let your application stay around to complete sending telemetry data it has collected.

-D HXCPP_TRACY_NO_EXIT

Questions relevant for hxcpp & this PR

dazKind and others added 2 commits September 8, 2024 12:36
* add tracy client

* add Aidan's StackContext Zone

* a bit more documentation

* doc cleanup

* add HXCPP_TRACY_DISABLE_STACKS flag
@dazKind
Copy link
Contributor Author

dazKind commented Sep 8, 2024

Ok, seems like 1426a88 fixes the pipelines. That also means that the tracy include has sideeffects for mysql on macos. Interesting.

@Aidan63
Copy link
Contributor

Aidan63 commented Sep 8, 2024

The tracy source files should be moved to project/thirdparty as thats where all the other vendored libraries live. Would also be good to not need the hxcpp.h manually added to TracyClient.cpp to ease updating later on.

Now that we've got a better idea of what we need to do I wonder if a better approach is to make a tracy implementation of the hxcpp telemetry api. I.e. Have a TracyTelemetry.cpp which implements all the tlm and __hxcpp_hxt prefixed functions. tlmSampleEnter, for example, is called whenever a new stack frame is created so that can be used to issue a tracy call.
Many of those functions may just be no-ops for now, but the allocation ones will be useful once I've figured out allocation tracking.

Also wonder if we can do something similar for the hxcpp profiler api, might be able to provide a tracy implementation of that for custom zones, advantage being cpp.Profiler is already in the std library.

@Aidan63
Copy link
Contributor

Aidan63 commented Sep 8, 2024

Another plus of a dedicated TracyTelemetry.cpp file is then only that needs to include tracy headers, so we dodge that mac sql issue you mentioned entirely.

@dazKind
Copy link
Contributor Author

dazKind commented Sep 8, 2024

Ok, we updated the setup.

  • Sources have been moved to project/thirdparty
  • little tweaks to the build.xmls
  • things are refactored into TracyTelemetry.cpp and useful tracy functions are exposed as globals now.

Updating the description&docs here now.

There are few more things left to be done concerning memory, but we are discovering more and more cool things that this integration allows, e.g. like source-preview:
image

@dazKind
Copy link
Contributor Author

dazKind commented Sep 14, 2024

Ok, things have settled and we can move out of draft now.

Major kudos for @Aidan63 who was instrumental in making this a reality and taking it way beyond the initial scope in a relatively short amount of time!

predator-handshake

Working on this has been a blast!

@dazKind dazKind marked this pull request as ready for review September 14, 2024 21:52
@BNTFryingPan
Copy link

i used hxscout once forever ago and had a hard time figuring it out, so this looks like it would be a big improvement

@Vortex2Oblivion
Copy link

The hxscout killer?

@skial skial mentioned this pull request Sep 17, 2024
1 task
Copy link

@EliteMasterEric EliteMasterEric left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested this with Funkin' and it worked brilliantly with minimal setup.

Note: This works on Haxe 4.3.6 also, as long as the cpp.vm.tracy.TraceyProfiler class from the linked project is included somewhere in the workspace (you don't need to use a fork of Haxe).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants