CatalogueBenchmark.vala 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /**
  2. * CatalogueBenchmark - Benchmarks for Catalogue entity operations
  3. *
  4. * Measures performance of catalogue creation, key enumeration,
  5. * and group retrieval operations.
  6. *
  7. * @version 0.1
  8. * @since 0.1
  9. */
  10. namespace Implexus.Tools.Perf {
  11. /**
  12. * Benchmark for Catalogue entity operations.
  13. *
  14. * Tests:
  15. * - create_catalogue: Creating catalogues with key expressions
  16. * - get_keys: Enumerating catalogue keys
  17. * - get_group: Retrieving documents in a specific group
  18. * - get_group_documents: Full enumeration of group members
  19. * - create_catalogue_numeric: Creating catalogues with numeric keys
  20. * - get_all_groups: Getting all groups from a catalogue
  21. * - create_catalogue_multifield: Creating catalogues with different fields
  22. */
  23. public class CatalogueBenchmark : Benchmark {
  24. /**
  25. * {@inheritDoc}
  26. */
  27. public override string name { get { return "Catalogue"; } }
  28. /**
  29. * Creates a new CatalogueBenchmark.
  30. *
  31. * @param engine The engine to benchmark
  32. * @param config The benchmark configuration
  33. */
  34. public CatalogueBenchmark(Core.Engine engine, BenchmarkConfig config) {
  35. base(engine, config);
  36. }
  37. /**
  38. * {@inheritDoc}
  39. */
  40. public override async void run_async(Results results) throws Error {
  41. // Setup: Create test documents with varying key values
  42. var parent_path = new Core.EntityPath("/perf-test/catalogues");
  43. yield ensure_container_async(new Core.EntityPath("/perf-test"), "perf-test");
  44. _cleanup_tracker.add_container(new Core.EntityPath("/perf-test").to_string());
  45. yield cleanup_path_async(parent_path);
  46. var root = yield _engine.get_root_async();
  47. var perf_test = yield root.get_child_async("perf-test");
  48. var parent_container = yield perf_test.create_container_async("catalogues");
  49. _cleanup_tracker.add_container(parent_path.to_string());
  50. int test_doc_count = _config.test_doc_count;
  51. int quick_iterations = _config.quick_iterations;
  52. int iterations = _config.iterations;
  53. // Create test documents with status property
  54. print(" Setting up test documents (%d documents)...\n", test_doc_count);
  55. string[] statuses = { "active", "inactive", "pending", "archived" };
  56. for (int i = 0; i < test_doc_count; i++) {
  57. var doc_name = "item-%d".printf(i);
  58. var doc_path = parent_path.append_child(doc_name);
  59. yield cleanup_path_async(doc_path);
  60. var doc = yield parent_container.create_document_async(doc_name, "StatusItem");
  61. yield doc.set_entity_property_async(
  62. "status",
  63. new Invercargill.NativeElement<string>(statuses[i % statuses.length])
  64. );
  65. yield doc.set_entity_property_async(
  66. "priority",
  67. new Invercargill.NativeElement<int>(i % 5)
  68. );
  69. yield doc.set_entity_property_async(
  70. "department",
  71. new Invercargill.NativeElement<string>("dept-%d".printf(i % 3))
  72. );
  73. // Track for deferred cleanup
  74. _cleanup_tracker.add_document(doc_path.to_string());
  75. }
  76. // Test 1: Create catalogue with status key
  77. var catalogue_path = parent_path.append_child("by-status");
  78. print(" Testing create_catalogue (%d iterations)...\n", quick_iterations);
  79. var create_op = new CreateCatalogueOp(this, parent_container, catalogue_path, "by-status", "StatusItem", "status");
  80. var create_result = yield measure_async("create_catalogue", quick_iterations, create_op);
  81. results.add(name, create_result);
  82. // Test 2: Get catalogue keys
  83. print(" Testing get_keys (%d iterations)...\n", iterations);
  84. Core.Entity? cat_entity = yield _engine.get_entity_or_null_async(catalogue_path);
  85. var catalogue_entity = cat_entity as Entities.Catalogue;
  86. var keys_op = new GetKeysOp(catalogue_entity);
  87. var keys_result = yield measure_async("get_keys", iterations, keys_op);
  88. results.add(name, keys_result);
  89. // Test 3: Get group by key
  90. print(" Testing get_group (%d iterations)...\n", iterations);
  91. var group_op = new GetGroupOp(catalogue_entity, "active");
  92. var group_result = yield measure_async("get_group", iterations, group_op);
  93. results.add(name, group_result);
  94. // Test 4: Get group documents
  95. print(" Testing get_group_documents (%d iterations)...\n", iterations);
  96. var group_docs_op = new GetGroupDocumentsOp(catalogue_entity, "active");
  97. var group_docs_result = yield measure_async("get_group_documents", iterations, group_docs_op);
  98. results.add(name, group_docs_result);
  99. // Test 5: Create catalogue with numeric key
  100. var priority_catalogue_path = parent_path.append_child("by-priority");
  101. print(" Testing create_catalogue_numeric (%d iterations)...\n", quick_iterations);
  102. var priority_create_op = new CreateCatalogueOp(this, parent_container, priority_catalogue_path, "by-priority", "StatusItem", "priority");
  103. var priority_create_result = yield measure_async("create_catalogue_numeric", quick_iterations, priority_create_op);
  104. results.add(name, priority_create_result);
  105. // Test 6: Get all groups from numeric catalogue
  106. print(" Testing get_all_groups (%d iterations)...\n", quick_iterations);
  107. Core.Entity? prio_cat_entity = yield _engine.get_entity_or_null_async(priority_catalogue_path);
  108. var priority_catalogue = prio_cat_entity as Entities.Catalogue;
  109. var all_groups_op = new GetAllGroupsOp(priority_catalogue);
  110. var all_groups_result = yield measure_async("get_all_groups", quick_iterations, all_groups_op);
  111. results.add(name, all_groups_result);
  112. // Test 7: Create multi-field catalogue
  113. var dept_catalogue_path = parent_path.append_child("by-department");
  114. print(" Testing create_catalogue_multifield (%d iterations)...\n", quick_iterations);
  115. var dept_create_op = new CreateCatalogueOp(this, parent_container, dept_catalogue_path, "by-department", "StatusItem", "department");
  116. var dept_create_result = yield measure_async("create_catalogue_multifield", quick_iterations, dept_create_op);
  117. results.add(name, dept_create_result);
  118. }
  119. }
  120. // Operation classes for CatalogueBenchmark
  121. private class CreateCatalogueOp : AsyncOperation {
  122. private CatalogueBenchmark _benchmark;
  123. private Core.Entity _parent_container;
  124. private Core.EntityPath _catalogue_path;
  125. private string _name;
  126. private string _entity_type;
  127. private string _key_expression;
  128. public CreateCatalogueOp(CatalogueBenchmark benchmark, Core.Entity parent_container, Core.EntityPath catalogue_path, string name, string entity_type, string key_expression) {
  129. _benchmark = benchmark;
  130. _parent_container = parent_container;
  131. _catalogue_path = catalogue_path;
  132. _name = name;
  133. _entity_type = entity_type;
  134. _key_expression = key_expression;
  135. }
  136. public override async void execute_async() throws Error {
  137. yield _benchmark.cleanup_path_async(_catalogue_path);
  138. yield _parent_container.create_catalogue_async(_name, _entity_type, _key_expression);
  139. // Track for deferred cleanup
  140. _benchmark._cleanup_tracker.add_catalogue(_catalogue_path.to_string());
  141. }
  142. }
  143. private class GetKeysOp : AsyncOperation {
  144. private Entities.Catalogue? _catalogue_entity;
  145. public GetKeysOp(Entities.Catalogue? catalogue_entity) {
  146. _catalogue_entity = catalogue_entity;
  147. }
  148. public override async void execute_async() throws Error {
  149. if (_catalogue_entity != null) {
  150. // get_group_keys is synchronous (runs in DBM thread context)
  151. var keys = ((!) _catalogue_entity).get_group_keys();
  152. // Force enumeration
  153. int count = 0;
  154. foreach (var key in keys) {
  155. count++;
  156. }
  157. }
  158. }
  159. }
  160. private class GetGroupOp : AsyncOperation {
  161. private Entities.Catalogue? _catalogue_entity;
  162. private string _group_name;
  163. public GetGroupOp(Entities.Catalogue? catalogue_entity, string group_name) {
  164. _catalogue_entity = catalogue_entity;
  165. _group_name = group_name;
  166. }
  167. public override async void execute_async() throws Error {
  168. if (_catalogue_entity != null) {
  169. var group = yield ((!) _catalogue_entity).get_child_async(_group_name);
  170. }
  171. }
  172. }
  173. private class GetGroupDocumentsOp : AsyncOperation {
  174. private Entities.Catalogue? _catalogue_entity;
  175. private string _group_name;
  176. public GetGroupDocumentsOp(Entities.Catalogue? catalogue_entity, string group_name) {
  177. _catalogue_entity = catalogue_entity;
  178. _group_name = group_name;
  179. }
  180. public override async void execute_async() throws Error {
  181. if (_catalogue_entity != null) {
  182. var docs = yield ((!) _catalogue_entity).get_group_documents_async(_group_name);
  183. // Force enumeration
  184. int count = 0;
  185. foreach (var doc in docs) {
  186. count++;
  187. }
  188. }
  189. }
  190. }
  191. private class GetAllGroupsOp : AsyncOperation {
  192. private Entities.Catalogue? _catalogue;
  193. public GetAllGroupsOp(Entities.Catalogue? catalogue) {
  194. _catalogue = catalogue;
  195. }
  196. public override async void execute_async() throws Error {
  197. if (_catalogue != null) {
  198. var children = yield ((!) _catalogue).get_children_async();
  199. // Force enumeration of all groups
  200. int total_count = 0;
  201. foreach (var group in children) {
  202. var group_children = yield group.get_children_async();
  203. foreach (var doc in group_children) {
  204. total_count++;
  205. }
  206. }
  207. }
  208. }
  209. }
  210. }