/** * CategoryBenchmark - Benchmarks for Category entity operations * * Measures performance of category creation, member enumeration, * and predicate evaluation. * * @version 0.1 * @since 0.1 */ namespace Implexus.Tools.Perf { /** * Benchmark for Category entity operations. * * Tests: * - create_category: Creating categories with predicates * - get_members: Enumerating category members * - predicate_evaluation: Testing predicate matching performance * - create_category_complex: Creating categories with complex predicates * - create_category_bool: Creating categories with boolean predicates * - contains_document: Checking document membership */ public class CategoryBenchmark : Benchmark { /** * {@inheritDoc} */ public override string name { get { return "Category"; } } /** * Creates a new CategoryBenchmark. * * @param engine The engine to benchmark * @param config The benchmark configuration */ public CategoryBenchmark(Core.Engine engine, BenchmarkConfig config) { base(engine, config); } /** * {@inheritDoc} */ public override async void run_async(Results results) throws Error { // Setup: Create test documents var parent_path = new Core.EntityPath("/perf-test/categories"); yield ensure_container_async(new Core.EntityPath("/perf-test"), "perf-test"); _cleanup_tracker.add_container(new Core.EntityPath("/perf-test").to_string()); yield cleanup_path_async(parent_path); var root = yield _engine.get_root_async(); var perf_test = yield root.get_child_async("perf-test"); var parent_container = yield perf_test.create_container_async("categories"); _cleanup_tracker.add_container(parent_path.to_string()); int test_doc_count = _config.test_doc_count; int quick_iterations = _config.quick_iterations; int iterations = _config.iterations; // Create test documents with category property print(" Setting up test documents (%d documents)...\n", test_doc_count); for (int i = 0; i < test_doc_count; i++) { var doc_name = "item-%d".printf(i); var doc_path = parent_path.append_child(doc_name); yield cleanup_path_async(doc_path); var doc = yield parent_container.create_document_async(doc_name, "TestItem"); yield doc.set_entity_property_async( "category", new Invercargill.NativeElement(i % 5 == 0 ? "A" : "B") ); yield doc.set_entity_property_async( "priority", new Invercargill.NativeElement(i % 10) ); yield doc.set_entity_property_async( "active", new Invercargill.NativeElement(i % 2 == 0) ); // Track for deferred cleanup _cleanup_tracker.add_document(doc_path.to_string()); } // Test 1: Create category with simple predicate var category_path = parent_path.append_child("category-a"); print(" Testing create_category (%d iterations)...\n", quick_iterations); var create_op = new CreateCategoryOp(this, parent_container, category_path, "category-a", "TestItem", "category == \"A\""); var create_result = yield measure_async("create_category", quick_iterations, create_op); results.add(name, create_result); // Test 2: Get category members print(" Testing get_members (%d iterations)...\n", iterations); var get_op = new GetCategoryMembersOp(_engine, category_path); var get_result = yield measure_async("get_members", iterations, get_op); results.add(name, get_result); // Test 3: Create category with complex predicate var complex_category_path = parent_path.append_child("complex-category"); print(" Testing create_category_complex (%d iterations)...\n", quick_iterations); var complex_create_op = new CreateCategoryOp(this, parent_container, complex_category_path, "complex-category", "TestItem", "category == \"A\" && priority > 5"); var complex_create_result = yield measure_async("create_category_complex", quick_iterations, complex_create_op); results.add(name, complex_create_result); // Test 4: Get members from complex category print(" Testing get_members_complex (%d iterations)...\n", iterations); var complex_get_op = new GetCategoryMembersOp(_engine, complex_category_path); var complex_get_result = yield measure_async("get_members_complex", iterations, complex_get_op); results.add(name, complex_get_result); // Test 5: Create category with boolean predicate var bool_category_path = parent_path.append_child("active-category"); print(" Testing create_category_bool (%d iterations)...\n", quick_iterations); var bool_create_op = new CreateCategoryOp(this, parent_container, bool_category_path, "active-category", "TestItem", "active"); var bool_create_result = yield measure_async("create_category_bool", quick_iterations, bool_create_op); results.add(name, bool_create_result); // Test 6: Check membership print(" Testing contains_document (%d iterations)...\n", iterations); Core.Entity? cat_entity = yield _engine.get_entity_or_null_async(category_path); var category_entity = cat_entity as Entities.Category; var contains_op = new ContainsDocumentOp(category_entity, parent_path, test_doc_count); var contains_result = yield measure_async("contains_document", iterations, contains_op); results.add(name, contains_result); } } // Operation classes for CategoryBenchmark private class CreateCategoryOp : AsyncOperation { private CategoryBenchmark _benchmark; private Core.Entity _parent_container; private Core.EntityPath _category_path; private string _name; private string _entity_type; private string _predicate; public CreateCategoryOp(CategoryBenchmark benchmark, Core.Entity parent_container, Core.EntityPath category_path, string name, string entity_type, string predicate) { _benchmark = benchmark; _parent_container = parent_container; _category_path = category_path; _name = name; _entity_type = entity_type; _predicate = predicate; } public override async void execute_async() throws Error { yield _benchmark.cleanup_path_async(_category_path); yield _parent_container.create_category_async(_name, _entity_type, _predicate); // Track for deferred cleanup _benchmark._cleanup_tracker.add_category(_category_path.to_string()); } } private class GetCategoryMembersOp : AsyncOperation { private Core.Engine _engine; private Core.EntityPath _category_path; public GetCategoryMembersOp(Core.Engine engine, Core.EntityPath category_path) { _engine = engine; _category_path = category_path; } public override async void execute_async() throws Error { var entity = yield _engine.get_entity_or_null_async(_category_path); if (entity != null) { var children = yield ((!) entity).get_children_async(); // Force enumeration int count = 0; foreach (var child in children) { count++; } } } } private class ContainsDocumentOp : AsyncOperation { private Entities.Category? _category_entity; private Core.EntityPath _parent_path; private int _test_doc_count; public ContainsDocumentOp(Entities.Category? category_entity, Core.EntityPath parent_path, int test_doc_count) { _category_entity = category_entity; _parent_path = parent_path; _test_doc_count = test_doc_count; } public override async void execute_async() throws Error { if (_category_entity != null) { var test_path = _parent_path.append_child("item-%d".printf(iteration % _test_doc_count)); // contains_document is synchronous (runs in DBM thread context) ((!) _category_entity).contains_document(test_path.to_string()); } } } }