Overte C++ Documentation
Profile.h
1 //
2 // Created by Ryan Huffman on 2016-12-14
3 // Copyright 2013-2016 High Fidelity, Inc.
4 // Copyright 2023 Overte e.V.
5 //
6 // Distributed under the Apache License, Version 2.0.
7 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
8 // SPDX-License-Identifier: Apache-2.0
9 //
10 #pragma once
11 
12 #ifndef HIFI_PROFILE_
13 #define HIFI_PROFILE_
14 
15 #include "Trace.h"
16 #include "SharedUtil.h"
17 
18 // When profiling something that may happen many times per frame, use a xxx_detail category so that they may easily be filtered out of trace results
19 Q_DECLARE_LOGGING_CATEGORY(trace_app)
20 Q_DECLARE_LOGGING_CATEGORY(trace_app_detail)
21 Q_DECLARE_LOGGING_CATEGORY(trace_metadata)
22 Q_DECLARE_LOGGING_CATEGORY(trace_network)
23 Q_DECLARE_LOGGING_CATEGORY(trace_picks)
24 Q_DECLARE_LOGGING_CATEGORY(trace_render)
25 Q_DECLARE_LOGGING_CATEGORY(trace_render_detail)
26 Q_DECLARE_LOGGING_CATEGORY(trace_render_gpu)
27 Q_DECLARE_LOGGING_CATEGORY(trace_resource)
28 Q_DECLARE_LOGGING_CATEGORY(trace_resource_parse)
29 Q_DECLARE_LOGGING_CATEGORY(trace_resource_network)
30 Q_DECLARE_LOGGING_CATEGORY(trace_script)
31 Q_DECLARE_LOGGING_CATEGORY(trace_script_entities)
32 Q_DECLARE_LOGGING_CATEGORY(trace_simulation)
33 Q_DECLARE_LOGGING_CATEGORY(trace_simulation_detail)
34 Q_DECLARE_LOGGING_CATEGORY(trace_simulation_animation)
35 Q_DECLARE_LOGGING_CATEGORY(trace_simulation_animation_detail)
36 Q_DECLARE_LOGGING_CATEGORY(trace_simulation_physics)
37 Q_DECLARE_LOGGING_CATEGORY(trace_simulation_physics_detail)
38 Q_DECLARE_LOGGING_CATEGORY(trace_startup)
39 Q_DECLARE_LOGGING_CATEGORY(trace_workload)
40 Q_DECLARE_LOGGING_CATEGORY(trace_baker)
41 
42 class ProfileDurationBase {
43 
44 protected:
45  ProfileDurationBase(const QLoggingCategory& category, const QString& name);
46  const QString _name;
47  const QLoggingCategory& _category;
48 };
49 
50 class ProfileDuration : public ProfileDurationBase {
51 public:
52  ProfileDuration(const QLoggingCategory& category, const QString& name, uint32_t argbColor = 0xff0000ff, uint64_t payload = 0, const QVariantMap& args = QVariantMap());
53  ~ProfileDuration();
54 
55  static uint64_t beginRange(const QLoggingCategory& category, const char* name, uint32_t argbColor);
56  static void endRange(const QLoggingCategory& category, uint64_t rangeId);
57 };
58 
59 class ConditionalProfileDuration : public ProfileDurationBase {
60 public:
61  ConditionalProfileDuration(const QLoggingCategory& category, const QString& name, uint32_t minTime);
62  ~ConditionalProfileDuration();
63 
64 private:
65  const int64_t _startTime;
66  const int64_t _minTime;
67 };
68 
69 
70 inline void syncBegin(const QLoggingCategory& category, const QString& name, const QString& id, const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()) {
71  if (category.isDebugEnabled()) {
72  tracing::traceEvent(category, name, tracing::DurationBegin, id, args, extra);
73  }
74 }
75 
76 
77 inline void syncEnd(const QLoggingCategory& category, const QString& name, const QString& id, const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()) {
78  if (category.isDebugEnabled()) {
79  tracing::traceEvent(category, name, tracing::DurationEnd, id, args, extra);
80  }
81 }
82 
83 inline void asyncBegin(const QLoggingCategory& category, const QString& name, const QString& id, const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()) {
84  if (category.isDebugEnabled()) {
85  tracing::traceEvent(category, name, tracing::AsyncNestableStart, id, args, extra);
86  }
87 }
88 
89 
90 inline void asyncEnd(const QLoggingCategory& category, const QString& name, const QString& id, const QVariantMap& args = QVariantMap(), const QVariantMap& extra = QVariantMap()) {
91  if (category.isDebugEnabled()) {
92  tracing::traceEvent(category, name, tracing::AsyncNestableEnd, id, args, extra);
93  }
94 }
95 
96 inline void instant(const QLoggingCategory& category, const QString& name, const QString& scope = "t", const QVariantMap& args = QVariantMap(), QVariantMap extra = QVariantMap()) {
97  if (category.isDebugEnabled()) {
98  extra["s"] = scope;
99  tracing::traceEvent(category, name, tracing::Instant, "", args, extra);
100  }
101 }
102 
103 inline void counter(const QLoggingCategory& category, const QString& name, const QVariantMap& args, const QVariantMap& extra = QVariantMap()) {
104  if (category.isDebugEnabled()) {
105  tracing::traceEvent(category, name, tracing::Counter, "", args, extra);
106  }
107 }
108 
109 inline void metadata(const QString& metadataType, const QVariantMap& args) {
110  tracing::traceEvent(trace_metadata(), metadataType, tracing::Metadata, "", args);
111 }
112 
113 #define PROFILE_RANGE(category, name) ProfileDuration profileRangeThis(trace_##category(), name);
114 #define PROFILE_RANGE_IF_LONGER(category, name, ms) ConditionalProfileDuration profileRangeThis(trace_##category(), name, ms);
115 #define PROFILE_RANGE_EX(category, name, argbColor, payload, ...) ProfileDuration profileRangeThis(trace_##category(), name, argbColor, (uint64_t)payload, ##__VA_ARGS__);
116 #define PROFILE_RANGE_BEGIN(category, rangeId, name, argbColor) rangeId = ProfileDuration::beginRange(trace_##category(), name, argbColor)
117 #define PROFILE_RANGE_END(category, rangeId) ProfileDuration::endRange(trace_##category(), rangeId)
118 #define PROFILE_SYNC_BEGIN(category, name, id, ...) syncBegin(trace_##category(), name, id, ##__VA_ARGS__);
119 #define PROFILE_SYNC_END(category, name, id, ...) syncEnd(trace_##category(), name, id, ##__VA_ARGS__);
120 #define PROFILE_ASYNC_BEGIN(category, name, id, ...) asyncBegin(trace_##category(), name, id, ##__VA_ARGS__);
121 #define PROFILE_ASYNC_END(category, name, id, ...) asyncEnd(trace_##category(), name, id, ##__VA_ARGS__);
122 #define PROFILE_COUNTER_IF_CHANGED(category, name, type, value) { static type lastValue = 0; type newValue = value; if (newValue != lastValue) { counter(trace_##category(), name, { { name, newValue }}); lastValue = newValue; } }
123 #define PROFILE_COUNTER(category, name, ...) counter(trace_##category(), name, ##__VA_ARGS__);
124 #define PROFILE_INSTANT(category, name, ...) instant(trace_##category(), name, ##__VA_ARGS__);
125 #define PROFILE_SET_THREAD_NAME(threadName) metadata("thread_name", { { "name", threadName } });
126 
127 #define SAMPLE_PROFILE_RANGE(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_RANGE(category, name); }
128 #define SAMPLE_PROFILE_RANGE_EX(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_RANGE_EX(category, name, argbColor, payload, ##__VA_ARGS__); }
129 #define SAMPLE_PROFILE_COUNTER(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_COUNTER(category, name, ##__VA_ARGS__); }
130 #define SAMPLE_PROFILE_INSTANT(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_INSTANT(category, name, ##__VA_ARGS__); }
131 
132 // uncomment WANT_DETAILED_PROFILING definition to enable profiling in high-frequency contexts
133 //#define WANT_DETAILED_PROFILING
134 #ifdef WANT_DETAILED_PROFILING
135 #define DETAILED_PROFILE_RANGE(category, name) ProfileDuration profileRangeThis(trace_##category(), name);
136 #define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) ProfileDuration profileRangeThis(trace_##category(), name, argbColor, (uint64_t)payload, ##__VA_ARGS__);
137 #else // WANT_DETAILED_PROFILING
138 #define DETAILED_PROFILE_RANGE(category, name) ; // no-op
139 #define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) ; // no-op
140 #endif // WANT_DETAILED_PROFILING
141 
142 #endif