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

Added Trace for the mapping connections, to allow JS profiling. #4766

Merged
merged 4 commits into from
Jun 6, 2022

Conversation

JoergAtGithub
Copy link
Member

This PR adds a Trace statement for each connection
It's grouped by control name - not by group+name - to keep the number of entries limited. I expected that the controls show the same performance for all groups/channels.

How to test:
mixxx --developer
Menu -> Developer -> Developer Tools
grafik

Under Stats you should see two lines per JS control connection to your mapping - as for any other trace.

PS: You might notice the huge times in my screenshot - this is a correct measurement, caused by inefficient JavaScript code in common-hid-packet-parser.js (HIDController.prototype.getOutputField)

Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

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

This will allocate a new string on each CO callback call, which is inefficient on its own. Moreover, you can already profile javascript in 2.4 via Qt's built-in console api (console.profile). https://doc.qt.io/qtcreator/creator-qml-performance-monitor.html

@JoergAtGithub
Copy link
Member Author

The console.profile command requires an external attached profiler tool. AFAIK, this is only supported by the QML engine, not by QJSEngine used for controller mappings. But even than, it would require a lot more skills from mapping developers, than the build in Stats window, which just needs Mixxx to be called in developer mode.

@Swiftb0y
Copy link
Member

AFAIK, this is only supported by the QML engine, not by QJSEngine used for controller mappings.

I'm not sure either, but if its only part of the QMLEngine and not QJSEngine, why would they make it part of the API offered by the QJSEngine? There are other QML-only APIs.

But even than, it would require a lot more skills from mapping developers, than the build in Stats window.

The majority of mapping developers won't have to concern themselves with optimizing their mappings. Optimizing Javascript is a very tricky task in itself because of the nature of the language and runtime. Simply providing a counter is likely not adequate. You only count the CO that is called which could be hooked up to many different callbacks, so you don't know which callback is actually the problem.

Besides, the current implementation will very likely cause major performance penalties in a hot path of the code. So unless you can minimize that, I don't want to merge this.

Comment on lines 7 to 9
std::unique_ptr<Trace> pCallCallbackTrace;
pCallCallbackTrace = std::make_unique<Trace>(
QString("JS " + key.item + " callback").toStdString().c_str());
Copy link
Member

Choose a reason for hiding this comment

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

why the unique_ptr? The trace object is not passed around, it could easily be allocated on the stack.
The creation of the QString also involves a heap allocation (likely since the string is likely quite long). toStdString might involves a heap allocation or at least a copy.

Copy link
Member

Choose a reason for hiding this comment

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

The trace Object id designed to live on the stack and will have almost zero overhead in normal mode.
You must not use QString here, because is also allocates memory in non developer mode.

This is the correct usage for minimum over-head at non developer mode:

Trace trace("SoundDeviceNetwork::callbackProcessClkRef %1",

To speed up the debug case as well, you may consider to introduce a char16_t* overload of Trace and pass the string as u" "
Or even better a template taking char16_t[] to make use of sizeoff() instead of parsing for "/0"

Comment on lines 7 to 9
std::unique_ptr<Trace> pCallCallbackTrace;
pCallCallbackTrace = std::make_unique<Trace>(
QString("JS " + key.item + " callback").toStdString().c_str());
Copy link
Member

Choose a reason for hiding this comment

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

The trace Object id designed to live on the stack and will have almost zero overhead in normal mode.
You must not use QString here, because is also allocates memory in non developer mode.

This is the correct usage for minimum over-head at non developer mode:

Trace trace("SoundDeviceNetwork::callbackProcessClkRef %1",

To speed up the debug case as well, you may consider to introduce a char16_t* overload of Trace and pass the string as u" "
Or even better a template taking char16_t[] to make use of sizeoff() instead of parsing for "/0"

@JoergAtGithub
Copy link
Member Author

To speed up the debug case as well, you may consider to introduce a char16_t* overload of Trace and pass the string as u" "
Or even better a template taking char16_t[] to make use of sizeoff() instead of parsing for "/0"

To use char16_t* requires to use https://doc.qt.io/qt-5/qstring.html#fromUtf16-1 where the documentation says: "This function is slow compared to the other Unicode conversions."

@Swiftb0y
Copy link
Member

Thanks the current solution eliminates my efficiency concerns, but I'm still not convinced that this is particularly useful. Optimizing a function when you only know its total runtime is usually just stumbling around in the dark. You need a more detailed trace of the contained functions as well which is usually collected by a profiler (such as the ones included its Qt's debugging tools).

@Swiftb0y
Copy link
Member

Swiftb0y commented May 26, 2022

AFAIK, this is only supported by the QML engine, not by QJSEngine used for controller mappings.

Did a little bit of research, this is only implicitly the case. See: https://bugreports.qt.io/browse/QTBUG-65419

I would consider merging this as a stopgap solution, though my primary concern still is, that constructing the tag based on the CO key does not really help when trying to find what callback exactly is making problems.

Copy link
Member

@daschuer daschuer left a comment

Choose a reason for hiding this comment

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

LGTM
@Swiftb0y merge?

@Swiftb0y
Copy link
Member

Swiftb0y commented Jun 2, 2022

Sure...

@daschuer daschuer merged commit 3d915de into mixxxdj:main Jun 6, 2022
@JoergAtGithub JoergAtGithub deleted the TraceJavascriptConnection branch June 6, 2022 07:02
@daschuer daschuer added this to the 2.4.0 milestone Jun 21, 2022
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.

3 participants