diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a3a458c62..544cb8415 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -52,7 +52,9 @@ set(standalone_tests set(benchmarks clx_render_benchmark crawl_benchmark - dun_render_benchmark) + dun_render_benchmark + path_benchmark +) include(Fixtures.cmake) @@ -99,6 +101,7 @@ target_link_dependencies(format_int_test PRIVATE libdevilutionx_format_int langu target_link_dependencies(ini_test PRIVATE libdevilutionx_ini app_fatal_for_testing) target_link_dependencies(parse_int_test PRIVATE libdevilutionx_parse_int) target_link_dependencies(path_test PRIVATE libdevilutionx_pathfinding libdevilutionx_direction app_fatal_for_testing) +target_link_dependencies(path_benchmark PRIVATE libdevilutionx_pathfinding app_fatal_for_testing) target_link_dependencies(str_cat_test PRIVATE libdevilutionx_strings) target_link_dependencies(utf8_test PRIVATE libdevilutionx_utf8) diff --git a/test/path_benchmark.cpp b/test/path_benchmark.cpp new file mode 100644 index 000000000..0db673e23 --- /dev/null +++ b/test/path_benchmark.cpp @@ -0,0 +1,122 @@ +#include + +#include +#include + +#include "engine/path.h" +#include "engine/point.hpp" +#include "engine/points_in_rectangle_range.hpp" +#include "engine/size.hpp" + +namespace devilution { +namespace { + +struct Map { + Size size; + const char *data; + char operator[](const Point &p) const { return data[p.y * size.width + p.x]; } +}; + +std::pair FindStartDest(const Map &m) +{ + Point start, dest; + for (Point p : PointsInRectangle(Rectangle(Point { 0, 0 }, m.size))) { + switch (m[p]) { + case 'S': + start = p; + break; + case 'E': + dest = p; + break; + } + } + return { start, dest }; +} + +void BenchmarkMap(const Map &map, benchmark::State &state) +{ + const auto [start, dest] = FindStartDest(map); + const auto posOk = /*posOk=*/[&map](Point p) { return map[p] != '#'; }; + for (auto _ : state) { + int8_t path[MaxPathLength]; + int result = FindPath(/*canStep=*/[](Point, Point) { return true; }, + posOk, start, dest, path); + benchmark::DoNotOptimize(result); + } +} + +void BM_SinglePath(benchmark::State &state) +{ + BenchmarkMap( + Map { + Size { 15, 15 }, + "###############" + "#...#...#.....#" + "#.#.#.#.#.###.#" + "#S#...#.#.#...#" + "#######.#.#.###" + "##...##.#.#E..#" + "#######.#.###.#" + "###...#...#...#" + "###.#######.###" + "#...###...#...#" + "#.#####.#.###.#" + "#.#...#.#.#...#" + "#.#.#.#.#.#.###" + "#...#...#...###" + "###############" }, + state); +} + +void BM_Bridges(benchmark::State &state) +{ + BenchmarkMap( + Map { + Size { 15, 15 }, + "###############" + "#.S...........#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "############.##" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "###.###########" + "#.....E.......#" + "###############" }, + state); +} + +void BM_NoPath(benchmark::State &state) +{ + BenchmarkMap( + Map { + Size { 15, 15 }, + "###############" + "#.S...........#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "#.............#" + "###############" + "#.....E.......#" + "###############" }, + state); +} + +BENCHMARK(BM_SinglePath); +BENCHMARK(BM_Bridges); +BENCHMARK(BM_NoPath); + +} // namespace +} // namespace devilution