diff --git a/src/libs/utils/impl/Profiler.cpp b/src/libs/utils/impl/Profiler.cpp index b432108f..2849290e 100644 --- a/src/libs/utils/impl/Profiler.cpp +++ b/src/libs/utils/impl/Profiler.cpp @@ -63,6 +63,8 @@ namespace profiling if (bufferSizeinMBytes < MinBufferSizeInMBytes) throw LmsException{ "Profiler must be configured with at least " + std::to_string(MinBufferSizeInMBytes) + " MBytes" }; + setThreadName(_creatorThreadId, "MainThread"); + for (Buffer& buffer : _buffers) _freeBuffers.push_back(&buffer); @@ -124,16 +126,30 @@ namespace profiling os << "{" << std::endl; os << "\t\"traceEvents\": [" << std::endl; + bool first{ true }; + + { + std::scoped_lock lock{ _threadNameMutex }; + + for (const auto& [threadId, threadName] : _threadNames) + { + if (first) + first = false; + else + os << ", " << std::endl; + + os << "\t\t{ "; + os << "\"name\" : \"thread_name\", "; + os << "\"pid\" : 1, "; + os << "\"tid\" : " << threadId << ", "; + os << "\"ph\" : \"M\", "; + os << "\"args\" : { \"name\" : \"" + threadName + "\" }"; + os << " }"; + } + } + // we allow threads to fill in their current block while dumping { - os << "\t\t{ "; - os << "\"name\" : \"thread_name\", "; - os << "\"pid\" : 1, "; - os << "\"tid\" : " << _creatorThreadId << ", "; - os << "\"ph\" : \"M\", "; - os << "\"args\" : { \"name\" : \"MainThread\" }"; - os << " }"; - std::scoped_lock lock{ _mutex }; for (Buffer& buffer : _buffers) @@ -144,7 +160,11 @@ namespace profiling using clockMicro = std::chrono::duration; const CompleteEvent& event{ buffer.durationEvents[i] }; - os << "," << std::endl; + if (first) + first = false; + else + os << ", " << std::endl;; + os << "\t\t{ "; os << "\"name\" : \"" << event.name.c_str() << "\", "; os << "\"cat\" : \"" << event.category.c_str() << "\", "; @@ -163,4 +183,10 @@ namespace profiling os << "\t\"meta_cpu_count\" : " << std::thread::hardware_concurrency() << std::endl; os << "}" << std::endl; } + + void Profiler::setThreadName(std::thread::id id, std::string_view threadName) + { + std::scoped_lock lock{ _threadNameMutex }; + _threadNames.emplace(id, threadName); + } } \ No newline at end of file diff --git a/src/libs/utils/impl/Profiler.hpp b/src/libs/utils/impl/Profiler.hpp index e9668068..b8b4fdc2 100644 --- a/src/libs/utils/impl/Profiler.hpp +++ b/src/libs/utils/impl/Profiler.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "utils/IProfiler.hpp" @@ -40,6 +41,7 @@ namespace profiling bool isLevelActive(Level level) const override; void write(const CompleteEvent& event) override; void dumpCurrentBuffer(std::ostream& os) override; + void setThreadName(std::thread::id id, std::string_view threadName) override; static constexpr std::size_t BufferSize{ 32 * 1024 }; @@ -60,6 +62,9 @@ namespace profiling std::vector _buffers; // allocated once during construction + std::mutex _threadNameMutex; + std::unordered_map _threadNames; + std::mutex _mutex; std::deque _freeBuffers; diff --git a/src/libs/utils/include/utils/IProfiler.hpp b/src/libs/utils/include/utils/IProfiler.hpp index 3ce806a1..35cd3d12 100644 --- a/src/libs/utils/include/utils/IProfiler.hpp +++ b/src/libs/utils/include/utils/IProfiler.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "LiteralString.hpp" @@ -69,6 +70,7 @@ namespace profiling virtual bool isLevelActive(Level level) const = 0; virtual void write(const CompleteEvent& entry) = 0; virtual void dumpCurrentBuffer(std::ostream& os) = 0; + virtual void setThreadName(std::thread::id id, std::string_view threadName) = 0; }; static constexpr std::size_t MinBufferSizeInMBytes = 16;