PostIndexDocumentBenchmark.vala 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /**
  2. * PostIndexDocumentBenchmark - Benchmarks for Document operations with indexes present
  3. *
  4. * Measures performance of document creation, reading, and updating
  5. * when indexes, categories, and catalogues are present. This is slower
  6. * due to hooks being triggered on document operations.
  7. *
  8. * @version 0.2
  9. * @since 0.1
  10. */
  11. namespace Implexus.Tools.Perf {
  12. /**
  13. * Benchmark for Document entity operations with indexes present.
  14. *
  15. * This benchmark runs after the Index, Category, and Catalogue benchmarks
  16. * to measure the performance impact of having indexed entities present.
  17. *
  18. * Tests:
  19. * - create_document_small_indexed: Creating documents with few properties (with indexes)
  20. * - create_document_large_indexed: Creating documents with many properties (with indexes)
  21. * - get_document_indexed: Reading document properties (with indexes)
  22. * - update_document_indexed: Modifying document properties (with indexes)
  23. * - get_property_indexed: Getting a single property (with indexes)
  24. * - delete_document_indexed: Deleting documents (with indexes)
  25. */
  26. public class PostIndexDocumentBenchmark : Benchmark {
  27. /**
  28. * {@inheritDoc}
  29. */
  30. public override string name { get { return "PostIndexDocument"; } }
  31. /**
  32. * Creates a new PostIndexDocumentBenchmark.
  33. *
  34. * @param engine The engine to benchmark
  35. * @param config The benchmark configuration
  36. */
  37. public PostIndexDocumentBenchmark(Core.Engine engine, BenchmarkConfig config) {
  38. base(engine, config);
  39. }
  40. /**
  41. * {@inheritDoc}
  42. */
  43. public override async void run_async(Results results) throws Error {
  44. // Create parent container for post-index documents
  45. var parent_path = new Core.EntityPath("/perf-test/post-index-docs");
  46. yield ensure_container_async(new Core.EntityPath("/perf-test"), "perf-test");
  47. // Note: /perf-test is already tracked by previous benchmarks
  48. yield cleanup_path_async(parent_path);
  49. var root = yield _engine.get_root_async();
  50. var perf_test = yield root.get_child_async("perf-test");
  51. var parent_container = yield perf_test.create_container_async("post-index-docs");
  52. _cleanup_tracker.add_container(parent_path.to_string());
  53. int iterations = _config.iterations;
  54. int heavy_iterations = _config.heavy_iterations;
  55. // Test 1: Create documents with small properties (with indexes present)
  56. print(" Testing create_document_small_indexed (%d iterations)...\n", iterations);
  57. var create_small_op = new CreateSmallIndexedDocOp(this, parent_container, parent_path);
  58. var create_small = yield measure_async("create_document_small_indexed", iterations, create_small_op);
  59. results.add(name, create_small);
  60. // Test 2: Create documents with large properties (with indexes present)
  61. print(" Testing create_document_large_indexed (%d iterations)...\n", heavy_iterations);
  62. var create_large_op = new CreateLargeIndexedDocOp(this, parent_container, parent_path);
  63. var create_large = yield measure_async("create_document_large_indexed", heavy_iterations, create_large_op);
  64. results.add(name, create_large);
  65. // Test 3: Read documents (small, with indexes present)
  66. print(" Testing get_document_indexed (%d iterations)...\n", iterations);
  67. var read_op = new GetIndexedDocumentOp(_engine, parent_path, iterations);
  68. var read_result = yield measure_async("get_document_indexed", iterations, read_op);
  69. results.add(name, read_result);
  70. // Test 4: Update documents (with indexes present)
  71. print(" Testing update_document_indexed (%d iterations)...\n", iterations);
  72. var update_op = new UpdateIndexedDocumentOp(_engine, parent_path, iterations);
  73. var update_result = yield measure_async("update_document_indexed", iterations, update_op);
  74. results.add(name, update_result);
  75. // Test 5: Get property by name (with indexes present)
  76. print(" Testing get_property_indexed (%d iterations)...\n", iterations);
  77. var get_prop_op = new GetIndexedPropertyOp(_engine, parent_path, iterations);
  78. var get_prop_result = yield measure_async("get_property_indexed", iterations, get_prop_op);
  79. results.add(name, get_prop_result);
  80. // Test 6: Delete documents (with indexes present)
  81. print(" Testing delete_document_indexed (%d iterations)...\n", iterations);
  82. var delete_op = new DeleteIndexedDocumentOp(_engine, parent_path);
  83. var delete_result = yield measure_async("delete_document_indexed", iterations, delete_op);
  84. results.add(name, delete_result);
  85. }
  86. }
  87. // Operation classes for PostIndexDocumentBenchmark
  88. private class CreateSmallIndexedDocOp : AsyncOperation {
  89. private PostIndexDocumentBenchmark _benchmark;
  90. private Core.Entity _parent_container;
  91. private Core.EntityPath _parent_path;
  92. public CreateSmallIndexedDocOp(PostIndexDocumentBenchmark benchmark, Core.Entity parent_container, Core.EntityPath parent_path) {
  93. _benchmark = benchmark;
  94. _parent_container = parent_container;
  95. _parent_path = parent_path;
  96. }
  97. public override async void execute_async() throws Error {
  98. var doc_name = "post-doc-%d".printf(iteration);
  99. var doc_path = _parent_path.append_child(doc_name);
  100. yield _benchmark.cleanup_path_async(doc_path);
  101. var doc = yield _parent_container.create_document_async(doc_name, "User");
  102. yield doc.set_entity_property_async("name", new Invercargill.NativeElement<string>("post-user-%d".printf(iteration)));
  103. yield doc.set_entity_property_async("age", new Invercargill.NativeElement<int>(iteration));
  104. // Track for deferred cleanup
  105. _benchmark._cleanup_tracker.add_document(doc_path.to_string());
  106. }
  107. }
  108. private class CreateLargeIndexedDocOp : AsyncOperation {
  109. private PostIndexDocumentBenchmark _benchmark;
  110. private Core.Entity _parent_container;
  111. private Core.EntityPath _parent_path;
  112. public CreateLargeIndexedDocOp(PostIndexDocumentBenchmark benchmark, Core.Entity parent_container, Core.EntityPath parent_path) {
  113. _benchmark = benchmark;
  114. _parent_container = parent_container;
  115. _parent_path = parent_path;
  116. }
  117. public override async void execute_async() throws Error {
  118. var doc_name = "post-large-doc-%d".printf(iteration);
  119. var doc_path = _parent_path.append_child(doc_name);
  120. yield _benchmark.cleanup_path_async(doc_path);
  121. var doc = yield _parent_container.create_document_async(doc_name, "LargeDocument");
  122. // Add 50 properties
  123. for (int j = 0; j < 50; j++) {
  124. yield doc.set_entity_property_async(
  125. "field_%d".printf(j),
  126. new Invercargill.NativeElement<string>("post-value-%d-%d".printf(iteration, j))
  127. );
  128. }
  129. // Track for deferred cleanup
  130. _benchmark._cleanup_tracker.add_document(doc_path.to_string());
  131. }
  132. }
  133. private class GetIndexedDocumentOp : AsyncOperation {
  134. private Core.Engine _engine;
  135. private Core.EntityPath _parent_path;
  136. private int _iterations;
  137. public GetIndexedDocumentOp(Core.Engine engine, Core.EntityPath parent_path, int iterations) {
  138. _engine = engine;
  139. _parent_path = parent_path;
  140. _iterations = iterations;
  141. }
  142. public override async void execute_async() throws Error {
  143. var doc_name = "post-doc-%d".printf(iteration % _iterations);
  144. var path = _parent_path.append_child(doc_name);
  145. var entity = yield _engine.get_entity_or_null_async(path);
  146. if (entity != null) {
  147. // Access properties to force load
  148. var props = yield ((!) entity).get_properties_async();
  149. var name_prop = props.get("name");
  150. }
  151. }
  152. }
  153. private class UpdateIndexedDocumentOp : AsyncOperation {
  154. private Core.Engine _engine;
  155. private Core.EntityPath _parent_path;
  156. private int _iterations;
  157. public UpdateIndexedDocumentOp(Core.Engine engine, Core.EntityPath parent_path, int iterations) {
  158. _engine = engine;
  159. _parent_path = parent_path;
  160. _iterations = iterations;
  161. }
  162. public override async void execute_async() throws Error {
  163. var doc_name = "post-doc-%d".printf(iteration % _iterations);
  164. var path = _parent_path.append_child(doc_name);
  165. var entity = yield _engine.get_entity_or_null_async(path);
  166. if (entity != null) {
  167. yield ((!) entity).set_entity_property_async(
  168. "updated",
  169. new Invercargill.NativeElement<bool?>(true)
  170. );
  171. }
  172. }
  173. }
  174. private class GetIndexedPropertyOp : AsyncOperation {
  175. private Core.Engine _engine;
  176. private Core.EntityPath _parent_path;
  177. private int _iterations;
  178. public GetIndexedPropertyOp(Core.Engine engine, Core.EntityPath parent_path, int iterations) {
  179. _engine = engine;
  180. _parent_path = parent_path;
  181. _iterations = iterations;
  182. }
  183. public override async void execute_async() throws Error {
  184. var doc_name = "post-doc-%d".printf(iteration % _iterations);
  185. var path = _parent_path.append_child(doc_name);
  186. var entity = yield _engine.get_entity_or_null_async(path);
  187. if (entity != null) {
  188. var prop = yield ((!) entity).get_entity_property_async("name");
  189. }
  190. }
  191. }
  192. private class DeleteIndexedDocumentOp : AsyncOperation {
  193. private Core.Engine _engine;
  194. private Core.EntityPath _parent_path;
  195. public DeleteIndexedDocumentOp(Core.Engine engine, Core.EntityPath parent_path) {
  196. _engine = engine;
  197. _parent_path = parent_path;
  198. }
  199. public override async void execute_async() throws Error {
  200. var doc_name = "post-doc-%d".printf(iteration);
  201. var path = _parent_path.append_child(doc_name);
  202. var entity = yield _engine.get_entity_or_null_async(path);
  203. if (entity != null) {
  204. yield ((!) entity).delete_async();
  205. }
  206. }
  207. }
  208. }