Files
ViewDesignEngine/tests/benchmark/bench_boolean_perf.cpp
T

194 lines
6.2 KiB
C++
Raw Normal View History

/// @file bench_boolean_perf.cpp
/// @brief 布尔性能基准测试
///
/// 测试不同面数模型的 union / intersect / difference 性能。
/// 结果输出到 stdout,由 CI 汇总后写入 docs/benchmark-report.md
#include <gtest/gtest.h>
#include "vde/brep/brep.h"
#include "vde/brep/modeling.h"
#include "vde/brep/brep_boolean.h"
#include <chrono>
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
using namespace vde::brep;
using namespace std::chrono;
// ── 计时辅助 ──
struct BenchmarkResult {
std::string name;
double time_ms;
size_t faces_a;
size_t faces_b;
size_t faces_result;
};
static std::vector<BenchmarkResult> g_results;
static double measure_ms(std::function<void()> fn, int iterations = 3) {
double best = 1e18;
for (int i = 0; i < iterations; ++i) {
auto start = high_resolution_clock::now();
fn();
auto end = high_resolution_clock::now();
double ms = duration_cast<microseconds>(end - start).count() / 1000.0;
if (ms < best) best = ms;
}
return best;
}
static void record(const std::string& name, double ms,
size_t fa, size_t fb, size_t fr) {
g_results.push_back({name, ms, fa, fb, fr});
std::cout << " [BENCH] " << std::left << std::setw(40) << name
<< std::right << std::setw(10) << std::fixed << std::setprecision(2)
<< ms << " ms"
<< " (faces: " << fa << " + " << fb << "" << fr << ")"
<< std::endl;
}
// ═══════════════════════════════════════════════
// 布尔并集基准
// ═══════════════════════════════════════════════
TEST(BenchmarkBoolean, Union_SmallModels) {
// 小面数:两个低分辨率球体
auto a = make_sphere(1.0, 8, 4);
auto b = make_sphere(0.8, 8, 4);
double ms = measure_ms([&]() {
auto u = brep_union(a, b);
(void)u.num_faces();
}, 5);
auto result = brep_union(a, b);
record("Boolean.Union/Small", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
TEST(BenchmarkBoolean, Union_MediumModels) {
// 中面数:两个中等细分球体
auto a = make_sphere(2.0, 16, 8);
auto b = make_sphere(1.5, 16, 8);
double ms = measure_ms([&]() {
auto u = brep_union(a, b);
(void)u.num_faces();
}, 3);
auto result = brep_union(a, b);
record("Boolean.Union/Medium", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
TEST(BenchmarkBoolean, Union_LargeModels) {
// 大面数:两个高细分球体
auto a = make_sphere(3.0, 24, 16);
auto b = make_sphere(2.5, 24, 16);
double ms = measure_ms([&]() {
auto u = brep_union(a, b);
(void)u.num_faces();
}, 3);
auto result = brep_union(a, b);
record("Boolean.Union/Large", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
// ═══════════════════════════════════════════════
// 布尔交集基准
// ═══════════════════════════════════════════════
TEST(BenchmarkBoolean, Intersection_Small) {
auto a = make_sphere(1.0, 8, 4);
auto b = make_box(1.2, 1.2, 1.2);
double ms = measure_ms([&]() {
auto i = brep_intersection(a, b);
(void)i.num_faces();
}, 5);
auto result = brep_intersection(a, b);
record("Boolean.Intersection/Small", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
TEST(BenchmarkBoolean, Intersection_Medium) {
auto a = make_sphere(2.0, 16, 8);
auto b = make_cylinder(1.5, 4.0, 32);
double ms = measure_ms([&]() {
auto i = brep_intersection(a, b);
(void)i.num_faces();
}, 3);
auto result = brep_intersection(a, b);
record("Boolean.Intersection/Medium", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
TEST(BenchmarkBoolean, Intersection_Large) {
auto a = make_sphere(3.0, 24, 16);
auto b = make_cylinder(2.0, 6.0, 64);
double ms = measure_ms([&]() {
auto i = brep_intersection(a, b);
(void)i.num_faces();
}, 3);
auto result = brep_intersection(a, b);
record("Boolean.Intersection/Large", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
// ═══════════════════════════════════════════════
// 布尔差集基准
// ═══════════════════════════════════════════════
TEST(BenchmarkBoolean, Difference_Small) {
auto a = make_box(2.0, 2.0, 2.0);
auto b = make_sphere(0.8, 8, 4);
double ms = measure_ms([&]() {
auto d = brep_difference(a, b);
(void)d.num_faces();
}, 5);
auto result = brep_difference(a, b);
record("Boolean.Difference/Small", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
TEST(BenchmarkBoolean, Difference_Medium) {
auto a = make_box(4.0, 4.0, 4.0);
auto b = make_sphere(1.5, 16, 8);
double ms = measure_ms([&]() {
auto d = brep_difference(a, b);
(void)d.num_faces();
}, 3);
auto result = brep_difference(a, b);
record("Boolean.Difference/Medium", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}
TEST(BenchmarkBoolean, Difference_Large) {
auto a = make_box(6.0, 6.0, 6.0);
auto b = make_sphere(2.0, 24, 16);
double ms = measure_ms([&]() {
auto d = brep_difference(a, b);
(void)d.num_faces();
}, 3);
auto result = brep_difference(a, b);
record("Boolean.Difference/Large", ms, a.num_faces(), b.num_faces(), result.num_faces());
EXPECT_TRUE(result.is_valid());
}