#include #include "vde/core/performance_tuning.h" #include "vde/core/point.h" #include #include #include #include #include using namespace vde::core; // =========================================================================== // parallel_task_graph 测试 // =========================================================================== TEST(PerformanceTuningTest, ParallelTaskGraph_BasicExecution) { std::atomic counter{0}; std::vector tasks = { {0, "task0", [&]{ counter++; }, {}}, {1, "task1", [&]{ counter++; }, {0}}, // 依赖 task0 {2, "task2", [&]{ counter++; }, {0}}, // 依赖 task0 {3, "task3", [&]{ counter++; }, {1,2}}, // 依赖 task1, task2 }; parallel_task_graph(tasks, 2); EXPECT_EQ(counter.load(), 4); } TEST(PerformanceTuningTest, ParallelTaskGraph_DiamondDependency) { std::vector execution_order; std::mutex mtx; auto make_task = [&](int id, std::vector deps) -> TaskNode { return {id, "task" + std::to_string(id), [&, id]{ std::lock_guard lk(mtx); execution_order.push_back(id); }, deps}; }; std::vector tasks = { make_task(0, {}), make_task(1, {0}), make_task(2, {0}), make_task(3, {1, 2}), make_task(4, {3}), }; parallel_task_graph(tasks, 4); ASSERT_EQ(execution_order.size(), 5u); // task0 must be first EXPECT_EQ(execution_order[0], 0); // task4 must be last EXPECT_EQ(execution_order[4], 4); } TEST(PerformanceTuningTest, ParallelTaskGraph_CycleDetection) { std::vector tasks = { {0, "task0", []{}, {1}}, // 依赖 task1 {1, "task1", []{}, {0}}, // 依赖 task0 → 循环 }; EXPECT_THROW({ parallel_task_graph(tasks, 2); }, std::runtime_error); } TEST(PerformanceTuningTest, ParallelTaskGraph_EmptyTasks) { std::vector empty; EXPECT_NO_THROW(parallel_task_graph(empty, 1)); } // =========================================================================== // WorkStealingScheduler 测试 // =========================================================================== TEST(PerformanceTuningTest, WorkStealingScheduler_BasicSubmit) { auto& scheduler = work_stealing_scheduler(); std::atomic counter{0}; for (int i = 0; i < 100; ++i) { scheduler.submit([&]{ counter++; }); } scheduler.wait_all(); EXPECT_EQ(counter.load(), 100); } TEST(PerformanceTuningTest, WorkStealingScheduler_PriorityTasks) { auto& scheduler = work_stealing_scheduler(); std::vector completion_order; std::mutex mtx; // 提交低优先级任务 scheduler.submit([&]{ std::this_thread::sleep_for(std::chrono::milliseconds(50)); std::lock_guard lk(mtx); completion_order.push_back(0); }, 0); // 提交高优先级任务(应优先执行) scheduler.submit([&]{ std::lock_guard lk(mtx); completion_order.push_back(1); }, 10); scheduler.wait_all(); EXPECT_EQ(completion_order.size(), 2u); EXPECT_EQ(completion_order[0], 1) << "High priority should complete first"; } // =========================================================================== // MemoryPoolIntegration 测试 // =========================================================================== TEST(PerformanceTuningTest, MemoryPool_AllocateDeallocate) { auto& pool = memory_pool_integration(); pool.reset(); auto* pt = pool.allocate_point3d(); ASSERT_NE(pt, nullptr); *pt = Point3D(1, 2, 3); EXPECT_DOUBLE_EQ(pt->x(), 1.0); pool.deallocate_point3d(pt); auto stats = pool.stats(); EXPECT_GT(stats.total_allocations + stats.cache_hits, 0u); pool.reset(); } TEST(PerformanceTuningTest, MemoryPool_Reuse) { auto& pool = memory_pool_integration(); pool.reset(); pool.warm_up(10); auto* pt1 = pool.allocate_point3d(); auto* pt2 = pool.allocate_point3d(); EXPECT_NE(pt1, pt2) << "Should get different pointers"; pool.deallocate_point3d(pt1); pool.deallocate_point3d(pt2); auto* pt3 = pool.allocate_point3d(); // pt3 很可能来自池(pt1 或 pt2) EXPECT_TRUE(pt3 == pt1 || pt3 == pt2) << "Should reuse from pool"; pool.reset(); } TEST(PerformanceTuningTest, MemoryPool_GenericAllocate) { auto& pool = memory_pool_integration(); pool.reset(); pool.set_pool_size(64); void* buf = pool.allocate(128); ASSERT_NE(buf, nullptr); pool.deallocate(buf, 128); auto stats = pool.stats(); EXPECT_GE(stats.total_allocations, 1u); pool.reset(); } // =========================================================================== // cache_optimization_hints 测试 // =========================================================================== TEST(PerformanceTuningTest, CacheOptimizationHints_ReturnsValid) { auto hints = cache_optimization_hints(); EXPECT_GT(hints.l1_cache_size, 0u); EXPECT_GT(hints.l2_cache_size, 0u); EXPECT_GT(hints.cache_line_size, 0u); EXPECT_EQ(hints.cache_line_size, 64u) << "Expected 64-byte cache line"; EXPECT_GE(hints.numa_node_count, 1); } TEST(PerformanceTuningTest, Prefetch_Compiles) { int value = 42; // 预取不应崩溃 EXPECT_NO_THROW(prefetch(&value)); EXPECT_NO_THROW(prefetch_write(&value)); } TEST(PerformanceTuningTest, PaddedAtomic_Alignment) { PaddedAtomic<> padded; padded.value = 42; EXPECT_EQ(padded.value.load(), 42); // 验证对齐 EXPECT_EQ(sizeof(padded), CACHE_LINE_SIZE); EXPECT_EQ(alignof(decltype(padded)), CACHE_LINE_SIZE); } // =========================================================================== // profile_guided_layout 测试 // =========================================================================== TEST(PerformanceTuningTest, ProfileGuidedLayout_HotColdSplit) { std::vector records = { {"field_a", 1000, 50, 0.0}, {"field_b", 100, 5, 0.0}, {"field_c", 10, 1, 0.0}, }; auto plan = profile_guided_layout(records, "TestStruct"); EXPECT_GT(plan.hot_fields.size(), 0u); EXPECT_GT(plan.cold_fields.size(), 0u); EXPECT_GT(plan.estimated_improvement, 0.0) << "Should estimate performance improvement"; } TEST(PerformanceTuningTest, ProfileGuidedLayout_EmptyRecords) { std::vector empty; auto plan = profile_guided_layout(empty, "Empty"); EXPECT_EQ(plan.hot_fields.size(), 0u); EXPECT_EQ(plan.cold_fields.size(), 0u); } // =========================================================================== // Point3DSoA 测试 // =========================================================================== TEST(PerformanceTuningTest, Point3DSoA_ConversionRoundtrip) { std::vector original = { Point3D(1, 2, 3), Point3D(4, 5, 6), Point3D(7, 8, 9), Point3D(10, 11, 12), }; auto soa = Point3DSoA::from_aos(original); EXPECT_EQ(soa.size(), 4u); EXPECT_DOUBLE_EQ(soa.x[0], 1.0); EXPECT_DOUBLE_EQ(soa.y[1], 5.0); EXPECT_DOUBLE_EQ(soa.z[2], 9.0); auto restored = soa.to_aos(); EXPECT_EQ(restored.size(), 4u); for (size_t i = 0; i < original.size(); ++i) { EXPECT_DOUBLE_EQ(restored[i].x(), original[i].x()); EXPECT_DOUBLE_EQ(restored[i].y(), original[i].y()); EXPECT_DOUBLE_EQ(restored[i].z(), original[i].z()); } } TEST(PerformanceTuningTest, Point3DSoA_Empty) { std::vector empty; auto soa = Point3DSoA::from_aos(empty); EXPECT_EQ(soa.size(), 0u); auto restored = soa.to_aos(); EXPECT_EQ(restored.size(), 0u); }