Voted for it too. Thanks @sudara for opening this interesting discussion.
Actually it got me interested into macOS’s Signposts
Really simple API, quite low overhead and very helpful. Building on @dave96’s class I came up with this simple wrapper, if anybody is interested:
#ifdef __APPLE__
#include <os/log.h>
#include <os/signpost.h>
struct Signpost {
Signpost() : log_(os_log_create("com.company.myApp", OS_LOG_CATEGORY_POINTS_OF_INTEREST)) {}
static os_log_t& getInstance() {
static Signpost signpost;
return signpost.log_;
}
private:
os_log_t log_;
};
#define SIGNPOST_BEGIN(name, ...) \
os_signpost_id_t _signpost_interval_id = os_signpost_id_generate(Signpost::getInstance()); \
os_signpost_emit_with_type(Signpost::getInstance(), OS_SIGNPOST_INTERVAL_BEGIN, \
_signpost_interval_id, name, __VA_ARGS__)
#define SIGNPOST_END(name, ...) \
os_signpost_emit_with_type(Signpost::getInstance(), OS_SIGNPOST_INTERVAL_END, \
_signpost_interval_id, name, __VA_ARGS__)
#define SIGNPOST_EVENT(name, ...) \
os_signpost_emit_with_type(Signpost::getInstance(), OS_SIGNPOST_EVENT, OS_SIGNPOST_ID_EXCLUSIVE, \
name, __VA_ARGS__)
#else
#define SIGNPOST_BEGIN(...) ;
#define SIGNPOST_END(...) ;
#define SIGNPOST_EVENT(...) ;
#endif
Caveat: with the new (post-10.14) “named” signpost API I don’t think you can go RAII like @dave96, because the strings attached to the events must be litterals.
Then to e.g. profile all paint calls it’s a matter of temporarily modifying juce_Component.cpp
:
diff --git a/modules/juce_gui_basics/components/juce_Component.cpp b/modules/juce_gui_basics/components/juce_Component.cpp
index 9f8d9d742..5063604aa 100644
--- a/modules/juce_gui_basics/components/juce_Component.cpp
+++ b/modules/juce_gui_basics/components/juce_Component.cpp
@@ -23,6 +23,21 @@
==============================================================================
*/
+#include <cxxabi.h>
+
+std::string demangle(const char* name) {
+
+ int status = -1;
+ std::unique_ptr<char, void(*)(void*)> res {
+ abi::__cxa_demangle(name, nullptr, nullptr, &status),
+ std::free
+ };
+
+ return (status==0) ? res.get() : name ;
+}
+
namespace juce
{
@@ -1996,6 +2011,7 @@ void Component::paintWithinParentContext (Graphics& g)
void Component::paintComponentAndChildren (Graphics& g)
{
+ SIGNPOST_BEGIN("paint", "%s", demangle(typeid(*this).name()).c_str());
auto clipBounds = g.getClipBounds();
if (flags.dontClipGraphicsFlag && getNumChildComponents() == 0)
@@ -2057,6 +2073,7 @@ void Component::paintComponentAndChildren (Graphics& g)
Graphics::ScopedSaveState ss (g);
paintOverChildren (g);
+ SIGNPOST_END("paint");
}
void Component::paintEntireComponent (Graphics& g, bool ignoreAlphaLevel)
… which gets me this beautiful waterfall on my app 
@sudara hope we get a more permanent way of profiling Component
!