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>
This commit is contained in:
Marco Bubke
2023-10-14 15:56:03 +02:00
committed by Tim Jenssen
parent 11bf705e26
commit ad12bbb669
14 changed files with 481 additions and 83 deletions

View File

@@ -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

View File

@@ -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,92 @@ 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;
constexpr Token(Token &&other) noexcept = default;
constexpr Token &operator=(Token &&other) noexcept = default;
~BasicDisabledToken() {}
constexpr explicit operator bool() const { return false; }
static constexpr bool isActive() { return false; }
Token begin(ArgumentType) { return Token{}; }
void tick(ArgumentType) {}
void end() {}
};
template<typename TraceEvent, bool enabled>
class Category;
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 Token<Category, true>
class ObjectToken<Category, true> : public BasicEnabledToken
{
Token(std::string_view name, std::size_t id, Category &category)
ObjectToken(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;
ObjectToken() = default;
Token(const Token &) = delete;
Token &operator=(const Token &) = delete;
ObjectToken(const ObjectToken &other) = delete;
Token(Token &&other) noexcept
: m_name{other.m_name}
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 &operator=(Token &&other) noexcept
ObjectToken &operator=(ObjectToken &&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 +444,120 @@ public:
return *this;
}
~Token() { end(); }
constexpr explicit operator bool() const { return m_id; }
static constexpr bool isActive() { return true; }
Token begin(ArgumentType name)
~ObjectToken()
{
if (m_id)
m_category->beginAsynchronous(m_id, name);
m_category->end('e', m_id, std::move(m_name));
return Token{m_name, m_id, *m_category};
m_id = 0;
}
void tick(ArgumentType name)
template<typename... Arguments>
void change(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()
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 AsynchronousToken<Category, true> : public BasicEnabledToken
{
AsynchronousToken(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;
AsynchronousToken() = default;
AsynchronousToken(const AsynchronousToken &) = delete;
AsynchronousToken &operator=(const AsynchronousToken &) = delete;
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)}
{}
AsynchronousToken &operator=(AsynchronousToken &&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;
}
~AsynchronousToken() { end(); }
template<typename... Arguments>
AsynchronousToken begin(ArgumentType name, Arguments &&...arguments)
{
if (m_id)
m_category->endAsynchronous(m_id, m_name);
m_category->begin('b', m_id, std::move(name), std::forward<Arguments>(arguments)...);
return AsynchronousToken{m_name, m_id, *m_category};
}
template<typename... Arguments>
void tick(ArgumentType name, Arguments &&...arguments)
{
if (m_id)
m_category->tick('n', m_id, std::move(name), std::forward<Arguments>(arguments)...);
}
template<typename... Arguments>
void end(Arguments &&...arguments)
{
if (m_id)
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;
beginAsynchronous(id, traceName);
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;
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()) {

View File

@@ -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
@@ -201,6 +208,12 @@ extend_qtc_library(QmlDesignerCore
timestampproviderinterface.h
)
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

View File

@@ -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()

View File

@@ -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();

View File

@@ -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,

View File

@@ -27,7 +27,7 @@ constexpr bool tracingIsEnabled()
}
using Category = NanotraceHR::StringViewCategory<tracingIsEnabled()>;
using TraceToken = Category::TokenType;
using TraceToken = Category::AsynchronousTokenType;
Category &category();
class FontCollectorSizeAuxiliaryData

View File

@@ -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;

View File

@@ -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

View File

@@ -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())

View File

@@ -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>;

View File

@@ -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

View File

@@ -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

View File

@@ -144,6 +144,7 @@ add_qtc_library(TestDesignerCore OBJECT
projectstorage/typeannotationreader.h
projectstorage/qmldocumentparserinterface.h
projectstorage/qmltypesparserinterface.h
tracing/qmldesignertracing.cpp tracing/qmldesignertracing.h
rewritertransaction.cpp
rewritertransaction.h
)