| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- /**
- * IndexBenchmark - Benchmarks for Index entity operations
- *
- * Measures performance of text index creation and search operations
- * using n-gram based full-text search.
- *
- * @version 0.1
- * @since 0.1
- */
- namespace Implexus.Tools.Perf {
- /**
- * Benchmark for Index entity operations.
- *
- * Tests:
- * - create_index: Creating text indices
- * - search_contains: Searching with contains pattern
- * - search_prefix: Prefix-based searches
- * - search_suffix: Suffix-based searches
- * - search_exact: Exact match searches
- * - search_rare_term: Searching for rare terms
- * - create_index_title: Creating indices on title field
- * - search_title: Searching on title index
- */
- public class IndexBenchmark : Benchmark {
-
- /**
- * {@inheritDoc}
- */
- public override string name { get { return "Index"; } }
-
- /**
- * Creates a new IndexBenchmark.
- *
- * @param engine The engine to benchmark
- * @param config The benchmark configuration
- */
- public IndexBenchmark(Core.Engine engine, BenchmarkConfig config) {
- base(engine, config);
- }
-
- /**
- * {@inheritDoc}
- */
- public override async void run_async(Results results) throws Error {
- // Setup: Create test documents with text content
- var parent_path = new Core.EntityPath("/perf-test/indices");
- 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("indices");
- _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;
-
- // Sample texts for indexing
- string[] sample_texts = {
- "The quick brown fox jumps over the lazy dog",
- "A journey of a thousand miles begins with a single step",
- "To be or not to be that is the question",
- "All that glitters is not gold",
- "The only thing we have to fear is fear itself",
- "Ask not what your country can do for you",
- "I have a dream that one day this nation will rise up",
- "In the beginning was the Word and the Word was with God",
- "It was the best of times it was the worst of times",
- "Call me Ishmael Some years ago never mind how long precisely"
- };
-
- // Create test documents with text content
- print(" Setting up test documents (%d documents)...\n", test_doc_count);
- for (int i = 0; i < test_doc_count; i++) {
- var doc_name = "doc-%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, "TextDoc");
- yield doc.set_entity_property_async(
- "content",
- new Invercargill.NativeElement<string>(sample_texts[i % sample_texts.length])
- );
- yield doc.set_entity_property_async(
- "title",
- new Invercargill.NativeElement<string>("Document %d".printf(i))
- );
- // Track for deferred cleanup
- _cleanup_tracker.add_document(doc_path.to_string());
- }
-
- // Test 1: Create index on content field
- var index_path = parent_path.append_child("content-index");
- print(" Testing create_index (%d iterations)...\n", quick_iterations);
- var create_op = new CreateIndexOp(this, parent_container, index_path, "content-index", "TextDoc", "content");
- var create_result = yield measure_async("create_index", quick_iterations, create_op);
- results.add(name, create_result);
-
- // Get the index entity for search tests
- Core.Entity? idx_entity = yield _engine.get_entity_or_null_async(index_path);
- var index_entity = idx_entity as Entities.Index;
-
- // Test 2: Search with single term (contains)
- print(" Testing search_contains (%d iterations)...\n", iterations);
- var contains_op = new SearchOp(index_entity, "*the*");
- var contains_result = yield measure_async("search_contains", iterations, contains_op);
- results.add(name, contains_result);
-
- // Test 3: Search with prefix pattern
- print(" Testing search_prefix (%d iterations)...\n", iterations);
- var prefix_op = new SearchOp(index_entity, "the*");
- var prefix_result = yield measure_async("search_prefix", iterations, prefix_op);
- results.add(name, prefix_result);
-
- // Test 4: Search with suffix pattern
- print(" Testing search_suffix (%d iterations)...\n", iterations);
- var suffix_op = new SearchOp(index_entity, "*ing");
- var suffix_result = yield measure_async("search_suffix", iterations, suffix_op);
- results.add(name, suffix_result);
-
- // Test 5: Exact match search
- print(" Testing search_exact (%d iterations)...\n", iterations);
- var exact_op = new SearchOp(index_entity, "dog");
- var exact_result = yield measure_async("search_exact", iterations, exact_op);
- results.add(name, exact_result);
-
- // Test 6: Search for rare term
- print(" Testing search_rare_term (%d iterations)...\n", iterations);
- var rare_op = new SearchOp(index_entity, "*Ishmael*");
- var rare_result = yield measure_async("search_rare_term", iterations, rare_op);
- results.add(name, rare_result);
-
- // Test 7: Create index on title field
- var title_index_path = parent_path.append_child("title-index");
- print(" Testing create_index_title (%d iterations)...\n", quick_iterations);
- var title_create_op = new CreateIndexOp(this, parent_container, title_index_path, "title-index", "TextDoc", "title");
- var title_create_result = yield measure_async("create_index_title", quick_iterations, title_create_op);
- results.add(name, title_create_result);
-
- // Test 8: Search on title index
- Core.Entity? title_idx_entity = yield _engine.get_entity_or_null_async(title_index_path);
- var title_index = title_idx_entity as Entities.Index;
- print(" Testing search_title (%d iterations)...\n", iterations);
- var title_search_op = new SearchOp(title_index, "*Document*");
- var title_search_result = yield measure_async("search_title", iterations, title_search_op);
- results.add(name, title_search_result);
- }
- }
- // Operation classes for IndexBenchmark
- private class CreateIndexOp : AsyncOperation {
- private IndexBenchmark _benchmark;
- private Core.Entity _parent_container;
- private Core.EntityPath _index_path;
- private string _name;
- private string _entity_type;
- private string _field_name;
-
- public CreateIndexOp(IndexBenchmark benchmark, Core.Entity parent_container, Core.EntityPath index_path, string name, string entity_type, string field_name) {
- _benchmark = benchmark;
- _parent_container = parent_container;
- _index_path = index_path;
- _name = name;
- _entity_type = entity_type;
- _field_name = field_name;
- }
-
- public override async void execute_async() throws Error {
- yield _benchmark.cleanup_path_async(_index_path);
- yield _parent_container.create_index_async(_name, _entity_type, _field_name);
- // Track for deferred cleanup
- _benchmark._cleanup_tracker.add_index(_index_path.to_string());
- }
- }
- private class SearchOp : AsyncOperation {
- private Entities.Index? _index_entity;
- private string _pattern;
-
- public SearchOp(Entities.Index? index_entity, string pattern) {
- _index_entity = index_entity;
- _pattern = pattern;
- }
-
- public override async void execute_async() throws Error {
- if (_index_entity != null) {
- // search is synchronous (runs in DBM thread context)
- var search_result = ((!) _index_entity).search(_pattern);
- if (search_result != null) {
- var children = yield ((!) search_result).get_children_async();
- int count = 0;
- foreach (var doc in children) {
- count++;
- }
- }
- }
- }
- }
- }
|