[Bf-blender-cvs] [d34c240ebf4] functions: Cache particle blocks in container for reuse

Jacques Lucke noreply at git.blender.org
Wed Jul 10 12:00:57 CEST 2019


Commit: d34c240ebf40aac87aeae732184ddee4f89e65c3
Author: Jacques Lucke
Date:   Wed Jul 10 11:05:46 2019 +0200
Branches: functions
https://developer.blender.org/rBd34c240ebf40aac87aeae732184ddee4f89e65c3

Cache particle blocks in container for reuse

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

M	source/blender/blenlib/BLI_small_stack.hpp
M	source/blender/blenlib/BLI_small_vector.hpp
M	source/blender/simulations/bparticles/particles_container.cpp
M	source/blender/simulations/bparticles/particles_container.hpp
M	source/blender/simulations/bparticles/simulate.cpp

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

diff --git a/source/blender/blenlib/BLI_small_stack.hpp b/source/blender/blenlib/BLI_small_stack.hpp
index 31555dbcd43..fe6667e8bd5 100644
--- a/source/blender/blenlib/BLI_small_stack.hpp
+++ b/source/blender/blenlib/BLI_small_stack.hpp
@@ -42,6 +42,11 @@ template<typename T, uint N = 4> class SmallStack {
   {
   }
 
+  operator ArrayRef<T>()
+  {
+    return m_elements;
+  }
+
   /**
    * Return the number of elements in the stack.
    */
diff --git a/source/blender/blenlib/BLI_small_vector.hpp b/source/blender/blenlib/BLI_small_vector.hpp
index 64c2e7ee75e..ffa275973b5 100644
--- a/source/blender/blenlib/BLI_small_vector.hpp
+++ b/source/blender/blenlib/BLI_small_vector.hpp
@@ -261,6 +261,11 @@ template<typename T, uint N = 4> class SmallVector {
     this->extend(other.begin(), other.size());
   }
 
+  void extend(ArrayRef<T> array)
+  {
+    this->extend(array.begin(), array.size());
+  }
+
   void extend(const T *start, uint amount)
   {
     this->reserve(m_size + amount);
diff --git a/source/blender/simulations/bparticles/particles_container.cpp b/source/blender/simulations/bparticles/particles_container.cpp
index 318ec66ec43..01f064f9938 100644
--- a/source/blender/simulations/bparticles/particles_container.cpp
+++ b/source/blender/simulations/bparticles/particles_container.cpp
@@ -1,5 +1,9 @@
+#include "BLI_timeit.hpp"
+
 #include "particles_container.hpp"
 
+#define CACHED_BLOCKS_PER_CONTAINER 5
+
 namespace BParticles {
 
 ParticlesBlock::ParticlesBlock(ParticlesContainer &container, AttributeArraysCore &attributes_core)
@@ -14,21 +18,28 @@ ParticlesContainer::ParticlesContainer(AttributesInfo attributes, uint block_siz
 
 ParticlesContainer::~ParticlesContainer()
 {
-  while (m_blocks.size() > 0) {
-    ParticlesBlock *block = m_blocks.any();
-    block->clear();
-    this->release_block(*block);
+  for (ParticlesBlock *block : m_active_blocks) {
+    this->free_block(block);
+  }
+  for (ParticlesBlock *block : m_cached_blocks) {
+    this->free_block(block);
   }
 }
 
 ParticlesBlock &ParticlesContainer::new_block()
 {
+  SCOPED_TIMER(__func__);
+
   std::lock_guard<std::mutex> lock(m_blocks_mutex);
 
-  AttributeArraysCore attributes_core = AttributeArraysCore::NewWithSeparateAllocations(
-      m_attributes_info, m_block_size);
-  ParticlesBlock *block = new ParticlesBlock(*this, attributes_core);
-  m_blocks.add_new(block);
+  if (!m_cached_blocks.empty()) {
+    ParticlesBlock *block = m_cached_blocks.pop();
+    m_active_blocks.add_new(block);
+    return *block;
+  }
+
+  ParticlesBlock *block = this->allocate_block();
+  m_active_blocks.add_new(block);
   return *block;
 }
 
@@ -37,12 +48,30 @@ void ParticlesContainer::release_block(ParticlesBlock &block)
   std::lock_guard<std::mutex> lock(m_blocks_mutex);
 
   BLI_assert(block.active_amount() == 0);
-  BLI_assert(m_blocks.contains(&block));
+  BLI_assert(m_active_blocks.contains(&block));
   BLI_assert(&block.container() == this);
 
-  block.attributes_core().free_buffers();
-  m_blocks.remove(&block);
-  delete █
+  m_active_blocks.remove(&block);
+  if (m_cached_blocks.size() < CACHED_BLOCKS_PER_CONTAINER) {
+    m_cached_blocks.push(&block);
+  }
+  else {
+    this->free_block(&block);
+  }
+}
+
+ParticlesBlock *ParticlesContainer::allocate_block()
+{
+  AttributeArraysCore attributes_core = AttributeArraysCore::NewWithSeparateAllocations(
+      m_attributes_info, m_block_size);
+  ParticlesBlock *block = new ParticlesBlock(*this, attributes_core);
+  return block;
+}
+
+void ParticlesContainer::free_block(ParticlesBlock *block)
+{
+  block->attributes_core().free_buffers();
+  delete block;
 }
 
 static SmallVector<int> map_attribute_indices(AttributesInfo &from_info, AttributesInfo &to_info)
@@ -93,7 +122,11 @@ void ParticlesContainer::update_attributes(AttributesInfo new_info)
 
   SmallVector<void *> arrays;
   arrays.reserve(new_info.amount());
-  for (ParticlesBlock *block : m_blocks) {
+
+  SmallVector<ParticlesBlock *> all_blocks;
+  all_blocks.extend(m_active_blocks);
+  all_blocks.extend(m_cached_blocks);
+  for (ParticlesBlock *block : all_blocks) {
     arrays.clear();
 
     for (uint new_index : new_info.attribute_indices()) {
@@ -127,7 +160,7 @@ void ParticlesContainer::flatten_attribute_data(StringRef attribute_name, void *
   uint element_size = size_of_attribute_type(m_attributes_info.type_of(attribute_index));
 
   uint offset = 0;
-  for (ParticlesBlock *block : m_blocks) {
+  for (ParticlesBlock *block : m_active_blocks) {
     uint amount = block->active_amount();
     void *src = block->attributes().get_ptr(attribute_index);
     memcpy(POINTER_OFFSET(dst, offset), src, amount * element_size);
diff --git a/source/blender/simulations/bparticles/particles_container.hpp b/source/blender/simulations/bparticles/particles_container.hpp
index a833573e134..ea91000ab68 100644
--- a/source/blender/simulations/bparticles/particles_container.hpp
+++ b/source/blender/simulations/bparticles/particles_container.hpp
@@ -3,6 +3,7 @@
 #include <mutex>
 
 #include "BLI_small_map.hpp"
+#include "BLI_small_stack.hpp"
 
 #include "attributes.hpp"
 
@@ -10,6 +11,7 @@ namespace BParticles {
 
 using BLI::SmallMap;
 using BLI::SmallSet;
+using BLI::SmallStack;
 
 class ParticlesContainer;
 class ParticlesBlock;
@@ -25,7 +27,8 @@ class ParticlesBlock;
 class ParticlesContainer {
  private:
   AttributesInfo m_attributes_info;
-  SmallSet<ParticlesBlock *> m_blocks;
+  SmallSetVector<ParticlesBlock *> m_active_blocks;
+  SmallStack<ParticlesBlock *> m_cached_blocks;
   uint m_block_size;
   std::mutex m_blocks_mutex;
 
@@ -59,7 +62,7 @@ class ParticlesContainer {
   /**
    * Get a read-only buffer of all the blocks currently in use.
    */
-  const SmallSet<ParticlesBlock *> &active_blocks();
+  ArrayRef<ParticlesBlock *> active_blocks();
 
   /**
    * Create a new block in this container. It safe to call this function from separate threads at
@@ -85,6 +88,10 @@ class ParticlesContainer {
   SmallVector<float3> flatten_attribute_float3(StringRef attribute_name);
 
   friend bool operator==(const ParticlesContainer &a, const ParticlesContainer &b);
+
+ private:
+  ParticlesBlock *allocate_block();
+  void free_block(ParticlesBlock *block);
 };
 
 /**
@@ -201,7 +208,7 @@ inline uint ParticlesContainer::block_size() const
 inline uint ParticlesContainer::count_active() const
 {
   uint count = 0;
-  for (ParticlesBlock *block : m_blocks) {
+  for (ParticlesBlock *block : m_active_blocks) {
     count += block->active_amount();
   }
   return count;
@@ -212,9 +219,9 @@ inline AttributesInfo &ParticlesContainer::attributes_info()
   return m_attributes_info;
 }
 
-inline const SmallSet<ParticlesBlock *> &ParticlesContainer::active_blocks()
+inline ArrayRef<ParticlesBlock *> ParticlesContainer::active_blocks()
 {
-  return m_blocks;
+  return m_active_blocks;
 }
 
 inline bool operator==(const ParticlesContainer &a, const ParticlesContainer &b)
diff --git a/source/blender/simulations/bparticles/simulate.cpp b/source/blender/simulations/bparticles/simulate.cpp
index cd2754ac4e6..214ed7f9b10 100644
--- a/source/blender/simulations/bparticles/simulate.cpp
+++ b/source/blender/simulations/bparticles/simulate.cpp
@@ -618,14 +618,14 @@ BLI_NOINLINE static void delete_tagged_particles(ParticlesState &state,
       USE_THREADING);
 }
 
-BLI_NOINLINE static void compress_all_blocks(ParticlesContainer &particles)
+BLI_NOINLINE static void compress_all_blocks(ParticlesContainer &container)
 {
-  SmallVector<ParticlesBlock *> blocks = particles.active_blocks().to_small_vector();
+  SmallVector<ParticlesBlock *> blocks = container.active_blocks();
   ParticlesBlock::Compress(blocks);
 
   for (ParticlesBlock *block : blocks) {
     if (block->is_empty()) {
-      particles.release_block(*block);
+      container.release_block(*block);
     }
   }
 }



More information about the Bf-blender-cvs mailing list