You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
339 lines
12 KiB
339 lines
12 KiB
/**
|
|
* @file performance_test.cpp
|
|
* @brief primitive_process 性能基准测试(架构适配版)
|
|
*
|
|
* 测试覆盖:
|
|
* 1. SDF 评估性能
|
|
* 2. Descriptor 更新性能
|
|
* 3. AABB 计算性能
|
|
* 4. 大规模对象创建/销毁
|
|
* 5. 内存分配效率
|
|
*
|
|
* @note 已适配新架构:
|
|
* - new_primitive 需要 data_center 指针参数
|
|
* - 简化的销毁流程
|
|
*/
|
|
|
|
#define _USE_MATH_DEFINES
|
|
#include <windows.h>
|
|
#include <iostream>
|
|
#include <iomanip>
|
|
#include <chrono>
|
|
#include <vector>
|
|
#include <cmath>
|
|
#include <mimalloc.h>
|
|
|
|
#include <data/data_center.hpp>
|
|
#include <base/primitive.hpp>
|
|
#include <base/subface.hpp>
|
|
#include <primitive_descriptor.h>
|
|
|
|
// ============================================================================
|
|
// 性能计时器
|
|
// ============================================================================
|
|
|
|
class ScopedTimer
|
|
{
|
|
public:
|
|
explicit ScopedTimer(const char* name) : name_(name) { start_ = std::chrono::high_resolution_clock::now(); }
|
|
|
|
~ScopedTimer()
|
|
{
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start_);
|
|
std::cout << " " << name_ << ": " << std::fixed << std::setprecision(2) << duration.count() / 1000.0 << " ms\n";
|
|
}
|
|
|
|
private:
|
|
const char* name_;
|
|
std::chrono::high_resolution_clock::time_point start_;
|
|
};
|
|
|
|
// ============================================================================
|
|
// 辅助函数(新架构简化版)
|
|
// ============================================================================
|
|
|
|
void safe_destroy_primitive(primitive* ptr)
|
|
{
|
|
if (!ptr) return;
|
|
ptr->destroy();
|
|
mi_free(ptr);
|
|
}
|
|
|
|
// ============================================================================
|
|
// 性能测试 1: SDF 评估
|
|
// ============================================================================
|
|
|
|
void benchmark_sdf_evaluation()
|
|
{
|
|
std::cout << "\n1. SDF Evaluation Performance\n";
|
|
|
|
primitive_data_center_t data_center;
|
|
primitive* cyl = internal::new_primitive(PRIMITIVE_TYPE_CYLINDER, &data_center);
|
|
|
|
auto subfaces = cyl->get_subfaces();
|
|
auto* cylinder_face = subfaces[0].get_ptr();
|
|
auto eval_sdf = internal::get_eval_sdf_ptr(surface_type::cylinder);
|
|
|
|
constexpr int ITERATIONS = 1'000'000;
|
|
Eigen::Vector3d test_point(1.5, 0.5, 0.3);
|
|
|
|
{
|
|
ScopedTimer timer("1M SDF evaluations");
|
|
double sum = 0.0;
|
|
for (int i = 0; i < ITERATIONS; ++i) { sum += eval_sdf(make_pointer_wrapper(cylinder_face), test_point); }
|
|
// 防止编译器优化掉循环
|
|
if (sum > 1e10) std::cout << " Result: " << sum << "\n";
|
|
}
|
|
|
|
safe_destroy_primitive(cyl);
|
|
}
|
|
|
|
// ============================================================================
|
|
// 性能测试 2: Descriptor 更新
|
|
// ============================================================================
|
|
|
|
void benchmark_descriptor_update()
|
|
{
|
|
std::cout << "\n2. Descriptor Update Performance\n";
|
|
|
|
primitive_data_center_t data_center;
|
|
primitive* cyl = internal::new_primitive(PRIMITIVE_TYPE_CYLINDER, &data_center);
|
|
|
|
constexpr int ITERATIONS = 100'000;
|
|
|
|
{
|
|
ScopedTimer timer("100K descriptor updates");
|
|
for (int i = 0; i < ITERATIONS; ++i) {
|
|
double r = 1.0 + i * 0.0001;
|
|
double h = 2.0 + i * 0.0002;
|
|
cylinder_descriptor_t desc{r, h};
|
|
cyl->update_geometry(&desc, 0);
|
|
}
|
|
}
|
|
|
|
safe_destroy_primitive(cyl);
|
|
}
|
|
|
|
// ============================================================================
|
|
// 性能测试 3: AABB 计算
|
|
// ============================================================================
|
|
|
|
void benchmark_aabb_calculation()
|
|
{
|
|
std::cout << "\n3. AABB Calculation Performance\n";
|
|
|
|
primitive_data_center_t data_center;
|
|
primitive* cyl = internal::new_primitive(PRIMITIVE_TYPE_CYLINDER, &data_center);
|
|
|
|
constexpr int ITERATIONS = 1'000'000;
|
|
|
|
{
|
|
ScopedTimer timer("1M AABB calculations");
|
|
double sum = 0.0;
|
|
for (int i = 0; i < ITERATIONS; ++i) {
|
|
aabb_t aabb = cyl->fetch_aabb();
|
|
sum += aabb.volume();
|
|
}
|
|
if (sum > 1e10) std::cout << " Result: " << sum << "\n";
|
|
}
|
|
|
|
safe_destroy_primitive(cyl);
|
|
}
|
|
|
|
// ============================================================================
|
|
// 性能测试 4: 大规模对象创建/销毁(新架构适配)
|
|
// ============================================================================
|
|
|
|
void benchmark_mass_creation()
|
|
{
|
|
std::cout << "\n4. Mass Object Creation/Destruction (New Architecture)\n";
|
|
|
|
primitive_data_center_t data_center;
|
|
constexpr int COUNT = 10'000;
|
|
|
|
{
|
|
ScopedTimer timer("Create/destroy 10K primitives");
|
|
for (int i = 0; i < COUNT; ++i) {
|
|
// 新架构:构造时传入 data_center 指针
|
|
primitive* cyl = internal::new_primitive(PRIMITIVE_TYPE_CYLINDER, &data_center);
|
|
|
|
cylinder_descriptor_t desc{1.0 + i * 0.01, 2.0 + i * 0.02};
|
|
cyl->update_geometry(&desc, 0);
|
|
|
|
safe_destroy_primitive(cyl);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// 性能测试 5: 批量对象管理(新架构适配)
|
|
// ============================================================================
|
|
|
|
void benchmark_batch_management()
|
|
{
|
|
std::cout << "\n5. Batch Object Management (New Architecture)\n";
|
|
|
|
primitive_data_center_t data_center;
|
|
constexpr int COUNT = 1'000;
|
|
|
|
std::vector<primitive*> primitives;
|
|
primitives.reserve(COUNT);
|
|
|
|
{
|
|
ScopedTimer timer("Create 1K primitives");
|
|
for (int i = 0; i < COUNT; ++i) {
|
|
primitive* cyl = internal::new_primitive(PRIMITIVE_TYPE_CYLINDER, &data_center);
|
|
primitives.push_back(cyl);
|
|
}
|
|
}
|
|
|
|
{
|
|
ScopedTimer timer("Update 1K descriptors");
|
|
for (int i = 0; i < COUNT; ++i) {
|
|
cylinder_descriptor_t desc{1.0 + i * 0.1, 2.0 + i * 0.2};
|
|
primitives[i]->update_geometry(&desc, 0);
|
|
}
|
|
}
|
|
|
|
{
|
|
ScopedTimer timer("Calculate 1K AABBs");
|
|
double sum = 0.0;
|
|
for (int i = 0; i < COUNT; ++i) {
|
|
aabb_t aabb = primitives[i]->fetch_aabb();
|
|
sum += aabb.volume();
|
|
}
|
|
std::cout << " Total volume: " << sum << "\n";
|
|
}
|
|
|
|
{
|
|
ScopedTimer timer("Destroy 1K primitives");
|
|
for (auto* p : primitives) { safe_destroy_primitive(p); }
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// 性能测试 6: 内存分配效率
|
|
// ============================================================================
|
|
|
|
void benchmark_memory_allocation()
|
|
{
|
|
std::cout << "\n6. Memory Allocation Efficiency\n";
|
|
|
|
constexpr int ITERATIONS = 100'000;
|
|
|
|
{
|
|
ScopedTimer timer("100K mimalloc allocations (64 bytes)");
|
|
std::vector<void*> ptrs;
|
|
ptrs.reserve(ITERATIONS);
|
|
|
|
for (int i = 0; i < ITERATIONS; ++i) { ptrs.push_back(mi_malloc(64)); }
|
|
|
|
for (void* p : ptrs) { mi_free(p); }
|
|
}
|
|
|
|
{
|
|
ScopedTimer timer("100K mimalloc allocations (1024 bytes)");
|
|
std::vector<void*> ptrs;
|
|
ptrs.reserve(ITERATIONS);
|
|
|
|
for (int i = 0; i < ITERATIONS; ++i) { ptrs.push_back(mi_malloc(1024)); }
|
|
|
|
for (void* p : ptrs) { mi_free(p); }
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// 性能测试 7: 参数映射性能(新架构适配)
|
|
// ============================================================================
|
|
|
|
void benchmark_parametrization()
|
|
{
|
|
std::cout << "\n7. Parametrization Performance (New Architecture)\n";
|
|
|
|
primitive_data_center_t data_center;
|
|
primitive* cyl = internal::new_primitive(PRIMITIVE_TYPE_CYLINDER, &data_center);
|
|
|
|
auto subfaces = cyl->get_subfaces();
|
|
auto* cylinder_face = subfaces[0].get_ptr();
|
|
|
|
auto map_param_to_point_with_weight = internal::get_map_param_to_point_with_weight_ptr(surface_type::cylinder);
|
|
auto map_point_to_param = internal::get_map_point_to_param_ptr(surface_type::cylinder);
|
|
|
|
constexpr int ITERATIONS = 1'000'000;
|
|
|
|
{
|
|
ScopedTimer timer("1M param->point conversions");
|
|
Eigen::Vector2d param(M_PI / 4, 0.5);
|
|
Eigen::Vector3d sum = Eigen::Vector3d::Zero();
|
|
|
|
for (int i = 0; i < ITERATIONS; ++i) {
|
|
// 使用结构化绑定从 std::tuple 中提取点坐标
|
|
auto [point_h, surface_jacobi, volume_jacobi] =
|
|
map_param_to_point_with_weight(make_pointer_wrapper(cylinder_face), param);
|
|
sum += point_h.head<3>();
|
|
}
|
|
|
|
if (sum.norm() > 1e10) std::cout << " Result: " << sum.transpose() << "\n";
|
|
}
|
|
|
|
{
|
|
ScopedTimer timer("1M point->param conversions");
|
|
Eigen::Vector3d point(0.707, 0.707, 0.5);
|
|
Eigen::Vector2d sum = Eigen::Vector2d::Zero();
|
|
|
|
for (int i = 0; i < ITERATIONS; ++i) { sum += map_point_to_param(make_pointer_wrapper(cylinder_face), point); }
|
|
|
|
if (sum.norm() > 1e10) std::cout << " Result: " << sum.transpose() << "\n";
|
|
}
|
|
|
|
safe_destroy_primitive(cyl);
|
|
}
|
|
|
|
// ============================================================================
|
|
// 主测试入口
|
|
// ============================================================================
|
|
|
|
int main()
|
|
{
|
|
SetConsoleOutputCP(CP_UTF8);
|
|
|
|
std::cout << "╔══════════════════════════════════════════════╗\n";
|
|
std::cout << "║ PRIMITIVE_PROCESS PERFORMANCE BENCHMARK ║\n";
|
|
std::cout << "║ (New Architecture Adapted) ║\n";
|
|
std::cout << "╚══════════════════════════════════════════════╝\n";
|
|
std::cout << "mimalloc version: " << mi_version() << "\n\n";
|
|
|
|
// 获取初始内存状态
|
|
size_t initial_rss, initial_peak_rss;
|
|
mi_process_info(nullptr, nullptr, nullptr, &initial_rss, &initial_peak_rss, nullptr, nullptr, nullptr);
|
|
|
|
std::cout << "Initial RSS: " << (initial_rss / 1024) << " KB\n";
|
|
std::cout << "Initial Peak RSS: " << (initial_peak_rss / 1024) << " KB\n";
|
|
|
|
// 运行基准测试
|
|
benchmark_sdf_evaluation();
|
|
benchmark_descriptor_update();
|
|
benchmark_aabb_calculation();
|
|
benchmark_mass_creation();
|
|
benchmark_batch_management();
|
|
benchmark_memory_allocation();
|
|
benchmark_parametrization();
|
|
|
|
// 获取最终内存状态
|
|
size_t final_rss, final_peak_rss;
|
|
mi_process_info(nullptr, nullptr, nullptr, &final_rss, &final_peak_rss, nullptr, nullptr, nullptr);
|
|
|
|
std::cout << "\n╔══════════════════════════════════════════════╗\n";
|
|
std::cout << "║ MEMORY STATISTICS ║\n";
|
|
std::cout << "╚══════════════════════════════════════════════╝\n";
|
|
std::cout << "Final RSS: " << (final_rss / 1024) << " KB\n";
|
|
std::cout << "Peak RSS: " << (final_peak_rss / 1024) << " KB\n";
|
|
std::cout << "RSS Delta: " << ((final_rss - initial_rss) / 1024) << " KB\n";
|
|
|
|
std::cout << "\n╔══════════════════════════════════════════════╗\n";
|
|
std::cout << "║ ✓ BENCHMARK COMPLETED ║\n";
|
|
std::cout << "╚══════════════════════════════════════════════╝\n";
|
|
|
|
return 0;
|
|
}
|