diff options
author | Marco Bubke <marco.bubke@qt.io> | 2023-10-14 15:56:03 +0200 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@qt.io> | 2023-10-17 11:55:03 +0000 |
commit | ad12bbb6698a6c00ed127f79a0078f52b1e7ce7d (patch) | |
tree | 10bc3ca87b822387a0763defa7f25824f75d043a /src | |
parent | 11bf705e26bec1db1f33304d2cdbd00559b91b9c (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')
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 |