diff options
author | Jeroen Bakker <jbakker> | 2022-01-25 16:51:35 +0300 |
---|---|---|
committer | Jeroen Bakker <jeroen@blender.org> | 2022-01-25 16:51:44 +0300 |
commit | 948211679f2a0681421160be0d3b90f507bc0be7 (patch) | |
tree | 423b273d4c560b1ce64b4e37366764b228b690ed /source/blender/blenkernel/intern/lib_override.c | |
parent | 3f42417cd4c8c01142937ba03c8fa6ef6e895494 (diff) |
Performance: Remap multiple items in UI
During sprite fright loading of complex scenes would spend a long time in remapping ID's
The remapping process is done on a per ID instance that resulted in a very time consuming
process that goes over every possible ID reference to find out if it needs to be updated.
If there are N of references to ID blocks and there are M ID blocks that needed to be remapped
it would take N*M checks. These checks are scattered around the place and memory.
Each reference would only be updated at most once, but most of the time no update is needed at all.
Idea: By grouping the changes together will reduce the number of checks resulting in improved performance.
This would only require N checks. Additional benefits is improved data locality as data is only loaded once
in the L2 cache.
It has be implemented for the resyncing process and UI editors.
On an Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz 16Gig the resyncing process went
from 170 seconds to 145 seconds (during hotspot recording).
After this patch has been applied we could add similar approach
to references (references between data blocks) and functionality (tagged deletion).
In my understanding this could reduce the resyncing process to less than a second.
Opening the village production file between 10 and 20 seconds.
Flame graphs showing that UI remapping isn't visible anymore (`WM_main_remap_editor_id_reference`)
* Master {F12769210 size=full}
* This patch {F12769211 size=full}
Reviewed By: mont29
Maniphest Tasks: T94185
Differential Revision: https://developer.blender.org/D13615
Diffstat (limited to 'source/blender/blenkernel/intern/lib_override.c')
-rw-r--r-- | source/blender/blenkernel/intern/lib_override.c | 66 |
1 files changed, 41 insertions, 25 deletions
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 38ce8ea88b9..bc897e9075b 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -1121,6 +1121,45 @@ void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadRepor } } +static void lib_override_library_remap(Main *bmain, + const ID *id_root_reference, + GHash *linkedref_to_old_override) +{ + ID *id; + struct IDRemapper *remapper = BKE_id_remapper_create(); + FOREACH_MAIN_ID_BEGIN (bmain, id) { + + if (id->tag & LIB_TAG_DOIT && id->newid != NULL && id->lib == id_root_reference->lib) { + ID *id_override_new = id->newid; + ID *id_override_old = BLI_ghash_lookup(linkedref_to_old_override, id); + if (id_override_old == NULL) { + continue; + } + + BKE_id_remapper_add(remapper, id_override_old, id_override_new); + /* Remap no-main override IDs we just created too. */ + GHashIterator linkedref_to_old_override_iter; + GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) { + ID *id_override_old_iter = BLI_ghashIterator_getValue(&linkedref_to_old_override_iter); + if ((id_override_old_iter->tag & LIB_TAG_NO_MAIN) == 0) { + continue; + } + + BKE_libblock_relink_ex(bmain, + id_override_old_iter, + id_override_old, + id_override_new, + ID_REMAP_FORCE_USER_REFCOUNT | ID_REMAP_FORCE_NEVER_NULL_USAGE); + } + } + } + FOREACH_MAIN_ID_END; + + /* Remap all IDs to use the new override. */ + BKE_libblock_remap_multiple(bmain, remapper, 0); + BKE_id_remapper_free(remapper); +} + static bool lib_override_library_resync(Main *bmain, Scene *scene, ViewLayer *view_layer, @@ -1312,32 +1351,9 @@ static bool lib_override_library_resync(Main *bmain, } FOREACH_MAIN_LISTBASE_END; - /* We need to remap old to new override usages in a separate loop, after all new overrides have + /* We remap old to new override usages in a separate loop, after all new overrides have * been added to Main. */ - FOREACH_MAIN_ID_BEGIN (bmain, id) { - if (id->tag & LIB_TAG_DOIT && id->newid != NULL && id->lib == id_root_reference->lib) { - ID *id_override_new = id->newid; - ID *id_override_old = BLI_ghash_lookup(linkedref_to_old_override, id); - - if (id_override_old != NULL) { - /* Remap all IDs to use the new override. */ - BKE_libblock_remap(bmain, id_override_old, id_override_new, 0); - /* Remap no-main override IDs we just created too. */ - GHashIterator linkedref_to_old_override_iter; - GHASH_ITER (linkedref_to_old_override_iter, linkedref_to_old_override) { - ID *id_override_old_iter = BLI_ghashIterator_getValue(&linkedref_to_old_override_iter); - if (id_override_old_iter->tag & LIB_TAG_NO_MAIN) { - BKE_libblock_relink_ex(bmain, - id_override_old_iter, - id_override_old, - id_override_new, - ID_REMAP_FORCE_USER_REFCOUNT | ID_REMAP_FORCE_NEVER_NULL_USAGE); - } - } - } - } - } - FOREACH_MAIN_ID_END; + lib_override_library_remap(bmain, id_root_reference, linkedref_to_old_override); BKE_main_collection_sync(bmain); |