[Bf-blender-cvs] [e6cc94dabc7] profiler-editor: update profiler code

Jacques Lucke noreply at git.blender.org
Thu Apr 29 11:30:47 CEST 2021


Commit: e6cc94dabc766c01bd05a6aad40f9d2dac394ab5
Author: Jacques Lucke
Date:   Tue Apr 27 12:07:08 2021 +0200
Branches: profiler-editor
https://developer.blender.org/rBe6cc94dabc766c01bd05a6aad40f9d2dac394ab5

update profiler code

===================================================================

M	source/blender/blenlib/BLI_single_producer_chunk_consumer.hh
M	source/blender/blenlib/intern/profile.cc

===================================================================

diff --git a/source/blender/blenlib/BLI_single_producer_chunk_consumer.hh b/source/blender/blenlib/BLI_single_producer_chunk_consumer.hh
index cd8b647a276..cb5fc066a17 100644
--- a/source/blender/blenlib/BLI_single_producer_chunk_consumer.hh
+++ b/source/blender/blenlib/BLI_single_producer_chunk_consumer.hh
@@ -101,11 +101,10 @@ class SingleProducerChunkConsumerQueue {
 
   /**
    * Start appending a new element.
-   * Returns a pointer to uninitialized memory.
-   * The caller is responsible for constructing the new element in the returned buffer.
+   * This constructs the new element with the given parameters.
    * This must be used in conjunction with #commit_append.
    */
-  T *prepare_append()
+  template<typename... Args> T *prepare_append(Args &&... args)
   {
     if (current_->end == current_->capacity_end) {
       /* Create a new chunk when the current one is full. */
@@ -115,8 +114,8 @@ class SingleProducerChunkConsumerQueue {
       current_->next.store(new_chunk, std::memory_order_release);
       current_ = new_chunk;
     }
-    /* Return a pointer to the next uninitialized element. */
-    return current_->end;
+    /* Return a pointer to the next element. */
+    return new (current_->end) T(std::forward<Args>(args)...);
   }
 
   /**
@@ -202,7 +201,7 @@ class SingleProducerChunkConsumerQueue {
   void delete_chunk(Chunk *chunk)
   {
     destruct_n(chunk->begin, chunk->committed_size);
-    allocator_.deallocate(chunk->data);
+    allocator_.deallocate(chunk->begin);
     chunk->~Chunk();
     allocator_.deallocate(chunk);
   }
diff --git a/source/blender/blenlib/intern/profile.cc b/source/blender/blenlib/intern/profile.cc
index e55857b68fb..c6d3828e379 100644
--- a/source/blender/blenlib/intern/profile.cc
+++ b/source/blender/blenlib/intern/profile.cc
@@ -33,10 +33,32 @@ static uint64_t get_unique_session_id()
   return id++;
 }
 
-static RawVector<ProfileTaskBegin> recorded_task_begins;
-static RawVector<ProfileTaskEnd> recorded_task_ends;
-static thread_local RawStack<uint64_t> threadlocal_id_stack;
-static thread_local uint64_t threadlocal_thread_id = get_unique_session_id();
+struct ThreadLocalProfileData;
+
+static std::mutex registered_threadlocals_mutex;
+static RawVector<ThreadLocalProfileData *> registered_threadlocals;
+
+struct ThreadLocalProfileData {
+  ThreadLocalProfileData()
+  {
+    std::lock_guard lock{registered_threadlocals_mutex};
+    registered_threadlocals.append(this);
+    thread_id = get_unique_session_id();
+  }
+
+  ~ThreadLocalProfileData()
+  {
+    std::lock_guard lock{registered_threadlocals_mutex};
+    registered_threadlocals.remove_first_occurrence_and_reorder(this);
+  }
+
+  uint64_t thread_id;
+  SingleProducerChunkConsumerQueue<ProfileTaskBegin> queue_begins;
+  SingleProducerChunkConsumerQueue<ProfileTaskEnd> queue_ends;
+  RawStack<uint64_t> id_stack;
+};
+
+static ThreadLocalProfileData threadlocal_profile_data;
 bool bli_profiling_is_enabled = false;
 
 namespace blender::profile {
@@ -51,13 +73,12 @@ static void stop_profiling()
   bli_profiling_is_enabled = false;
 }
 
-/* TODO: Need to reduce threading overhead, but this works fine for now. */
-static std::mutex profile_mutex;
+static std::mutex listeners_mutex;
 static RawVector<ProfileListener *> listeners;
 
 ProfileListener::ProfileListener()
 {
-  std::lock_guard lock{profile_mutex};
+  std::lock_guard lock{listeners_mutex};
   listeners.append(this);
   if (listeners.size() == 1) {
     start_profiling();
@@ -66,7 +87,7 @@ ProfileListener::ProfileListener()
 
 ProfileListener::~ProfileListener()
 {
-  std::lock_guard lock{profile_mutex};
+  std::lock_guard lock{listeners_mutex};
   listeners.remove_first_occurrence_and_reorder(this);
   if (listeners.is_empty()) {
     stop_profiling();
@@ -75,13 +96,14 @@ ProfileListener::~ProfileListener()
 
 void ProfileListener::flush_to_all()
 {
-  std::lock_guard lock{profile_mutex};
-  RecordedProfile recorded_profile;
-  recorded_profile.task_begins = std::move(recorded_task_begins);
-  recorded_profile.task_ends = std::move(recorded_task_ends);
-
-  for (ProfileListener *listener : listeners) {
-    listener->handle(recorded_profile);
+  std::scoped_lock lock{listeners_mutex, registered_threadlocals_mutex};
+  for (ThreadLocalProfileData *data : registered_threadlocals) {
+    RecordedProfile recorded_profile;
+    /* Todo load data from threadlocals. */
+    UNUSED_VARS(data);
+    for (ProfileListener *listener : listeners) {
+      listener->handle(recorded_profile);
+    }
   }
 }
 
@@ -89,42 +111,41 @@ void ProfileListener::flush_to_all()
 
 void _bli_profile_task_begin(BLI_ProfileTask *task, const char *name)
 {
-  ProfileTaskBegin task_begin;
-  task_begin.id = get_unique_session_id();
-  task_begin.name = name;
-  task_begin.parent_id = threadlocal_id_stack.peek_default(0);
-  task_begin.thread_id = threadlocal_thread_id;
-  task_begin.time = Clock::now();
+  task->id = get_unique_session_id();
 
-  task->id = task_begin.id;
+  ProfileTaskBegin *task_begin = threadlocal_profile_data.queue_begins.prepare_append();
+  task_begin->id = task->id;
+  task_begin->name = name;
+  task_begin->parent_id = threadlocal_profile_data.id_stack.peek_default(0);
+  task_begin->thread_id = threadlocal_profile_data.thread_id;
+  task_begin->time = Clock::now();
 
-  std::scoped_lock lock{profile_mutex};
-  recorded_task_begins.append(task_begin);
+  threadlocal_profile_data.queue_begins.commit_append();
 }
 
 void _bli_profile_task_begin_subtask(BLI_ProfileTask *task,
                                      const char *name,
                                      const BLI_ProfileTask *parent_task)
 {
-  ProfileTaskBegin task_begin;
-  task_begin.id = get_unique_session_id();
-  task_begin.name = name;
-  task_begin.parent_id = parent_task->id;
-  task_begin.thread_id = threadlocal_thread_id;
-  task_begin.time = Clock::now();
+  task->id = get_unique_session_id();
 
-  task->id = task_begin.id;
+  ProfileTaskBegin *task_begin = threadlocal_profile_data.queue_begins.prepare_append();
+  task_begin->id = task->id;
+  task_begin->name = name;
+  task_begin->parent_id = parent_task->id;
+  task_begin->thread_id = threadlocal_profile_data.thread_id;
+  task_begin->time = Clock::now();
 
-  std::scoped_lock lock{profile_mutex};
-  recorded_task_begins.append(task_begin);
+  threadlocal_profile_data.queue_begins.commit_append();
 }
 
 void _bli_profile_task_end(BLI_ProfileTask *task)
 {
-  ProfileTaskEnd task_end;
-  task_end.begin_id = task->id;
-  task_end.time = Clock::now();
+  TimePoint time = Clock::now();
+
+  ProfileTaskEnd *task_end = threadlocal_profile_data.queue_ends.prepare_append();
+  task_end->begin_id = task->id;
+  task_end->time = time;
 
-  std::scoped_lock lock{profile_mutex};
-  recorded_task_ends.append(task_end);
+  threadlocal_profile_data.queue_ends.commit_append();
 }



More information about the Bf-blender-cvs mailing list