Bonsai - cache get_user and get_application for a speed-up

This commit is contained in:
Andrej730
2025-06-17 18:31:11 +05:00
parent 71d469a271
commit 21f5363c74
+42 -2
View File
@@ -24,6 +24,7 @@ import ifcopenshell.util.unit
import ifcopenshell.api.owner.settings import ifcopenshell.api.owner.settings
import bonsai.bim import bonsai.bim
import bonsai.tool as tool import bonsai.tool as tool
import weakref
from bpy.app.handlers import persistent from bpy.app.handlers import persistent
from bonsai.bim.ifc import IfcStore from bonsai.bim.ifc import IfcStore
from bonsai.bim.module.model.data import AuthoringData from bonsai.bim.module.model.data import AuthoringData
@@ -257,24 +258,61 @@ def redo_post(scene: bpy.types.Scene) -> None:
tool.Ifc.rebuild_element_maps() tool.Ifc.rebuild_element_maps()
# Cache is important as those entities will be retrieved very often,
# for every IfcOwnerHistory creation or update.
class SettingsCache:
APPLICATION_ID: Union[int, None] = None
USER_ID: Union[int, None] = None
_file: Union[weakref.ReferenceType[ifcopenshell.file], None] = None
@classmethod
def get_file(cls) -> Union[ifcopenshell.file, None]:
if cls._file is None:
return None
return cls._file()
@classmethod
def set_file(cls, file: ifcopenshell.file) -> None:
cls._file = weakref.ref(file)
def get_application(ifc: ifcopenshell.file) -> ifcopenshell.entity_instance: def get_application(ifc: ifcopenshell.file) -> ifcopenshell.entity_instance:
# TODO: cache this for even faster application retrieval. It honestly makes a difference on long scripts. if SettingsCache.get_file() is ifc and SettingsCache.APPLICATION_ID is not None:
try:
app = ifc.by_id(SettingsCache.APPLICATION_ID)
return app
except RuntimeError:
pass
# Use only main part from the version to avoid flooding advanced users projects with IfcApplications. # Use only main part from the version to avoid flooding advanced users projects with IfcApplications.
version = tool.Blender.get_bonsai_version().split("-")[0] version = tool.Blender.get_bonsai_version().split("-")[0]
for element in ifc.by_type("IfcApplication"): for element in ifc.by_type("IfcApplication"):
if element.ApplicationIdentifier == "Bonsai" and element.Version == version: if element.ApplicationIdentifier == "Bonsai" and element.Version == version:
return element return element
return ifcopenshell.api.owner.add_application( application = ifcopenshell.api.owner.add_application(
ifc, ifc,
version=version, version=version,
application_full_name="Bonsai", application_full_name="Bonsai",
application_identifier="Bonsai", application_identifier="Bonsai",
) )
SettingsCache.APPLICATION_ID = application.id()
SettingsCache.set_file(ifc)
return application
def get_user(ifc: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None]: def get_user(ifc: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None]:
# TODO: cache this for even faster application retrieval. It honestly makes a difference on long scripts. # TODO: cache this for even faster application retrieval. It honestly makes a difference on long scripts.
if SettingsCache.get_file() is ifc and SettingsCache.USER_ID is not None:
try:
user = ifc.by_id(SettingsCache.USER_ID)
return user
except RuntimeError:
pass
if pao := next(iter(ifc.by_type("IfcPersonAndOrganization")), None): if pao := next(iter(ifc.by_type("IfcPersonAndOrganization")), None):
SettingsCache.USER_ID = pao.id()
SettingsCache.set_file(ifc)
return pao return pao
elif ifc.schema == "IFC2X3": elif ifc.schema == "IFC2X3":
if (person := next(iter(ifc.by_type("IfcPerson")), None)) is None: if (person := next(iter(ifc.by_type("IfcPerson")), None)) is None:
@@ -282,6 +320,8 @@ def get_user(ifc: ifcopenshell.file) -> Union[ifcopenshell.entity_instance, None
if (organization := next(iter(ifc.by_type("IfcOrganization")), None)) is None: if (organization := next(iter(ifc.by_type("IfcOrganization")), None)) is None:
organization = ifcopenshell.api.owner.add_organisation(ifc) organization = ifcopenshell.api.owner.add_organisation(ifc)
pao = ifcopenshell.api.owner.add_person_and_organisation(ifc, person=person, organisation=organization) pao = ifcopenshell.api.owner.add_person_and_organisation(ifc, person=person, organisation=organization)
SettingsCache.USER_ID = pao.id()
SettingsCache.set_file(ifc)
return pao return pao