[Bf-blender-cvs] [7d7e90ca685] master: UI: Use vector instead of linked lists for context store

Hans Goudey noreply at git.blender.org
Mon Dec 19 06:24:20 CET 2022


Commit: 7d7e90ca685954409ece007d03d2e93860a6cef7
Author: Hans Goudey
Date:   Sun Dec 18 19:13:15 2022 -0600
Branches: master
https://developer.blender.org/rB7d7e90ca685954409ece007d03d2e93860a6cef7

UI: Use vector instead of linked lists for context store

Duplicating context lists took a measurable amount of time when drawing
large node trees in the node editor. Instead of using a linked list of
entries, which results in many small allocations, use a vector. Also,
use std::string and StringRefNull instead of char buffers and pointers.

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

M	source/blender/blenkernel/BKE_context.h
M	source/blender/blenkernel/intern/context.cc
M	source/blender/editors/interface/interface.cc

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

diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 90597a3e273..f836b98f3b2 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -16,6 +16,11 @@
 #include "DNA_object_enums.h"
 #include "RNA_types.h"
 
+#ifdef __cplusplus
+#  include "BLI_string_ref.hh"
+#  include "BLI_vector.hh"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -84,19 +89,22 @@ typedef int /*eContextResult*/ (*bContextDataCallback)(const bContext *C,
                                                        const char *member,
                                                        bContextDataResult *result);
 
-typedef struct bContextStoreEntry {
-  struct bContextStoreEntry *next, *prev;
+#ifdef __cplusplus
 
-  char name[128];
+struct bContextStoreEntry {
+  std::string name;
   PointerRNA ptr;
-} bContextStoreEntry;
+};
+
+struct bContextStore {
+  bContextStore *next = nullptr;
+  bContextStore *prev = nullptr;
 
-typedef struct bContextStore {
-  struct bContextStore *next, *prev;
+  blender::Vector<bContextStoreEntry> entries;
+  bool used = false;
+};
 
-  ListBase entries;
-  bool used;
-} bContextStore;
+#endif
 
 /* for the context's rna mode enum
  * keep aligned with data_mode_strings in context.cc */
@@ -132,18 +140,23 @@ void CTX_free(bContext *C);
 
 bContext *CTX_copy(const bContext *C);
 
+#ifdef __cplusplus
+
 /* Stored Context */
 
-bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr);
+bContextStore *CTX_store_add(ListBase *contexts,
+                             blender::StringRefNull name,
+                             const PointerRNA *ptr);
 bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context);
 bContextStore *CTX_store_get(bContext *C);
 void CTX_store_set(bContext *C, bContextStore *store);
 const PointerRNA *CTX_store_ptr_lookup(const bContextStore *store,
-                                       const char *name,
-                                       const StructRNA *type CPP_ARG_DEFAULT(nullptr));
-bContextStore *CTX_store_copy(bContextStore *store);
+                                       blender::StringRefNull name,
+                                       const StructRNA *type = nullptr);
+bContextStore *CTX_store_copy(const bContextStore *store);
 void CTX_store_free(bContextStore *store);
-void CTX_store_free_list(ListBase *contexts);
+
+#endif
 
 /* need to store if python is initialized or not */
 bool CTX_py_init_get(bContext *C);
diff --git a/source/blender/blenkernel/intern/context.cc b/source/blender/blenkernel/intern/context.cc
index 4469f22346a..8d8e96f26c8 100644
--- a/source/blender/blenkernel/intern/context.cc
+++ b/source/blender/blenkernel/intern/context.cc
@@ -126,7 +126,9 @@ void CTX_free(bContext *C)
 
 /* store */
 
-bContextStore *CTX_store_add(ListBase *contexts, const char *name, const PointerRNA *ptr)
+bContextStore *CTX_store_add(ListBase *contexts,
+                             const blender::StringRefNull name,
+                             const PointerRNA *ptr)
 {
   /* ensure we have a context to put the entry in, if it was already used
    * we have to copy the context to ensure */
@@ -134,23 +136,16 @@ bContextStore *CTX_store_add(ListBase *contexts, const char *name, const Pointer
 
   if (!ctx || ctx->used) {
     if (ctx) {
-      bContextStore *lastctx = ctx;
-      ctx = MEM_new<bContextStore>(__func__);
-      *ctx = *lastctx;
-      BLI_duplicatelist(&ctx->entries, &lastctx->entries);
+      ctx = MEM_new<bContextStore>(__func__, *ctx);
     }
     else {
-      ctx = MEM_cnew<bContextStore>(__func__);
+      ctx = MEM_new<bContextStore>(__func__);
     }
 
     BLI_addtail(contexts, ctx);
   }
 
-  bContextStoreEntry *entry = MEM_cnew<bContextStoreEntry>(__func__);
-  BLI_strncpy(entry->name, name, sizeof(entry->name));
-  entry->ptr = *ptr;
-
-  BLI_addtail(&ctx->entries, entry);
+  ctx->entries.append(bContextStoreEntry{name, *ptr});
 
   return ctx;
 }
@@ -163,22 +158,17 @@ bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context)
 
   if (!ctx || ctx->used) {
     if (ctx) {
-      bContextStore *lastctx = ctx;
-      ctx = MEM_new<bContextStore>(__func__);
-      *ctx = *lastctx;
-      BLI_duplicatelist(&ctx->entries, &lastctx->entries);
+      ctx = MEM_new<bContextStore>(__func__, *ctx);
     }
     else {
-      ctx = MEM_cnew<bContextStore>(__func__);
+      ctx = MEM_new<bContextStore>(__func__);
     }
 
     BLI_addtail(contexts, ctx);
   }
 
