aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@qt.io>2023-10-14 15:56:03 +0200
committerTim Jenssen <tim.jenssen@qt.io>2023-10-17 11:55:03 +0000
commitad12bbb6698a6c00ed127f79a0078f52b1e7ce7d (patch)
tree10bc3ca87b822387a0763defa7f25824f75d043a /src
parent11bf705e26bec1db1f33304d2cdbd00559b91b9c (diff)
QmlDesigner: Add object trace
'N' and 'D' phases are not supported by Perfetto. So I mapped it to async events. This patch is improving the interface for arguments too. Now you can select the type for you arguments. So the name can be a string_view but the arguments can be a string. The variadic template arguments are used to prevent any conversion code which could not be optimized out for an empty function. Change-Id: I1ad1927b5e3b63607a21df1351b1f5cfba50159c Reviewed-by: Tim Jenssen <tim.jenssen@qt.io> Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Diffstat (limited to 'src')
-rw-r--r--src/libs/nanotrace/nanotracehr.cpp12
-rw-r--r--src/libs/nanotrace/nanotracehr.h385
-rw-r--r--src/plugins/qmldesigner/CMakeLists.txt13
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp11
-rw-r--r--src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h2
-rw-r--r--src/plugins/qmldesigner/designercore/include/imagecacheauxiliarydata.h2
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalnode_p.h4
-rw-r--r--src/plugins/qmldesigner/designercore/model/internalproperty.h6
-rw-r--r--src/plugins/qmldesigner/designercore/model/model.cpp5
-rw-r--r--src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp13
-rw-r--r--src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp45
-rw-r--r--src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h47
13 files changed, 472 insertions, 75 deletions
diff --git a/src/libs/nanotrace/nanotracehr.cpp b/src/libs/nanotrace/nanotracehr.cpp
index e8c9abd7747..d97aa889391 100644
--- a/src/libs/nanotrace/nanotracehr.cpp
+++ b/src/libs/nanotrace/nanotracehr.cpp
@@ -23,8 +23,8 @@ template<typename TraceEvent>
void printEvent(std::ostream &out, const TraceEvent &event, qint64 processId, std::thread::id threadId)
{
out << R"({"ph":")" << event.type << R"(","name":")" << event.name << R"(","cat":")"
- << event.category << R"(","ts":")"
- << static_cast<double>(event.time.time_since_epoch().count()) / 1000 << R"(","pid":)"
+ << event.category << R"(","ts":)"
+ << static_cast<double>(event.time.time_since_epoch().count()) / 1000 << R"(,"pid":)"
<< processId << R"(,"tid":)" << threadId;
if (event.type == 'X')
@@ -94,6 +94,10 @@ template NANOTRACE_EXPORT void flushEvents(const Utils::span<StringViewTraceEven
template NANOTRACE_EXPORT void flushEvents(const Utils::span<StringTraceEvent> events,
std::thread::id threadId,
EnabledEventQueue<StringTraceEvent> &eventQueue);
+template NANOTRACE_EXPORT void flushEvents(
+ const Utils::span<StringViewWithStringArgumentsTraceEvent> events,
+ std::thread::id threadId,
+ EnabledEventQueue<StringViewWithStringArgumentsTraceEvent> &eventQueue);
void openFile(EnabledTraceFile &file)
{
@@ -143,6 +147,8 @@ void flushInThread(EnabledEventQueue<TraceEvent> &eventQueue)
template NANOTRACE_EXPORT void flushInThread(EnabledEventQueue<StringViewTraceEvent> &eventQueue);
template NANOTRACE_EXPORT void flushInThread(EnabledEventQueue<StringTraceEvent> &eventQueue);
+template NANOTRACE_EXPORT void flushInThread(
+ EnabledEventQueue<StringViewWithStringArgumentsTraceEvent> &eventQueue);
namespace {
EnabledTraceFile globalTraceFile{"global.json"};
@@ -196,4 +202,6 @@ void EventQueue<TraceEvent, std::true_type>::flush()
template class EventQueue<StringViewTraceEvent, std::true_type>;
template class EventQueue<StringTraceEvent, std::true_type>;
+template class EventQueue<StringViewWithStringArgumentsTraceEvent, std::true_type>;
+
} // namespace NanotraceHR
diff --git a/src/libs/nanotrace/nanotracehr.h b/src/libs/nanotrace/nanotracehr.h
index d90f57b9e7f..cfe006cd6ba 100644
--- a/src/libs/nanotrace/nanotracehr.h
+++ b/src/libs/nanotrace/nanotracehr.h
@@ -5,9 +5,12 @@
#include "nanotraceglobals.h"
+#include <utils/smallstring.h>
#include <utils/span.h>
+#include <QByteArrayView>
#include <QMetaObject>
+#include <QStringView>
#include <array>
#include <atomic>
@@ -17,6 +20,7 @@
#include <mutex>
#include <string>
#include <string_view>
+#include <tuple>
namespace NanotraceHR {
using Clock = std::chrono::steady_clock;
@@ -36,6 +40,84 @@ constexpr bool isTracerActive()
#endif
}
+#if __cplusplus >= 202002L && __has_cpp_attribute(msvc::no_unique_address)
+# define NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
+#elif __cplusplus >= 202002L && __has_cpp_attribute(no_unique_address) >= 201803L
+# define NO_UNIQUE_ADDRESS [[no_unique_address]]
+#else
+# define NO_UNIQUE_ADDRESS
+#endif
+
+namespace Internal {
+inline std::string_view covertToString(std::string_view text)
+{
+ return text;
+}
+
+template<std::size_t size>
+inline std::string_view covertToString(const char (&text)[size])
+{
+ return text;
+}
+
+inline Utils::PathString covertToString(QStringView text)
+{
+ return text;
+}
+
+inline Utils::PathString covertToString(QByteArrayView text)
+{
+ return text;
+}
+
+inline Utils::SmallString covertToString(long long number)
+{
+ return Utils::SmallString::number(number);
+}
+
+inline Utils::SmallString covertToString(double number)
+{
+ return Utils::SmallString::number(number);
+}
+
+template<typename String, typename Argument>
+void toArgument(String &text, Argument &&argument)
+{
+ const auto &[key, value] = argument;
+ text.append(R"(")");
+ text.append(covertToString(key));
+ text.append(R"(":")");
+ text.append(covertToString(value));
+ text.append(R"(",)");
+}
+
+template<typename String, typename... Arguments>
+String toArguments(Arguments &&...arguments)
+{
+ if constexpr (isTracerActive()) {
+ String text;
+ constexpr auto argumentCount = sizeof...(Arguments);
+ text.reserve(sizeof...(Arguments) * 20);
+ text.append("{");
+ (toArgument(text, arguments), ...);
+ if (argumentCount)
+ text.pop_back();
+
+ text.append("}");
+
+ return text;
+ } else {
+ return {};
+ }
+}
+
+inline std::string_view toArguments(std::string_view arguments)
+{
+ return arguments;
+}
+
+} // namespace Internal
+
namespace Literals {
struct TracerLiteral
{
@@ -43,6 +125,8 @@ struct TracerLiteral
constexpr operator std::string_view() const { return text; }
+ operator std::string() const { return std::string{text}; }
+
private:
constexpr TracerLiteral(std::string_view text)
: text{text}
@@ -59,11 +143,12 @@ constexpr TracerLiteral operator""_t(const char *text, size_t size)
using namespace Literals;
-template<typename String>
+template<typename String, typename ArgumentsString>
struct TraceEvent
{
using StringType = String;
using ArgumentType = std::conditional_t<std::is_same_v<String, std::string_view>, TracerLiteral, String>;
+ using ArgumentsStringType = ArgumentsString;
TraceEvent() = default;
TraceEvent(const TraceEvent &) = delete;
@@ -74,15 +159,16 @@ struct TraceEvent
String name;
String category;
- String arguments;
+ ArgumentsString arguments;
TimePoint time;
Duration duration;
std::size_t id = 0;
char type = ' ';
};
-using StringViewTraceEvent = TraceEvent<std::string_view>;
-using StringTraceEvent = TraceEvent<std::string>;
+using StringViewTraceEvent = TraceEvent<std::string_view, std::string_view>;
+using StringViewWithStringArgumentsTraceEvent = TraceEvent<std::string_view, std::string>;
+using StringTraceEvent = TraceEvent<std::string, std::string>;
enum class IsEnabled { No, Yes };
@@ -102,11 +188,16 @@ extern template NANOTRACE_EXPORT void flushEvents(const Utils::span<StringViewTr
extern template NANOTRACE_EXPORT void flushEvents(const Utils::span<StringTraceEvent> events,
std::thread::id threadId,
EnabledEventQueue<StringTraceEvent> &eventQueue);
-
+extern template NANOTRACE_EXPORT void flushEvents(
+ const Utils::span<StringViewWithStringArgumentsTraceEvent> events,
+ std::thread::id threadId,
+ EnabledEventQueue<StringViewWithStringArgumentsTraceEvent> &eventQueue);
template<typename TraceEvent>
void flushInThread(EnabledEventQueue<TraceEvent> &eventQueue);
extern template NANOTRACE_EXPORT void flushInThread(EnabledEventQueue<StringViewTraceEvent> &eventQueue);
extern template NANOTRACE_EXPORT void flushInThread(EnabledEventQueue<StringTraceEvent> &eventQueue);
+extern template NANOTRACE_EXPORT void flushInThread(
+ EnabledEventQueue<StringViewWithStringArgumentsTraceEvent> &eventQueue);
template<bool enable>
class TraceFile;
@@ -188,6 +279,7 @@ public:
extern template class NANOTRACE_EXPORT EventQueue<StringViewTraceEvent, std::true_type>;
extern template class NANOTRACE_EXPORT EventQueue<StringTraceEvent, std::true_type>;
+extern template class NANOTRACE_EXPORT EventQueue<StringViewWithStringArgumentsTraceEvent, std::true_type>;
template<typename TraceEvent, std::size_t eventCount, typename Enabled>
class EventQueueData
@@ -259,69 +351,183 @@ TraceEvent &getTraceEvent(EnabledEventQueue<TraceEvent> &eventQueue)
return eventQueue.currentEvents[eventQueue.eventsIndex++];
}
-template<typename Category, bool enabled>
-class Token
+class BasicDisabledToken
{
public:
using IsActive = std::false_type;
- using ArgumentType = typename Category::ArgumentType;
- Token() {}
+ BasicDisabledToken() {}
- ~Token() {}
+ BasicDisabledToken(const BasicDisabledToken &) = default;
+ BasicDisabledToken &operator=(const BasicDisabledToken &) = default;
+ BasicDisabledToken(BasicDisabledToken &&other) noexcept = default;
+ BasicDisabledToken &operator=(BasicDisabledToken &&other) noexcept = default;
- constexpr Token(const Token &) = delete;
- constexpr Token &operator=(const Token &) = delete;
+ ~BasicDisabledToken() {}
- constexpr Token(Token &&other) noexcept = default;
+ constexpr explicit operator bool() const { return false; }
- constexpr Token &operator=(Token &&other) noexcept = default;
+ static constexpr bool isActive() { return false; }
+};
+
+class BasicEnabledToken
+{
+public:
+ using IsActive = std::true_type;
+
+ BasicEnabledToken() {}
+
+ BasicEnabledToken(const BasicEnabledToken &) = default;
+ BasicEnabledToken &operator=(const BasicEnabledToken &) = default;
+ BasicEnabledToken(BasicEnabledToken &&other) noexcept = default;
+ BasicEnabledToken &operator=(BasicEnabledToken &&other) noexcept = default;
+ ~BasicEnabledToken() {}
constexpr explicit operator bool() const { return false; }
static constexpr bool isActive() { return false; }
+};
+
+template<typename Category, bool enabled>
+class ObjectToken : public BasicDisabledToken
+{
+public:
+ using ArgumentType = typename Category::ArgumentType;
+
+ ObjectToken() = default;
+ ObjectToken(const ObjectToken &) = delete;
+ ObjectToken &operator=(const ObjectToken &) = delete;
+ ObjectToken(ObjectToken &&other) noexcept = default;
+ ObjectToken &operator=(ObjectToken &&other) noexcept = default;
+ ~ObjectToken() = default;
+
+ template<typename... Arguments>
+ void change(ArgumentType, Arguments &&...)
+ {}
+};
+
+template<typename Category>
+class ObjectToken<Category, true> : public BasicEnabledToken
+{
+ ObjectToken(std::string_view name, std::size_t id, Category &category)
+ : m_name{name}
+ , m_id{id}
+ , m_category{&category}
+ {}
+
+public:
+ using StringType = typename Category::StringType;
+ using ArgumentType = typename Category::ArgumentType;
+
+ friend Category;
+
+ ObjectToken() = default;
+
+ ObjectToken(const ObjectToken &other) = delete;
+
+ ObjectToken &operator=(const ObjectToken &other) = delete;
+
+ ObjectToken(ObjectToken &&other) noexcept
+ : m_name{std::move(other.m_name)}
+ , m_id{std::exchange(other.m_id, 0)}
+ , m_category{std::exchange(other.m_category, nullptr)}
+ {}
- Token begin(ArgumentType) { return Token{}; }
+ ObjectToken &operator=(ObjectToken &&other) noexcept
+ {
+ if (&other != this) {
+ m_name = std::move(other.m_name);
+ m_id = std::exchange(other.m_id, 0);
+ m_category = std::exchange(other.m_category, nullptr);
+ }
+
+ return *this;
+ }
+
+ ~ObjectToken()
+ {
+ if (m_id)
+ m_category->end('e', m_id, std::move(m_name));
- void tick(ArgumentType) {}
+ m_id = 0;
+ }
+
+ template<typename... Arguments>
+ void change(ArgumentType name, Arguments &&...arguments)
+ {
+ if (m_id)
+ m_category->tick('n', m_id, std::move(name), std::forward<Arguments>(arguments)...);
+ }
- void end() {}
+private:
+ StringType m_name;
+ std::size_t m_id = 0;
+ Category *m_category = nullptr;
+};
+
+template<typename Category, bool enabled>
+class AsynchronousToken : public BasicDisabledToken
+{
+public:
+ using ArgumentType = typename Category::ArgumentType;
+
+ AsynchronousToken() {}
+
+ AsynchronousToken(const AsynchronousToken &) = delete;
+ AsynchronousToken &operator=(const AsynchronousToken &) = delete;
+ AsynchronousToken(AsynchronousToken &&other) noexcept = default;
+ AsynchronousToken &operator=(AsynchronousToken &&other) noexcept = default;
+
+ ~AsynchronousToken() {}
+
+ template<typename... Arguments>
+ AsynchronousToken begin(ArgumentType, Arguments &&...)
+ {
+ return AsynchronousToken{};
+ }
+
+ template<typename... Arguments>
+ void tick(Arguments &&...)
+ {}
+
+ template<typename... Arguments>
+ void end(Arguments &&...)
+ {}
};
template<typename TraceEvent, bool enabled>
class Category;
template<typename Category>
-class Token<Category, true>
+class AsynchronousToken<Category, true> : public BasicEnabledToken
{
- Token(std::string_view name, std::size_t id, Category &category)
+ AsynchronousToken(std::string_view name, std::size_t id, Category &category)
: m_name{name}
, m_id{id}
, m_category{&category}
{}
public:
- using IsActive = std::true_type;
using StringType = typename Category::StringType;
using ArgumentType = typename Category::ArgumentType;
friend Category;
- Token() = default;
+ AsynchronousToken() = default;
- Token(const Token &) = delete;
- Token &operator=(const Token &) = delete;
+ AsynchronousToken(const AsynchronousToken &) = delete;
+ AsynchronousToken &operator=(const AsynchronousToken &) = delete;
- Token(Token &&other) noexcept
- : m_name{other.m_name}
+ AsynchronousToken(AsynchronousToken &&other) noexcept
+ : m_name{std::move(other.m_name)}
, m_id{std::exchange(other.m_id, 0)}
, m_category{std::exchange(other.m_category, nullptr)}
{}
- Token &operator=(Token &&other) noexcept
+ AsynchronousToken &operator=(AsynchronousToken &&other) noexcept
{
if (&other != this) {
- m_name = other.m_name;
+ m_name = std::move(other.m_name);
m_id = std::exchange(other.m_id, 0);
m_category = std::exchange(other.m_category, nullptr);
}
@@ -329,30 +535,29 @@ public:
return *this;
}
- ~Token() { end(); }
-
- constexpr explicit operator bool() const { return m_id; }
+ ~AsynchronousToken() { end(); }
- static constexpr bool isActive() { return true; }
-
- Token begin(ArgumentType name)
+ template<typename... Arguments>
+ AsynchronousToken begin(ArgumentType name, Arguments &&...arguments)
{
if (m_id)
- m_category->beginAsynchronous(m_id, name);
+ m_category->begin('b', m_id, std::move(name), std::forward<Arguments>(arguments)...);
- return Token{m_name, m_id, *m_category};
+ return AsynchronousToken{m_name, m_id, *m_category};
}
- void tick(ArgumentType name)
+ template<typename... Arguments>
+ void tick(ArgumentType name, Arguments &&...arguments)
{
if (m_id)
- m_category->tickAsynchronous(m_id, name);
+ m_category->tick('n', m_id, std::move(name), std::forward<Arguments>(arguments)...);
}
- void end()
+ template<typename... Arguments>
+ void end(Arguments &&...arguments)
{
if (m_id)
- m_category->endAsynchronous(m_id, m_name);
+ m_category->end('e', m_id, std::move(m_name), std::forward<Arguments>(arguments)...);
m_id = 0;
}
@@ -369,15 +574,25 @@ class Category
public:
using IsActive = std::false_type;
using ArgumentType = typename TraceEvent::ArgumentType;
- using TokenType = Token<Category, false>;
+ using ArgumentsStringType = typename TraceEvent::ArgumentsStringType;
+ using AsynchronousTokenType = AsynchronousToken<Category, false>;
+ using ObjectTokenType = ObjectToken<Category, false>;
Category(ArgumentType, EventQueue<TraceEvent, std::true_type> &) {}
Category(ArgumentType, EventQueue<TraceEvent, std::false_type> &) {}
- TokenType beginAsynchronous(ArgumentType) { return {}; }
+ template<typename... Arguments>
+ AsynchronousTokenType beginAsynchronous(ArgumentType, Arguments &&...)
+ {
+ return {};
+ }
- void tickAsynchronous(ArgumentType) {}
+ template<typename... Arguments>
+ ObjectTokenType beginObject(ArgumentType, Arguments &&...)
+ {
+ return {};
+ }
static constexpr bool isActive() { return false; }
};
@@ -388,10 +603,13 @@ class Category<TraceEvent, true>
public:
using IsActive = std::true_type;
using ArgumentType = typename TraceEvent::ArgumentType;
+ using ArgumentsStringType = typename TraceEvent::ArgumentsStringType;
using StringType = typename TraceEvent::StringType;
- using TokenType = Token<Category, true>;
+ using AsynchronousTokenType = AsynchronousToken<Category, true>;
+ using ObjectTokenType = ObjectToken<Category, true>;
- friend TokenType;
+ friend AsynchronousTokenType;
+ friend ObjectTokenType;
template<typename EventQueue>
Category(ArgumentType name, EventQueue &queue)
@@ -403,11 +621,33 @@ public:
idCounter = globalIdCounter += 1ULL << 32;
}
- TokenType beginAsynchronous(ArgumentType traceName)
+ template<typename... Arguments>
+ AsynchronousTokenType beginAsynchronous(ArgumentType traceName, Arguments &&...arguments)
+ {
+ std::size_t id = ++idCounter;
+
+ begin('b', id, std::move(traceName), std::forward<Arguments>(arguments)...);
+
+ return {traceName, id, *this};
+ }
+
+ ObjectTokenType beginObject(ArgumentType traceName)
+ {
+ std::size_t id = ++idCounter;
+
+ if (id)
+ begin('b', id, std::move(traceName));
+
+ return {traceName, id, *this};
+ }
+
+ template<typename... Arguments>
+ ObjectTokenType beginObject(ArgumentType traceName, Arguments &&...arguments)
{
std::size_t id = ++idCounter;
- beginAsynchronous(id, traceName);
+ if (id)
+ begin('b', id, std::move(traceName), std::forward<Arguments>(arguments)...);
return {traceName, id, *this};
}
@@ -419,36 +659,65 @@ public:
static constexpr bool isActive() { return true; }
private:
- void beginAsynchronous(std::size_t id, StringType traceName)
+ static void appendArguments(TraceEvent &) {}
+
+ static void appendArguments(TraceEvent &traceEvent, TracerLiteral arguments)
+ {
+ traceEvent.arguments = arguments;
+ }
+
+ template<typename LocalTraceEvent, typename... Arguments>
+ static void appendArguments(LocalTraceEvent &traceEvent, Arguments &&...arguments)
+ {
+ using String = typename LocalTraceEvent::ArgumentsStringType;
+ static_assert(
+ !std::is_same_v<String, std::string_view>,
+ R"(The arguments type of the tracing event queue is a string view. You can only provide trace token arguments as TracerLiteral (""_t).)");
+
+ traceEvent.arguments = Internal::toArguments<String>(std::forward<Arguments>(arguments)...);
+ }
+
+ template<typename... Arguments>
+ void begin(char type, std::size_t id, StringType traceName, Arguments &&...arguments)
{
auto &traceEvent = getTraceEvent(m_eventQueue);
+
traceEvent.name = std::move(traceName);
traceEvent.category = m_name;
- traceEvent.type = 'b';
+ traceEvent.type = type;
traceEvent.id = id;
+ appendArguments(traceEvent, std::forward<Arguments>(arguments)...);
traceEvent.time = Clock::now();
}
- void tickAsynchronous(std::size_t id, StringType traceName)
+ template<typename... Arguments>
+ void tick(char type, std::size_t id, StringType traceName, Arguments &&...arguments)
{
auto time = Clock::now();
+
auto &traceEvent = getTraceEvent(m_eventQueue);
+
traceEvent.name = std::move(traceName);
traceEvent.category = m_name;
traceEvent.time = time;
- traceEvent.type = 'n';
+ traceEvent.type = type;
traceEvent.id = id;
+ appendArguments(traceEvent, std::forward<Arguments>(arguments)...);
}
- void endAsynchronous(std::size_t id, StringType traceName)
+ template<typename... Arguments>
+ void end(char type, std::size_t id, StringType traceName, Arguments &&...arguments)
{
auto time = Clock::now();
+
auto &traceEvent = getTraceEvent(m_eventQueue);
+
traceEvent.name = std::move(traceName);
traceEvent.category = m_name;
traceEvent.time = time;
- traceEvent.type = 'e';
+ traceEvent.type = type;
traceEvent.id = id;
+ appendArguments(traceEvent, std::forward<Arguments>(arguments)...);
}
private:
@@ -462,6 +731,8 @@ template<bool enabled>
using StringViewCategory = Category<StringViewTraceEvent, enabled>;
template<bool enabled>
using StringCategory = Category<StringTraceEvent, enabled>;
+template<bool enabled>
+using StringViewWithStringArgumentsCategory = Category<StringViewWithStringArgumentsTraceEvent, enabled>;
template<typename Category>
class Tracer
@@ -473,6 +744,10 @@ public:
constexpr Tracer(ArgumentType, Category &) {}
+ Tracer(const Tracer &) = delete;
+ Tracer &operator=(const Tracer &) = delete;
+ Tracer(Tracer &&other) noexcept = default;
+ Tracer &operator=(Tracer &&other) noexcept = delete;
~Tracer() {}
};
@@ -500,6 +775,10 @@ public:
}
}
+ Tracer(const Tracer &) = delete;
+ Tracer &operator=(const Tracer &) = delete;
+ Tracer(Tracer &&other) noexcept = default;
+ Tracer &operator=(Tracer &&other) noexcept = delete;
~Tracer()
{
if constexpr (isTracerActive()) {
@@ -529,7 +808,7 @@ class Tracer<StringCategory<true>>
public:
Tracer(std::string name, StringViewCategory<true> &category, std::string arguments)
: m_name{std::move(name)}
- , m_arguments{arguments}
+ , m_arguments{std::move(arguments)}
, m_category{category}
{
if constexpr (isTracerActive()) {
diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt
index e92dc29942f..275e75a8cff 100644
--- a/src/plugins/qmldesigner/CMakeLists.txt
+++ b/src/plugins/qmldesigner/CMakeLists.txt
@@ -23,6 +23,11 @@ env_with_default("QTC_ENABLE_IMAGE_CACHE_TRACING" ENV_QTC_ENABLE_IMAGE_CACHE_TRA
option(ENABLE_IMAGE_CACHE_TRACING "Enable image cache tracing" ${ENV_QTC_ENABLE_IMAGE_CACHE_TRACING})
add_feature_info("Image cache tracing" ${ENABLE_IMAGE_CACHE_TRACING} "")
+env_with_default("QTC_ENABLE_MODEL_TRACING" ENV_QTC_ENABLE_MODEL_TRACING OFF)
+option(ENABLE_MODEL_TRACING "Enable model tracing" ${ENV_QTC_ENABLE_MODEL_TRACING})
+add_feature_info("Model tracing" ${ENABLE_MODEL_TRACING} "")
+
+
add_qtc_library(QmlDesignerUtils STATIC
DEPENDS
@@ -96,8 +101,10 @@ extend_qtc_library(QmlDesignerCore
CONDITION TARGET Nanotrace
DEPENDS Nanotrace
DEFINES
+ ENABLE_QMLDESIGNER_TRACING
$<$<BOOL:${ENABLE_PROJECT_STORAGE_TRACING}>:ENABLE_PROJECT_STORAGE_TRACING>
$<$<BOOL:${ENABLE_IMAGE_CACHE_TRACING}>:ENABLE_IMAGE_CACHE_TRACING>
+ $<$<BOOL:${ENABLE_MODEL_TRACING}>:ENABLE_MODEL_TRACING>
)
extend_qtc_library(QmlDesignerCore
@@ -202,6 +209,12 @@ extend_qtc_library(QmlDesignerCore
)
extend_qtc_library(QmlDesignerCore
+ SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/designercore/tracing
+ SOURCES
+ qmldesignertracing.cpp qmldesignertracing.h
+)
+
+extend_qtc_library(QmlDesignerCore
SOURCES_PREFIX ${CMAKE_CURRENT_LIST_DIR}/designercore/include
SOURCES
abstractview.h
diff --git a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp
index 19fba2e15c5..37e3e05ac0f 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp
+++ b/src/plugins/qmldesigner/designercore/imagecache/asynchronousimagecache.cpp
@@ -7,6 +7,8 @@
#include "imagecachestorage.h"
#include "timestampprovider.h"
+#include <tracing/qmldesignertracing.h>
+
#include <QScopeGuard>
#include <thread>
@@ -17,15 +19,8 @@ using namespace NanotraceHR::Literals;
namespace ImageCache {
namespace {
-using TraceFile = NanotraceHR::TraceFile<ImageCache::tracingIsEnabled()>;
-
-TraceFile traceFile{"qml_designer.json"};
-
-thread_local auto eventQueueData = NanotraceHR::makeEventQueueData<NanotraceHR::StringViewTraceEvent, 10000>(
- traceFile);
-thread_local NanotraceHR::EventQueue eventQueue = eventQueueData.createEventQueue();
-thread_local Category category_{"image cache"_t, eventQueue};
+thread_local Category category_{"image cache"_t, QmlDesigner::Tracing::eventQueue()};
} // namespace
Category &category()
diff --git a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h
index e89e25bcb29..3b28c117fdb 100644
--- a/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h
+++ b/src/plugins/qmldesigner/designercore/imagecache/imagecachegenerator.h
@@ -68,7 +68,7 @@ private:
std::vector<ImageCache::CaptureImageWithScaledImagesCallback> captureCallbacks;
std::vector<ImageCache::InternalAbortCallback> abortCallbacks;
Sqlite::TimeStamp timeStamp;
- ImageCache::TraceToken traceToken;
+ NO_UNIQUE_ADDRESS ImageCache::TraceToken traceToken;
};
void startGeneration();
diff --git a/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h b/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h
index b1948f566bd..c3fc7bcd153 100644
--- a/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h
+++ b/src/plugins/qmldesigner/designercore/include/asynchronousimagecache.h
@@ -78,7 +78,7 @@ private:
ImageCache::AbortCallback abortCallback;
ImageCache::AuxiliaryData auxiliaryData;
RequestType requestType = RequestType::Image;
- ImageCache::TraceToken traceToken;
+ NO_UNIQUE_ADDRESS ImageCache::TraceToken traceToken;
};
static void request(Utils::SmallStringView name,
diff --git a/src/plugins/qmldesigner/designercore/include/imagecacheauxiliarydata.h b/src/plugins/qmldesigner/designercore/include/imagecacheauxiliarydata.h
index b27816f0548..96667624ad6 100644
--- a/src/plugins/qmldesigner/designercore/include/imagecacheauxiliarydata.h
+++ b/src/plugins/qmldesigner/designercore/include/imagecacheauxiliarydata.h
@@ -27,7 +27,7 @@ constexpr bool tracingIsEnabled()
}
using Category = NanotraceHR::StringViewCategory<tracingIsEnabled()>;
-using TraceToken = Category::TokenType;
+using TraceToken = Category::AsynchronousTokenType;
Category &category();
class FontCollectorSizeAuxiliaryData
diff --git a/src/plugins/qmldesigner/designercore/model/internalnode_p.h b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
index af5b43eec28..7d32b498a09 100644
--- a/src/plugins/qmldesigner/designercore/model/internalnode_p.h
+++ b/src/plugins/qmldesigner/designercore/model/internalnode_p.h
@@ -13,6 +13,7 @@
#include <auxiliarydata.h>
#include <projectstorageids.h>
+#include <tracing/qmldesignertracing.h>
#include <utils/smallstring.h>
#include <QHash>
@@ -30,6 +31,7 @@
namespace QmlDesigner {
namespace Internal {
+using namespace NanotraceHR::Literals;
class InternalProperty;
class InternalNode;
@@ -221,6 +223,8 @@ public:
ModuleId moduleId;
ImportedTypeNameId importedTypeNameId;
TypeId typeId;
+ NO_UNIQUE_ADDRESS ModelTracing::ObjectTraceToken traceToken = ModelTracing::category().beginObject(
+ "InternalNode"_t);
private:
AuxiliaryDatas m_auxiliaryDatas;
diff --git a/src/plugins/qmldesigner/designercore/model/internalproperty.h b/src/plugins/qmldesigner/designercore/model/internalproperty.h
index 66d0bcaa881..2dfcdd616bb 100644
--- a/src/plugins/qmldesigner/designercore/model/internalproperty.h
+++ b/src/plugins/qmldesigner/designercore/model/internalproperty.h
@@ -5,6 +5,8 @@
#include "qmldesignercorelib_global.h"
+#include <tracing/qmldesignertracing.h>
+
#include <QVariant>
#include <memory>
@@ -14,6 +16,8 @@ namespace QmlDesigner {
namespace Internal {
+using namespace NanotraceHR::Literals;
+
class InternalBindingProperty;
class InternalSignalHandlerProperty;
class InternalSignalDeclarationProperty;
@@ -185,6 +189,8 @@ private:
TypeName m_dynamicType;
std::weak_ptr<InternalNode> m_propertyOwner;
PropertyType m_propertyType = PropertyType::None;
+ NO_UNIQUE_ADDRESS ModelTracing::ObjectTraceToken traceToken = ModelTracing::category().beginObject(
+ "InternalProperty"_t, std::forward_as_tuple("name", m_name));
};
} // namespace Internal
diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp
index b85a0d8b403..67001855757 100644
--- a/src/plugins/qmldesigner/designercore/model/model.cpp
+++ b/src/plugins/qmldesigner/designercore/model/model.cpp
@@ -46,6 +46,8 @@
#include <QRegularExpression>
#include <qcompilerdetection.h>
+#include <string>
+
/*!
\defgroup CoreModel
*/
@@ -473,9 +475,12 @@ void ModelPrivate::setMetaInfo(const MetaInfo &metaInfo)
void ModelPrivate::changeNodeId(const InternalNodePointer &node, const QString &id)
{
+ using namespace NanotraceHR::Literals;
+
const QString oldId = node->id;
node->id = id;
+ node->traceToken.change("id"_t, std::forward_as_tuple("id", id));
if (!oldId.isEmpty())
m_idNodeHash.remove(oldId);
if (!id.isEmpty())
diff --git a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
index 29f732dea60..c3b659f6453 100644
--- a/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
+++ b/src/plugins/qmldesigner/designercore/projectstorage/projectstorage.cpp
@@ -3,20 +3,15 @@
#include "projectstorage.h"
+#include <tracing/qmldesignertracing.h>
+
#include <sqlitedatabase.h>
namespace QmlDesigner {
-namespace {
-NanotraceHR::TraceFile<projectStorageTracingIsEnabled()> traceFile{"projectstorage.json"};
-
-thread_local auto eventQueueData = NanotraceHR::makeEventQueueData<NanotraceHR::StringViewTraceEvent, 1000>(
- traceFile);
-thread_local NanotraceHR::EventQueue eventQueue = eventQueueData.createEventQueue();
-} // namespace
-
thread_local NanotraceHR::StringViewCategory<projectStorageTracingIsEnabled()> projectStorageCategory{
- "project storage"_t, eventQueue};
+ "project storage"_t, Tracing::eventQueue()};
+
} // namespace QmlDesigner
template class QmlDesigner::ProjectStorage<Sqlite::Database>;
diff --git a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
new file mode 100644
index 00000000000..5912914f6e9
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.cpp
@@ -0,0 +1,45 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "qmldesignertracing.h"
+
+namespace QmlDesigner {
+namespace Tracing {
+
+namespace {
+using TraceFile = NanotraceHR::TraceFile<tracingIsEnabled()>;
+
+TraceFile traceFile{"qml_designer.json"};
+
+thread_local auto strinViewEventQueueData = NanotraceHR::makeEventQueueData<NanotraceHR::StringViewTraceEvent,
+ 10000>(traceFile);
+thread_local NanotraceHR::EventQueue stringViewEventQueue_ = strinViewEventQueueData.createEventQueue();
+
+thread_local auto stringViewWithStringArgumentsEventQueueData = NanotraceHR::
+ makeEventQueueData<NanotraceHR::StringViewWithStringArgumentsTraceEvent, 1000>(traceFile);
+thread_local NanotraceHR::EventQueue stringViewEventWithStringArgumentsQueue_ = stringViewWithStringArgumentsEventQueueData
+ .createEventQueue();
+} // namespace
+
+EventQueue &eventQueue()
+{
+ return stringViewEventQueue_;
+}
+
+} // namespace Tracing
+
+namespace ModelTracing {
+namespace {
+using namespace NanotraceHR::Literals;
+
+thread_local Category category_{"model"_t, Tracing::stringViewEventWithStringArgumentsQueue_};
+
+} // namespace
+
+Category &category()
+{
+ return category_;
+}
+
+} // namespace ModelTracing
+} // namespace QmlDesigner
diff --git a/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
new file mode 100644
index 00000000000..4a9c741cc4c
--- /dev/null
+++ b/src/plugins/qmldesigner/designercore/tracing/qmldesignertracing.h
@@ -0,0 +1,47 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <qmldesignercorelib_exports.h>
+
+#include <nanotrace/nanotracehr.h>
+
+#pragma once
+
+namespace QmlDesigner {
+namespace Tracing {
+#ifdef ENABLE_QMLDESIGNER_TRACING
+using Enabled = std::true_type;
+#else
+using Enabled = std::false_type;
+#endif
+
+constexpr bool tracingIsEnabled()
+{
+#ifdef ENABLE_QMLDESIGNER_TRACING
+ return NanotraceHR::isTracerActive();
+#else
+ return false;
+#endif
+}
+
+using EventQueue = NanotraceHR::EventQueue<NanotraceHR::StringViewTraceEvent, Enabled>;
+QMLDESIGNERCORE_EXPORT EventQueue &eventQueue();
+
+} // namespace Tracing
+
+namespace ModelTracing {
+constexpr bool tracingIsEnabled()
+{
+#ifdef ENABLE_MODEL_TRACING
+ return NanotraceHR::isTracerActive();
+#else
+ return false;
+#endif
+}
+
+using Category = NanotraceHR::StringViewWithStringArgumentsCategory<tracingIsEnabled()>;
+using ObjectTraceToken = Category::ObjectTokenType;
+QMLDESIGNERCORE_EXPORT Category &category();
+
+} // namespace ModelTracing
+} // namespace QmlDesigner