From a9a047c0e3b9ec69284a96af0c1d04e5314d8fce Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 20 Jun 2024 14:09:29 +0200 Subject: [PATCH] Core: use implicit sharing for PackedFile data Found this bottleneck when checking #122281. With this patch, `ED_undo_pop` in the provided file speeds up from `132 ms` to `18 ms`. Pull Request: https://projects.blender.org/blender/blender/pulls/123243 --- source/blender/blenkernel/intern/image.cc | 6 ++---- source/blender/blenkernel/intern/packedFile.cc | 18 ++++++++++++------ source/blender/makesdna/DNA_packedFile_types.h | 10 +++++++++- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index 6aa7144d262..43d67be1a44 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -1363,10 +1363,8 @@ static bool image_memorypack_imbuf( } ImagePackedFile *imapf; - PackedFile *pf = MEM_cnew("PackedFile"); - - pf->size = ibuf->encoded_size; - pf->data = IMB_steal_encoded_buffer(ibuf); + PackedFile *pf = BKE_packedfile_new_from_memory(IMB_steal_encoded_buffer(ibuf), + ibuf->encoded_size); imapf = static_cast(MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile")); STRNCPY(imapf->filepath, filepath); diff --git a/source/blender/blenkernel/intern/packedFile.cc b/source/blender/blenkernel/intern/packedFile.cc index 90c4a2c2140..f1a49e4c80f 100644 --- a/source/blender/blenkernel/intern/packedFile.cc +++ b/source/blender/blenkernel/intern/packedFile.cc @@ -87,7 +87,7 @@ int BKE_packedfile_read(PackedFile *pf, void *data, int size) } if (size > 0) { - memcpy(data, ((char *)pf->data) + pf->seek, size); + memcpy(data, ((const char *)pf->data) + pf->seek, size); } else { size = 0; @@ -148,8 +148,9 @@ void BKE_packedfile_free(PackedFile *pf) { if (pf) { BLI_assert(pf->data != nullptr); + BLI_assert(pf->sharing_info != nullptr); - MEM_SAFE_FREE(pf->data); + pf->sharing_info->remove_user_and_delete_if_last(); MEM_freeN(pf); } else { @@ -165,7 +166,7 @@ PackedFile *BKE_packedfile_duplicate(const PackedFile *pf_src) PackedFile *pf_dst; pf_dst = static_cast(MEM_dupallocN(pf_src)); - pf_dst->data = MEM_dupallocN(pf_src->data); + pf_dst->sharing_info->add_user(); return pf_dst; } @@ -177,6 +178,7 @@ PackedFile *BKE_packedfile_new_from_memory(void *mem, int memlen) PackedFile *pf = static_cast(MEM_callocN(sizeof(*pf), "PackedFile")); pf->data = mem; pf->size = memlen; + pf->sharing_info = blender::implicit_sharing::info_for_mem_free(mem); return pf; } @@ -891,7 +893,9 @@ void BKE_packedfile_blend_write(BlendWriter *writer, const PackedFile *pf) return; } BLO_write_struct(writer, PackedFile, pf); - BLO_write_raw(writer, pf->size, pf->data); + BLO_write_shared(writer, pf->data, pf->size, pf->sharing_info, [&]() { + BLO_write_raw(writer, pf->size, pf->data); + }); } void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p) @@ -901,8 +905,10 @@ void BKE_packedfile_blend_read(BlendDataReader *reader, PackedFile **pf_p) if (pf == nullptr) { return; } - - BLO_read_data_address(reader, &pf->data); + pf->sharing_info = BLO_read_shared(reader, &pf->data, [&]() { + BLO_read_data_address(reader, &pf->data); + return blender::implicit_sharing::info_for_mem_free(const_cast(pf->data)); + }); if (pf->data == nullptr) { /* We cannot allow a PackedFile with a nullptr data field, * the whole code assumes this is not possible. See #70315. */ diff --git a/source/blender/makesdna/DNA_packedFile_types.h b/source/blender/makesdna/DNA_packedFile_types.h index b5730d51698..cb9ca36dd34 100644 --- a/source/blender/makesdna/DNA_packedFile_types.h +++ b/source/blender/makesdna/DNA_packedFile_types.h @@ -8,8 +8,16 @@ #pragma once +#include "BLI_implicit_sharing.h" + typedef struct PackedFile { int size; int seek; - void *data; + /** + * Raw data from the shared file. This data is const because it uses implicit sharing and may be + * shared with e.g. the undo system. + */ + const void *data; + /** Sharing info corresponding to the data above. This is run-time data. */ + const ImplicitSharingInfoHandle *sharing_info; } PackedFile;