-  LISTBASE_FOREACH (bContextStoreEntry *, tentry, &context->entries) {
-    bContextStoreEntry *entry = MEM_cnew<bContextStoreEntry>(__func__);
-    *entry = *tentry;
-    BLI_addtail(&ctx->entries, entry);
+  for (const bContextStoreEntry &src_entry : context->entries) {
+    ctx->entries.append(src_entry);
   }
 
   return ctx;
@@ -195,42 +185,27 @@ void CTX_store_set(bContext *C, bContextStore *store)
 }
 
 const PointerRNA *CTX_store_ptr_lookup(const bContextStore *store,
-                                       const char *name,
+                                       const blender::StringRefNull name,
                                        const StructRNA *type)
 {
-  bContextStoreEntry *entry = static_cast<bContextStoreEntry *>(
-      BLI_rfindstring(&store->entries, name, offsetof(bContextStoreEntry, name)));
-  if (!entry) {
-    return nullptr;
-  }
-
-  if (type && !RNA_struct_is_a(entry->ptr.type, type)) {
-    return nullptr;
+  for (auto entry = store->entries.rbegin(); entry != store->entries.rend(); ++entry) {
+    if (entry->name == name) {
+      if (type && RNA_struct_is_a(entry->ptr.type, type)) {
+        return &entry->ptr;
+      }
+    }
   }
-  return &entry->ptr;
+  return nullptr;
 }
 
-bContextStore *CTX_store_copy(bContextStore *store)
+bContextStore *CTX_store_copy(const bContextStore *store)
 {
-  bContextStore *ctx = MEM_cnew<bContextStore>(__func__);
-  *ctx = *store;
-  BLI_duplicatelist(&ctx->entries, &store->entries);
-
-  return ctx;
+  return MEM_new<bContextStore>(__func__, *store);
 }
 
 void CTX_store_free(bContextStore *store)
 {
-  BLI_freelistN(&store->entries);
-  MEM_freeN(store);
-}
-
-void CTX_store_free_list(ListBase *contexts)
-{
-  bContextStore *ctx;
-  while ((ctx = static_cast<bContextStore *>(BLI_pophead(contexts)))) {
-    CTX_store_free(ctx);
-  }
+  MEM_delete(store);
 }
 
 /* is python initialized? */
@@ -592,11 +567,8 @@ ListBase CTX_data_dir_get_ex(const bContext *C,
     RNA_PROP_END;
   }
   if (use_store && C->wm.store) {
-    bContextStoreEntry *entry;
-
-    for (entry = static_cast<bContextStoreEntry *>(C->wm.store->entries.first); entry;
-         entry = entry->next) {
-      data_dir_add(&lb, entry->name, use_all);
+    for (const bContextStoreEntry &entry : C->wm.store->entries) {
+      data_dir_add(&lb, entry.name.c_str(), use_all);
     }
   }
   if ((region = CTX_wm_region(C)) && region->type && region->type->context) {
diff --git a/source/blender/editors/interface/interface.cc b/source/blender/editors/interface/interface.cc
index 4d423f989a6..c16c3068320 100644
--- a/source/blender/editors/interface/interface.cc
+++ b/source/blender/editors/interface/interface.cc
@@ -3470,7 +3470,9 @@ void UI_block_free(const bContext *C, uiBlock *block)
     MEM_freeN(block->func_argN);
   }
 
-  CTX_store_free_list(&block->contexts);
+  LISTBASE_FOREACH_MUTABLE (bContextStore *, store, &block->contexts) {
+    CTX_store_free(store);
+  }
 
   BLI_freelistN(&block->saferct);
   BLI_freelistN(&block->color_pickers.list);



More information about the Bf-blender-cvs mailing list