tests: Add basic performance test for bpy/RNA API.

These tests check performances of ID python wrapper creation (these are
cached), regular RNA struct wrapper creation, acess to IDProperties,
(un)registering of py-defined PropertyGroup, and access to py-defined
properties (without and without custom get/set).

The goal of these tests is mainly to follow performances impact of
on-going refactors and improvements in the BPY/RNA area.
This commit is contained in:
Bastien Montagne
2025-08-05 10:37:09 +02:00
parent 9d039ef29e
commit d3f6523536

View File

@@ -0,0 +1,140 @@
# SPDX-FileCopyrightText: 2021-2022 Blender Authors
#
# SPDX-License-Identifier: Apache-2.0
import api
def _run_id_instance_access(args):
import bpy
import time
iterations = args["iterations"]
start_time = time.time()
for i in range(iterations):
bpy.data.scenes[0]
elapsed_time = time.time() - start_time
result = {'time': elapsed_time}
return result
def _run_static_subdata_instance_access(args):
import bpy
import time
iterations = args["iterations"]
start_time = time.time()
sce = bpy.data.scenes[0]
for i in range(iterations):
sce.render
elapsed_time = time.time() - start_time
result = {'time': elapsed_time}
return result
def _run_idproperty_access(args):
import bpy
import time
iterations = args["iterations"]
start_time = time.time()
sce = bpy.data.scenes[0]
sce["test"] = 3.14
for i in range(iterations):
sce["test"] += 0.001
elapsed_time = time.time() - start_time
result = {'time': elapsed_time}
return result
def _run_runtime_group_register_access(args):
import bpy
import time
iterations = args["iterations"]
do_register = args.get("do_register", False)
do_access = args.get("do_access", False)
do_get_set = args.get("do_get_set", False)
if do_get_set:
class DummyGroup(bpy.types.PropertyGroup):
dummy_prop : bpy.props.IntProperty(
get=lambda self: self.bl_system_properties_get()["dummy_prop"],
set=lambda self, val: self.bl_system_properties_get().set("dummy_prop", val),
)
else:
class DummyGroup(bpy.types.PropertyGroup):
dummy_prop : bpy.props.IntProperty()
start_time = time.time()
sce = bpy.data.scenes[0]
# Test Registration & Unregistration.
if do_register:
for i in range(iterations):
bpy.utils.register_class(DummyGroup)
bpy.types.Scene.dummy_group = bpy.props.PointerProperty(type=DummyGroup)
del bpy.types.Scene.dummy_group
bpy.utils.unregister_class(DummyGroup)
if do_access:
bpy.utils.register_class(DummyGroup)
bpy.types.Scene.dummy_group = bpy.props.PointerProperty(type=DummyGroup)
for i in range(iterations):
sce.dummy_group.dummy_prop += 1
del bpy.types.Scene.dummy_group
bpy.utils.unregister_class(DummyGroup)
elapsed_time = time.time() - start_time
result = {'time': elapsed_time}
return result
class BPYRNATest(api.Test):
def __init__(self, name, callback, iterations, args={}):
self.name_ = name
self.callback = callback
self.iterations = iterations
self.args = args
def name(self):
return f"{self.name_} ({int(self.iterations / 1000)}k)"
def category(self):
return "bpy_rna"
def run(self, env, device_id):
args = self.args
args["iterations"] = self.iterations
result, _ = env.run_in_blender(self.callback, args, ["--factory-startup"])
return result
def generate(env):
return [
BPYRNATest("ID Instance Access", _run_id_instance_access, 10000 * 1000),
BPYRNATest("Static RNA Stuct Instance Access", _run_static_subdata_instance_access, 10000 * 1000),
BPYRNATest("IDProperty Access", _run_idproperty_access, 10000 * 1000),
BPYRNATest("Py-Defined Struct Register", _run_runtime_group_register_access, 100 * 1000, {"do_register": True}),
BPYRNATest("Py-Defined Property Access", _run_runtime_group_register_access, 10000 * 1000, {"do_access": True}),
BPYRNATest("Py-Defined Property Custom Get/Set Access", _run_runtime_group_register_access, 10 * 1000,
{"do_access": True, "do_get_set": True}),
]