Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
test_optimization.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#include <gtest/gtest.h>
9#include <chrono>
10#include <thread>
11#include <vector>
12#include <random>
13#include <functional>
14
15using namespace kcenon::monitoring;
16
20class OptimizationTest : public ::testing::Test {
21protected:
22 void SetUp() override {
23 // Common setup for tests
24 }
25
26 void TearDown() override {
27 // Common cleanup for tests
28 }
29
33 std::vector<double> generate_test_data(size_t size, double min_val = 0.0, double max_val = 100.0) {
34 std::vector<double> data;
35 data.reserve(size);
36
37 std::random_device rd;
38 std::mt19937 gen(rd());
39 std::uniform_real_distribution<double> dist(min_val, max_val);
40
41 for (size_t i = 0; i < size; ++i) {
42 data.push_back(dist(gen));
43 }
44
45 return data;
46 }
47};
48
49// Lock-free Queue Tests
50TEST_F(OptimizationTest, LockfreeQueueBasicOperations) {
52 config.initial_capacity = 16;
53 config.max_capacity = 64;
54
55 lockfree_queue<int> queue(config);
56
57 EXPECT_TRUE(queue.empty());
58 EXPECT_EQ(queue.size(), 0);
59
60 // Push elements
61 for (int i = 0; i < 10; ++i) {
62 auto result = queue.push(i);
63 EXPECT_TRUE(result.is_ok()) << "Failed to push " << i;
64 }
65
66 EXPECT_FALSE(queue.empty());
67 EXPECT_EQ(queue.size(), 10);
68
69 // Pop elements
70 for (int i = 0; i < 10; ++i) {
71 auto result = queue.pop();
72 EXPECT_TRUE(result.is_ok()) << "Failed to pop element " << i;
73 EXPECT_EQ(result.value(), i);
74 }
75
76 EXPECT_TRUE(queue.empty());
77 EXPECT_EQ(queue.size(), 0);
78}
79
80TEST_F(OptimizationTest, LockfreeQueueConcurrentAccess) {
82 config.initial_capacity = 1024;
83 config.max_capacity = 4096;
84
85 lockfree_queue<int> queue(config);
86
87 const int num_producers = 4;
88 const int num_consumers = 2;
89 const int items_per_producer = 1000;
90
91 std::vector<std::thread> producers;
92 std::vector<std::thread> consumers;
93 std::atomic<int> total_consumed{0};
94 std::atomic<bool> producers_done{false};
95
96 // Start producers
97 for (int p = 0; p < num_producers; ++p) {
98 producers.emplace_back([&queue, p]() {
99 for (int i = 0; i < 1000; ++i) {
100 int value = p * 1000 + i;
101 auto result = queue.push(value);
102 while (!result.is_ok() || !result.value()) {
103 std::this_thread::yield();
104 result = queue.push(value);
105 }
106 }
107 });
108 }
109
110 // Start consumers
111 for (int c = 0; c < num_consumers; ++c) {
112 consumers.emplace_back([&queue, &total_consumed, &producers_done]() {
113 while (!producers_done.load() || !queue.empty()) {
114 auto result = queue.pop();
115 if (result.is_ok()) {
116 total_consumed.fetch_add(1);
117 } else {
118 std::this_thread::yield();
119 }
120 }
121 });
122 }
123
124 // Wait for producers
125 for (auto& producer : producers) {
126 producer.join();
127 }
128 producers_done.store(true);
129
130 // Wait for consumers
131 for (auto& consumer : consumers) {
132 consumer.join();
133 }
134
135 EXPECT_EQ(total_consumed.load(), num_producers * items_per_producer);
136 EXPECT_TRUE(queue.empty());
137
138 const auto& stats = queue.get_statistics();
139 // Push success rate should be high since we retry until success
140 // Lower threshold to 30% for CI environments with sanitizer overhead
141 // ThreadSanitizer in particular can significantly slow down atomic
142 // operations, causing more contention, retries, and lower success rates
143 EXPECT_GT(stats.get_push_success_rate(), 30.0);
144 // Pop failures are expected when queue is empty (consumers waiting for data)
145 // so we only check that successful pops equals total consumed
146 EXPECT_EQ(stats.pop_successes.load(), static_cast<size_t>(total_consumed.load()));
147}
148
149// Lock-free Queue: Move Push
150TEST_F(OptimizationTest, LockfreeQueueMovePush) {
152
153 std::string value = "test_value";
154 auto result = queue.push(std::move(value));
155 EXPECT_TRUE(result.is_ok());
156 EXPECT_TRUE(result.value());
157 EXPECT_EQ(queue.size(), 1);
158
159 auto pop_result = queue.pop();
160 EXPECT_TRUE(pop_result.is_ok());
161 EXPECT_EQ(pop_result.value(), "test_value");
162}
163
164// Lock-free Queue: Pop from Empty Queue
165TEST_F(OptimizationTest, LockfreeQueuePopEmpty) {
167 EXPECT_TRUE(queue.empty());
168
169 auto result = queue.pop();
170 EXPECT_TRUE(result.is_err());
171}
172
173// Lock-free Queue: Push when Full
174TEST_F(OptimizationTest, LockfreeQueuePushFull) {
176 config.initial_capacity = 4;
177 config.max_capacity = 4;
178
179 lockfree_queue<int> queue(config);
180
181 // Fill the queue to capacity
182 for (int i = 0; i < 4; ++i) {
183 auto result = queue.push(i);
184 EXPECT_TRUE(result.is_ok());
185 EXPECT_TRUE(result.value());
186 }
187
188 // Next push should return ok(false)
189 auto full_result = queue.push(999);
190 EXPECT_TRUE(full_result.is_ok());
191 EXPECT_FALSE(full_result.value());
192}
193
194// Lock-free Queue: Config Validation All Cases
195TEST_F(OptimizationTest, LockfreeQueueConfigValidationAllCases) {
196 // Valid config
199 valid.max_capacity = 64;
200 EXPECT_TRUE(valid.validate());
201
202 // Zero initial capacity
203 lockfree_queue_config zero_cap;
204 zero_cap.initial_capacity = 0;
205 EXPECT_FALSE(zero_cap.validate());
206
207 // max_capacity < initial_capacity
208 lockfree_queue_config max_less;
209 max_less.initial_capacity = 100;
210 max_less.max_capacity = 50;
211 EXPECT_FALSE(max_less.validate());
212
213 // max_capacity == 0 (unlimited) should be valid
214 lockfree_queue_config unlimited;
215 unlimited.initial_capacity = 16;
216 unlimited.max_capacity = 0;
217 EXPECT_TRUE(unlimited.validate());
218}
219
220// Lock-free Queue: Reset Statistics and Success Rate at Zero Attempts
221TEST_F(OptimizationTest, LockfreeQueueStatisticsReset) {
223
224 queue.push(1);
225 queue.push(2);
226 queue.pop();
227
228 const auto& stats = queue.get_statistics();
229 EXPECT_GT(stats.push_attempts.load(), 0);
230 EXPECT_GT(stats.pop_attempts.load(), 0);
231
232 queue.reset_statistics();
233
234 EXPECT_EQ(stats.push_attempts.load(), 0);
235 EXPECT_EQ(stats.push_successes.load(), 0);
236 EXPECT_EQ(stats.push_failures.load(), 0);
237 EXPECT_EQ(stats.pop_attempts.load(), 0);
238 EXPECT_EQ(stats.pop_successes.load(), 0);
239 EXPECT_EQ(stats.pop_failures.load(), 0);
240
241 // Success rate should be 100.0 when attempts == 0
242 EXPECT_DOUBLE_EQ(stats.get_push_success_rate(), 100.0);
243 EXPECT_DOUBLE_EQ(stats.get_pop_success_rate(), 100.0);
244}
245
246// Lock-free Queue: Move Constructor
247TEST_F(OptimizationTest, LockfreeQueueMoveConstructor) {
249 config.initial_capacity = 16;
250 config.max_capacity = 64;
251
252 lockfree_queue<int> queue1(config);
253 queue1.push(10);
254 queue1.push(20);
255 queue1.push(30);
256
257 // Move constructor
258 lockfree_queue<int> queue2(std::move(queue1));
259 EXPECT_EQ(queue2.size(), 3);
260
261 auto pop_result = queue2.pop();
262 EXPECT_TRUE(pop_result.is_ok());
263 EXPECT_EQ(pop_result.value(), 10);
264
265 pop_result = queue2.pop();
266 EXPECT_TRUE(pop_result.is_ok());
267 EXPECT_EQ(pop_result.value(), 20);
268
269 pop_result = queue2.pop();
270 EXPECT_TRUE(pop_result.is_ok());
271 EXPECT_EQ(pop_result.value(), 30);
272}
273
274// Lock-free Queue: make_lockfree_queue Factory with Config
275TEST_F(OptimizationTest, LockfreeQueueFactoryWithConfig) {
277 config.initial_capacity = 32;
278 config.max_capacity = 128;
279
280 auto queue = make_lockfree_queue<double>(config);
281 EXPECT_NE(queue, nullptr);
282 EXPECT_TRUE(queue->empty());
283 EXPECT_EQ(queue->capacity(), 32);
284}
285
286// Memory Pool Tests
287TEST_F(OptimizationTest, MemoryPoolBasicOperations) {
288 memory_pool_config config;
289 config.initial_blocks = 64;
290 config.max_blocks = 256;
291 config.block_size = 128;
292
293 memory_pool pool(config);
294
295 EXPECT_GT(pool.available_blocks(), 0);
296 EXPECT_EQ(pool.total_blocks(), 64);
297
298 // Allocate memory blocks
299 std::vector<void*> allocated_blocks;
300 for (int i = 0; i < 32; ++i) {
301 auto result = pool.allocate();
302 EXPECT_TRUE(result.is_ok()) << "Failed to allocate block " << i;
303 allocated_blocks.push_back(result.value());
304 }
305
306 EXPECT_EQ(pool.available_blocks(), 32); // 64 - 32 = 32
307
308 // Deallocate blocks
309 for (auto* ptr : allocated_blocks) {
310 auto result = pool.deallocate(ptr);
311 EXPECT_TRUE(result.is_ok());
312 }
313
314 EXPECT_EQ(pool.available_blocks(), 64); // All blocks returned
315
316 const auto& stats = pool.get_statistics();
317 EXPECT_EQ(stats.total_allocations.load(), 32);
318 EXPECT_EQ(stats.total_deallocations.load(), 32);
319 EXPECT_GT(stats.get_allocation_success_rate(), 99.0);
320}
321
322TEST_F(OptimizationTest, MemoryPoolObjectAllocation) {
323 memory_pool_config config;
324 config.initial_blocks = 128;
325 config.block_size = 64; // Enough for test objects
326
327 memory_pool pool(config);
328
329 struct TestObject {
330 int value;
331 double data;
332
333 TestObject(int v, double d) : value(v), data(d) {}
334 };
335
336 // Allocate objects
337 std::vector<TestObject*> objects;
338 for (int i = 0; i < 50; ++i) {
339 auto result = pool.allocate_object<TestObject>(i, i * 0.5);
340 EXPECT_TRUE(result.is_ok()) << "Failed to allocate object " << i;
341
342 auto* obj = result.value();
343 EXPECT_EQ(obj->value, i);
344 EXPECT_DOUBLE_EQ(obj->data, i * 0.5);
345
346 objects.push_back(obj);
347 }
348
349 // Deallocate objects
350 for (auto* obj : objects) {
351 auto result = pool.deallocate_object(obj);
352 EXPECT_TRUE(result.is_ok());
353 }
354}
355
356TEST_F(OptimizationTest, MemoryPoolConcurrentAccess) {
357 memory_pool_config config;
358 config.initial_blocks = 1024;
359 config.max_blocks = 4096;
360 config.block_size = 64;
361 config.use_thread_local_cache = true;
362
363 memory_pool pool(config);
364
365 const int num_threads = 8;
366 const int operations_per_thread = 500;
367
368 std::vector<std::thread> threads;
369 std::atomic<int> successful_operations{0};
370
371 for (int t = 0; t < num_threads; ++t) {
372 threads.emplace_back([&pool, &successful_operations, operations_per_thread]() {
373 std::vector<void*> allocated_ptrs;
374
375 // Allocate
376 for (int i = 0; i < operations_per_thread; ++i) {
377 auto result = pool.allocate();
378 if (result.is_ok()) {
379 allocated_ptrs.push_back(result.value());
380 }
381 }
382
383 // Deallocate
384 for (auto* ptr : allocated_ptrs) {
385 auto result = pool.deallocate(ptr);
386 if (result.is_ok()) {
387 successful_operations.fetch_add(1);
388 }
389 }
390 });
391 }
392
393 for (auto& thread : threads) {
394 thread.join();
395 }
396
397 EXPECT_GT(successful_operations.load(), num_threads * operations_per_thread * 0.85); // Relaxed for concurrent access
398
399 const auto& stats = pool.get_statistics();
400 EXPECT_GT(stats.get_allocation_success_rate(), 95.0);
401}
402
403// Memory Pool: Config Validation All Failure Cases
404TEST_F(OptimizationTest, MemoryPoolConfigValidationAllCases) {
405 // Valid config
408 valid.max_blocks = 256;
409 valid.block_size = 64;
410 valid.alignment = 8;
411 EXPECT_TRUE(valid.validate());
412
413 // Zero initial blocks
414 memory_pool_config zero_blocks;
415 zero_blocks.initial_blocks = 0;
416 EXPECT_FALSE(zero_blocks.validate());
417
418 // Zero block size
419 memory_pool_config zero_size;
420 zero_size.block_size = 0;
421 EXPECT_FALSE(zero_size.validate());
422
423 // Block size not 8-byte aligned
424 memory_pool_config bad_align;
425 bad_align.block_size = 13;
426 EXPECT_FALSE(bad_align.validate());
427
428 // Alignment not power of 2
429 memory_pool_config bad_pow2;
430 bad_pow2.block_size = 64;
431 bad_pow2.alignment = 6;
432 EXPECT_FALSE(bad_pow2.validate());
433
434 // Zero alignment
435 memory_pool_config zero_align;
436 zero_align.block_size = 64;
437 zero_align.alignment = 0;
438 EXPECT_FALSE(zero_align.validate());
439
440 // max_blocks < initial_blocks
441 memory_pool_config max_less;
442 max_less.initial_blocks = 100;
443 max_less.max_blocks = 50;
444 max_less.block_size = 64;
445 EXPECT_FALSE(max_less.validate());
446}
447
448// Memory Pool: Allocate When Full
449TEST_F(OptimizationTest, MemoryPoolAllocateWhenFull) {
450 memory_pool_config config;
451 config.initial_blocks = 4;
452 config.max_blocks = 4; // Cannot grow
453 config.block_size = 64;
454
455 memory_pool pool(config);
456
457 // Allocate all blocks
458 std::vector<void*> allocated;
459 for (int i = 0; i < 4; ++i) {
460 auto result = pool.allocate();
461 EXPECT_TRUE(result.is_ok());
462 allocated.push_back(result.value());
463 }
464 EXPECT_EQ(pool.available_blocks(), 0);
465
466 // Next allocation should fail with resource_unavailable
467 auto fail_result = pool.allocate();
468 EXPECT_TRUE(fail_result.is_err());
469
470 // Cleanup
471 for (auto* ptr : allocated) {
472 pool.deallocate(ptr);
473 }
474}
475
476// Memory Pool: Deallocate nullptr
477TEST_F(OptimizationTest, MemoryPoolDeallocateNullptr) {
478 memory_pool pool;
479
480 auto result = pool.deallocate(nullptr);
481 EXPECT_TRUE(result.is_err());
482}
483
484// Memory Pool: Deallocate Foreign Pointer
485TEST_F(OptimizationTest, MemoryPoolDeallocateForeignPtr) {
486 memory_pool pool;
487
488 int foreign_value = 42;
489 auto result = pool.deallocate(&foreign_value);
490 EXPECT_TRUE(result.is_err());
491}
492
493// Memory Pool: allocate_object When sizeof(T) > block_size
494TEST_F(OptimizationTest, MemoryPoolAllocateObjectOversized) {
495 memory_pool_config config;
496 config.initial_blocks = 16;
497 config.block_size = 8; // Very small blocks
498
499 memory_pool pool(config);
500
501 struct LargeObject {
502 double data[16]; // 128 bytes > 8 bytes block_size
503 };
504
505 auto result = pool.allocate_object<LargeObject>();
506 EXPECT_TRUE(result.is_err());
507}
508
509// SIMD Aggregator Tests
510TEST_F(OptimizationTest, SIMDAggregatorBasicOperations) {
511 simd_config config;
512 simd_aggregator aggregator(config);
513
514 std::vector<double> data = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
515
516 // Test sum
517 auto sum_result = aggregator.sum(data);
518 EXPECT_TRUE(sum_result.is_ok());
519 EXPECT_DOUBLE_EQ(sum_result.value(), 36.0);
520
521 // Test mean
522 auto mean_result = aggregator.mean(data);
523 EXPECT_TRUE(mean_result.is_ok());
524 EXPECT_DOUBLE_EQ(mean_result.value(), 4.5);
525
526 // Test min/max
527 auto min_result = aggregator.min(data);
528 EXPECT_TRUE(min_result.is_ok());
529 EXPECT_DOUBLE_EQ(min_result.value(), 1.0);
530
531 auto max_result = aggregator.max(data);
532 EXPECT_TRUE(max_result.is_ok());
533 EXPECT_DOUBLE_EQ(max_result.value(), 8.0);
534
535 // Test variance
536 auto var_result = aggregator.variance(data);
537 EXPECT_TRUE(var_result.is_ok());
538 EXPECT_GT(var_result.value(), 0.0); // Should be positive for this dataset
539}
540
541TEST_F(OptimizationTest, SIMDAggregatorLargeDataset) {
542 simd_config config;
543 config.enable_simd = true;
544 simd_aggregator aggregator(config);
545
546 // Generate large dataset
547 auto data = generate_test_data(10000, 0.0, 100.0);
548
549 // Test statistical summary
550 auto summary_result = aggregator.compute_summary(data);
551 EXPECT_TRUE(summary_result.is_ok());
552
553 const auto& summary = summary_result.value();
554 EXPECT_EQ(summary.count, 10000);
555 EXPECT_GT(summary.sum, 0.0);
556 EXPECT_GT(summary.mean, 0.0);
557 EXPECT_LT(summary.mean, 100.0);
558 EXPECT_GT(summary.variance, 0.0);
559 EXPECT_GT(summary.std_dev, 0.0);
560 EXPECT_GE(summary.min_val, 0.0);
561 EXPECT_LE(summary.max_val, 100.0);
562 EXPECT_LT(summary.min_val, summary.max_val);
563
564 // Check SIMD utilization
565 const auto& stats = aggregator.get_statistics();
566 if (aggregator.get_capabilities().avx2_available || aggregator.get_capabilities().neon_available) {
567 EXPECT_GT(stats.get_simd_utilization(), 0.0);
568 }
569}
570
571TEST_F(OptimizationTest, SIMDAggregatorPerformanceComparison) {
572 // Test SIMD vs scalar performance
573 simd_config simd_cfg;
574 simd_cfg.enable_simd = true;
575
576 simd_config scalar_cfg;
577 scalar_cfg.enable_simd = false;
578
579 simd_aggregator simd_agg(simd_cfg);
580 simd_aggregator scalar_agg(scalar_cfg);
581
582 auto large_data = generate_test_data(50000, 0.0, 1000.0);
583
584 // Measure SIMD performance
585 auto start_simd = std::chrono::high_resolution_clock::now();
586 auto simd_summary = simd_agg.compute_summary(large_data);
587 auto end_simd = std::chrono::high_resolution_clock::now();
588
589 // Measure scalar performance
590 auto start_scalar = std::chrono::high_resolution_clock::now();
591 auto scalar_summary = scalar_agg.compute_summary(large_data);
592 auto end_scalar = std::chrono::high_resolution_clock::now();
593
594 EXPECT_TRUE(simd_summary.is_ok());
595 EXPECT_TRUE(scalar_summary.is_ok());
596
597 // Results should be approximately equal
598 const auto& simd_result = simd_summary.value();
599 const auto& scalar_result = scalar_summary.value();
600
601 EXPECT_NEAR(simd_result.sum, scalar_result.sum, 1e-6);
602 EXPECT_NEAR(simd_result.mean, scalar_result.mean, 1e-6);
603 EXPECT_NEAR(simd_result.min_val, scalar_result.min_val, 1e-6);
604 EXPECT_NEAR(simd_result.max_val, scalar_result.max_val, 1e-6);
605
606 auto simd_duration = std::chrono::duration_cast<std::chrono::microseconds>(end_simd - start_simd);
607 auto scalar_duration = std::chrono::duration_cast<std::chrono::microseconds>(end_scalar - start_scalar);
608
609 // SIMD should be faster or at least comparable (depending on data size and CPU)
610 std::cout << "SIMD duration: " << simd_duration.count() << " μs" << std::endl;
611 std::cout << "Scalar duration: " << scalar_duration.count() << " μs" << std::endl;
612
613 if (simd_agg.get_capabilities().avx2_available || simd_agg.get_capabilities().neon_available) {
614 // Performance comparison is informational only - CI environments may have
615 // virtualization overhead or SIMD emulation that makes SIMD slower
616 if (simd_duration.count() > scalar_duration.count() * 1.2) {
617 std::cout << "[INFO] SIMD slower than scalar - this may be expected in CI/VM environments" << std::endl;
618 }
619 }
620}
621
622// SIMD Aggregator: Empty Vector Input
623TEST_F(OptimizationTest, SIMDAggregatorEmptyInput) {
624 simd_aggregator aggregator;
625 std::vector<double> empty_data;
626
627 auto sum_result = aggregator.sum(empty_data);
628 EXPECT_TRUE(sum_result.is_err());
629
630 auto mean_result = aggregator.mean(empty_data);
631 EXPECT_TRUE(mean_result.is_err());
632
633 auto min_result = aggregator.min(empty_data);
634 EXPECT_TRUE(min_result.is_err());
635
636 auto max_result = aggregator.max(empty_data);
637 EXPECT_TRUE(max_result.is_err());
638
639 auto var_result = aggregator.variance(empty_data);
640 EXPECT_TRUE(var_result.is_err());
641
642 auto summary_result = aggregator.compute_summary(empty_data);
643 EXPECT_TRUE(summary_result.is_err());
644}
645
646// SIMD Aggregator: Variance of Single Value
647TEST_F(OptimizationTest, SIMDAggregatorVarianceSingleValue) {
648 simd_aggregator aggregator;
649 std::vector<double> single = {42.0};
650
651 auto result = aggregator.variance(single);
652 EXPECT_TRUE(result.is_ok());
653 EXPECT_DOUBLE_EQ(result.value(), 0.0);
654}
655
656// SIMD Aggregator: Scalar-Only Mode
657TEST_F(OptimizationTest, SIMDAggregatorScalarOnlyMode) {
658 simd_config config;
659 config.enable_simd = false;
660 simd_aggregator aggregator(config);
661
662 auto data = generate_test_data(100, 0.0, 100.0);
663
664 auto sum_result = aggregator.sum(data);
665 EXPECT_TRUE(sum_result.is_ok());
666
667 auto mean_result = aggregator.mean(data);
668 EXPECT_TRUE(mean_result.is_ok());
669
670 // All operations should use scalar path
671 const auto& stats = aggregator.get_statistics();
672 EXPECT_EQ(stats.simd_operations.load(), 0);
673 EXPECT_GT(stats.scalar_operations.load(), 0);
674 EXPECT_GT(stats.total_elements_processed.load(), 0);
675}
676
677// SIMD Aggregator: test_simd Self-Test
678TEST_F(OptimizationTest, SIMDAggregatorSelfTest) {
679 simd_aggregator aggregator;
680 auto result = aggregator.test_simd();
681 EXPECT_TRUE(result.is_ok());
682 EXPECT_TRUE(result.value());
683}
684
685// SIMD Config: Additional Validation Cases
686TEST_F(OptimizationTest, SIMDConfigValidationAllCases) {
687 // Valid config
689 valid.vector_size = 8;
690 valid.alignment = 32;
691 EXPECT_TRUE(valid.validate());
692
693 // Zero vector size
694 simd_config zero_vec;
695 zero_vec.vector_size = 0;
696 EXPECT_FALSE(zero_vec.validate());
697
698 // Non-power-of-2 vector size
699 simd_config bad_vec;
700 bad_vec.vector_size = 5;
701 EXPECT_FALSE(bad_vec.validate());
702
703 // Zero alignment
704 simd_config zero_align;
705 zero_align.alignment = 0;
706 EXPECT_FALSE(zero_align.validate());
707
708 // Non-power-of-2 alignment
709 simd_config bad_align;
710 bad_align.alignment = 12;
711 EXPECT_FALSE(bad_align.validate());
712}
713
714// Configuration Tests
715TEST_F(OptimizationTest, ConfigurationValidation) {
716 // Test lockfree queue config validation
717 lockfree_queue_config invalid_queue_config;
718 invalid_queue_config.initial_capacity = 0; // Invalid
719 EXPECT_FALSE(invalid_queue_config.validate());
720
721 lockfree_queue_config valid_queue_config;
722 valid_queue_config.initial_capacity = 1024;
723 valid_queue_config.max_capacity = 4096;
724 EXPECT_TRUE(valid_queue_config.validate());
725
726 // Test memory pool config validation
727 memory_pool_config invalid_pool_config;
728 invalid_pool_config.block_size = 7; // Not 8-byte aligned
729 EXPECT_FALSE(invalid_pool_config.validate());
730
731 memory_pool_config valid_pool_config;
732 valid_pool_config.initial_blocks = 256;
733 valid_pool_config.max_blocks = 1024;
734 valid_pool_config.block_size = 64;
735 EXPECT_TRUE(valid_pool_config.validate());
736
737 // Test SIMD config validation
738 simd_config invalid_simd_config;
739 invalid_simd_config.vector_size = 7; // Not power of 2
740 EXPECT_FALSE(invalid_simd_config.validate());
741
742 simd_config valid_simd_config;
743 valid_simd_config.vector_size = 8;
744 valid_simd_config.alignment = 32;
745 EXPECT_TRUE(valid_simd_config.validate());
746}
747
748// Factory Functions Tests
749TEST_F(OptimizationTest, FactoryFunctions) {
750 // Test lockfree queue factory
751 auto queue = make_lockfree_queue<int>();
752 EXPECT_NE(queue, nullptr);
753 EXPECT_TRUE(queue->empty());
754
755 // Test memory pool factory
756 auto pool = make_memory_pool();
757 EXPECT_NE(pool, nullptr);
758 EXPECT_GT(pool->available_blocks(), 0);
759
760 // Test SIMD aggregator factory
761 auto aggregator = make_simd_aggregator();
762 EXPECT_NE(aggregator, nullptr);
763
764 // Test SIMD functionality
765 auto test_result = aggregator->test_simd();
766 EXPECT_TRUE(test_result.is_ok());
767 EXPECT_TRUE(test_result.value());
768}
769
770// Default Configurations Tests
771TEST_F(OptimizationTest, DefaultConfigurations) {
772 // Test default queue configurations
773 auto queue_configs = create_default_queue_configs();
774 EXPECT_GE(queue_configs.size(), 3);
775
776 for (const auto& config : queue_configs) {
777 EXPECT_TRUE(config.validate());
778 }
779
780 // Test default pool configurations
781 auto pool_configs = create_default_pool_configs();
782 EXPECT_GE(pool_configs.size(), 3);
783
784 for (const auto& config : pool_configs) {
785 EXPECT_TRUE(config.validate());
786 }
787
788 // Test default SIMD configurations
789 auto simd_configs = create_default_simd_configs();
790 EXPECT_GE(simd_configs.size(), 3);
791
792 for (const auto& config : simd_configs) {
793 EXPECT_TRUE(config.validate());
794 }
795}
796
797// Integration Tests
798TEST_F(OptimizationTest, IntegrationTest) {
799 // Test integration of all optimization components
801 memory_pool pool;
802 simd_aggregator aggregator;
803
804 // Generate data and push to queue
805 auto test_data = generate_test_data(1000);
806
807 for (double value : test_data) {
808 auto result = queue.push(value);
809 EXPECT_TRUE(result.is_ok());
810 }
811
812 // Pop data from queue and collect in vector
813 std::vector<double> collected_data;
814 collected_data.reserve(test_data.size());
815
816 while (!queue.empty()) {
817 auto result = queue.pop();
818 if (result.is_ok()) {
819 collected_data.push_back(result.value());
820 }
821 }
822
823 EXPECT_EQ(collected_data.size(), test_data.size());
824
825 // Use SIMD aggregator to process collected data
826 auto summary = aggregator.compute_summary(collected_data);
827 EXPECT_TRUE(summary.is_ok());
828
829 const auto& stats = summary.value();
830 EXPECT_EQ(stats.count, test_data.size());
831 EXPECT_GT(stats.sum, 0.0);
832 EXPECT_GT(stats.mean, 0.0);
833
834 // Verify statistics from all components
835 const auto& queue_stats = queue.get_statistics();
836 const auto& pool_stats = pool.get_statistics();
837 const auto& simd_stats = aggregator.get_statistics();
838
839 EXPECT_GT(queue_stats.get_push_success_rate(), 99.0);
840 EXPECT_GT(queue_stats.get_pop_success_rate(), 99.0);
841 EXPECT_GT(pool_stats.get_allocation_success_rate(), 99.0);
842 EXPECT_GT(simd_stats.total_elements_processed.load(), 0);
843}
Test suite for Phase 3 P4: Lock-free data structures integration.
std::vector< double > generate_test_data(size_t size, double min_val=0.0, double max_val=100.0)
Generate test data.
void TearDown() override
void SetUp() override
Thread-safe lock-free MPMC (Multiple Producer Multiple Consumer) queue.
const lockfree_queue_statistics & get_statistics() const
Get queue statistics.
size_t size() const
Get current queue size.
common::Result< bool > push(const T &value)
Push an element to the queue.
bool empty() const
Check if the queue is empty.
common::Result< T > pop()
Pop an element from the queue.
void reset_statistics()
Reset statistics.
Thread-safe fixed-size block memory allocator.
common::VoidResult deallocate_object(T *obj)
Destroy and deallocate an object.
const memory_pool_statistics & get_statistics() const
Get pool statistics.
size_t available_blocks() const
Get number of available blocks.
size_t total_blocks() const
Get total number of blocks.
common::Result< void * > allocate()
Allocate a memory block.
common::VoidResult deallocate(void *ptr)
Deallocate a memory block.
common::Result< T * > allocate_object(Args &&... args)
Allocate and construct an object.
SIMD-accelerated statistical aggregator.
common::Result< statistical_summary > compute_summary(const std::vector< double > &data)
Compute full statistical summary.
const simd_aggregator_statistics & get_statistics() const
Get aggregator statistics.
common::Result< double > mean(const std::vector< double > &data)
Calculate mean of elements.
common::Result< bool > test_simd()
Self-test SIMD functionality.
common::Result< double > sum(const std::vector< double > &data)
Calculate sum of elements.
common::Result< double > variance(const std::vector< double > &data)
Calculate variance of elements.
const simd_capabilities & get_capabilities() const
Get SIMD capabilities.
common::Result< double > min(const std::vector< double > &data)
Find minimum value.
common::Result< double > max(const std::vector< double > &data)
Find maximum value.
Lock-free MPMC queue optimized for metric collection pipelines.
Platform-specific aligned memory allocation pool for monitoring objects.
@ summary
Pre-calculated quantiles and count/sum.
std::unique_ptr< simd_aggregator > make_simd_aggregator()
Create a SIMD aggregator with default configuration.
std::unique_ptr< memory_pool > make_memory_pool()
Create a memory pool with default configuration.
std::vector< simd_config > create_default_simd_configs()
Create default SIMD configurations for different use cases.
std::vector< lockfree_queue_config > create_default_queue_configs()
Create default queue configurations for different use cases.
std::vector< memory_pool_config > create_default_pool_configs()
Create default pool configurations for different use cases.
std::unique_ptr< lockfree_queue< T > > make_lockfree_queue()
Create a lock-free queue with default configuration.
SIMD-accelerated metric aggregation (AVX2/NEON auto-detected).
Configuration for lock-free queue.
size_t initial_capacity
Initial capacity of the queue.
size_t max_capacity
Maximum capacity (0 = unlimited)
bool validate() const
Validate configuration.
Configuration for memory pool.
Definition memory_pool.h:67
size_t block_size
Size of each block in bytes.
Definition memory_pool.h:70
bool use_thread_local_cache
Use thread-local caching.
Definition memory_pool.h:72
size_t alignment
Memory alignment (must be power of 2)
Definition memory_pool.h:71
size_t max_blocks
Maximum number of blocks (0 = unlimited)
Definition memory_pool.h:69
size_t initial_blocks
Initial number of blocks.
Definition memory_pool.h:68
bool validate() const
Validate configuration.
Definition memory_pool.h:78
Configuration for SIMD aggregator.
bool validate() const
Validate configuration.
bool enable_simd
Enable SIMD acceleration.
size_t alignment
Memory alignment for SIMD operations.
size_t vector_size
SIMD vector width for processing.
TEST_F(OptimizationTest, LockfreeQueueBasicOperations)