diff --git a/src/libs/core/impl/TraceLogger.cpp b/src/libs/core/impl/TraceLogger.cpp index 5a6be0bc..5d264f0c 100644 --- a/src/libs/core/impl/TraceLogger.cpp +++ b/src/libs/core/impl/TraceLogger.cpp @@ -68,7 +68,7 @@ namespace lms::core::tracing for (Buffer& buffer : _buffers) _freeBuffers.push_back(&buffer); - LMS_LOG(UTILS, INFO, "TraceLogger: using " << _buffers.size() << " buffers. Buffer size = " << std::to_string(BufferSize) << ", entry size = " << sizeof(CompleteEvent) << ", entry count per buffer = " << Buffer::CompleteEventCount); + LMS_LOG(UTILS, INFO, "TraceLogger: using " << _buffers.size() << " buffers. Buffer size = " << std::to_string(BufferSize) << ", entry size = " << sizeof(CompleteEventEntry) << ", entry count per buffer = " << Buffer::CompleteEventCount); } bool TraceLogger::isLevelActive(Level level) const @@ -81,7 +81,12 @@ namespace lms::core::tracing if (!_currentBuffer) _currentBuffer = acquireBuffer(); - _currentBuffer->durationEvents[_currentBuffer->currentDurationIndex] = event; + CompleteEventEntry& entry{ _currentBuffer->durationEvents[_currentBuffer->currentDurationIndex] }; + entry.start = event.start; + entry.duration = event.duration; + entry.name = event.name.c_str(); + entry.category = event.category.c_str(); + entry.arg = event.arg.value_or(invalidHash); // update the index after writing the event, in case another thread wants to dump if (++_currentBuffer->currentDurationIndex == _currentBuffer->durationEvents.size()) @@ -163,7 +168,7 @@ namespace lms::core::tracing // Hence the double representation as the microsecond unit is not precise enough using clockMicro = std::chrono::duration; - const CompleteEvent& event{ buffer.durationEvents[i] }; + const CompleteEventEntry& event{ buffer.durationEvents[i] }; if (first) first = false; @@ -171,24 +176,24 @@ namespace lms::core::tracing os << ", " << std::endl;; os << "\t\t{ "; - os << "\"name\" : \"" << event.name.c_str() << "\", "; - os << "\"cat\" : \"" << event.category.c_str() << "\", "; + os << "\"name\" : \"" << event.name << "\", "; + os << "\"cat\" : \"" << event.category << "\", "; os << "\"pid\": 1, "; os << "\"tid\" : " << threadId << ", "; os << "\"ts\" : " << std::fixed << std::setprecision(3) << std::chrono::duration_cast(event.start - _start).count() << ", "; os << "\"dur\" : " << std::fixed << std::setprecision(3) << std::chrono::duration_cast(event.duration).count() << ", "; os << "\"ph\" : \"X\""; - if (event.arg.has_value()) + if (event.arg != invalidHash) { ArgEntryMap::const_iterator itArgEntry; { std::shared_lock lock{ _argMutex }; - itArgEntry = _argEntries.find(*event.arg); + itArgEntry = _argEntries.find(event.arg); assert(itArgEntry != _argEntries.cend()); } os << ", \"args\" : { \"" << itArgEntry->second.type.c_str() << "\" : \""; - stringUtils::writeJSEscapedString(os, std::string_view{ itArgEntry->second.value }); + stringUtils::writeJsonEscapedString(os, std::string_view{ itArgEntry->second.value }); os << "\" }"; } os << " }"; @@ -198,6 +203,7 @@ namespace lms::core::tracing os << std::endl; os << "\t]," << std::endl; + os << "\t\"meta_registered_arg_count\" : " << getRegisteredArgCount() << ", " << std::endl; os << "\t\"meta_cpu_count\" : " << std::thread::hardware_concurrency() << ", " << std::endl; os << "\t\"meta_build_type\" : "; #ifndef NDEBUG @@ -226,6 +232,7 @@ namespace lms::core::tracing TraceLogger::ArgHashType TraceLogger::registerArg(LiteralString argType, std::string_view argValue) { const ArgHashType hash{ computeArgHash(argType, argValue) }; + assert(hash != invalidHash); { const std::shared_lock lock{ _argMutex }; @@ -255,6 +262,13 @@ namespace lms::core::tracing } } + std::size_t TraceLogger::getRegisteredArgCount() const + { + const std::shared_lock lock{ _argMutex }; + + return _argEntries.size(); + } + std::uint32_t TraceLogger::toTraceThreadId(std::thread::id threadId) { // Pefetto UI does not accept 64bits thread ids diff --git a/src/libs/core/impl/TraceLogger.hpp b/src/libs/core/impl/TraceLogger.hpp index ee81090b..ba90c690 100644 --- a/src/libs/core/impl/TraceLogger.hpp +++ b/src/libs/core/impl/TraceLogger.hpp @@ -44,18 +44,30 @@ namespace lms::core::tracing void dumpCurrentBuffer(std::ostream& os) override; void setThreadName(std::thread::id id, std::string_view threadName) override; ArgHashType registerArg(LiteralString argType, std::string_view argValue) override; + std::size_t getRegisteredArgCount() const; static ArgHashType computeArgHash(LiteralString type, std::string_view value); static std::uint32_t toTraceThreadId(std::thread::id threadId); static constexpr std::size_t BufferSize{ 64 * 1024 }; + // Same as ComplteEvent, but compacted + struct CompleteEventEntry + { + clock::time_point start; + clock::duration duration; + const char* name; + const char* category; + ArgHashType arg; + }; + static constexpr ArgHashType invalidHash{ 0 }; + struct alignas(64) Buffer { - static constexpr std::size_t CompleteEventCount{ BufferSize / sizeof(CompleteEvent) }; + static constexpr std::size_t CompleteEventCount{ BufferSize / sizeof(CompleteEventEntry) }; std::thread::id threadId; - std::array durationEvents; + std::array durationEvents; std::atomic currentDurationIndex{}; }; @@ -68,7 +80,7 @@ namespace lms::core::tracing std::vector _buffers; // allocated once during construction - std::shared_mutex _argMutex; + mutable std::shared_mutex _argMutex; struct ArgEntry { LiteralString type;