Skip to content

Commit 4d6f747

Browse files
committed
switch to lazily allocating pathfinding results
1 parent 9d2cd37 commit 4d6f747

File tree

5 files changed

+113
-49
lines changed

5 files changed

+113
-49
lines changed

editor/tests/path-test.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ void path_test::update_pre(app& a, const Ns&)
157157
auto& w = M.world();
158158
auto& astar = M.astar();
159159

160+
result.res = {}; // return back to the pool to preserve cpu cache
160161
auto res = astar.Dijkstra(w, pending.from, pending.to, pending.own_id, pending.max_dist, pending.own_size, 1);
161162
has_result = !!res;
162163
result = {

src/search-astar.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ void set_result_from_idx(path_search_result& result,
135135
for (auto i = idx; i != (uint32_t)-1; i = nodes[i].prev)
136136
len++;
137137

138+
if (!len) [[unlikely]]
139+
return;
140+
138141
fm_debug_assert(idx != (uint32_t)-1);
139142
arrayResize(temp_nodes, 0);
140143
arrayReserve(temp_nodes, len+1);

src/search-result.cpp

+54-25
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,11 @@ namespace floormat {
1111

1212
Pointer<path_search_result::node> path_search_result::_pool; // NOLINT
1313

14-
path_search_result::path_search_result()
15-
{
16-
constexpr auto min_length = TILE_MAX_DIM*2;
17-
if (_pool)
18-
{
19-
auto ptr = move(_pool);
20-
fm_debug_assert(ptr->vec.empty());
21-
auto next = move(ptr->_next);
22-
_node = move(ptr);
23-
_pool = move(next);
24-
}
25-
else
26-
{
27-
_node = Pointer<node>{InPlaceInit};
28-
_node->vec.reserve(min_length);
29-
}
30-
}
14+
path_search_result::path_search_result() = default;
3115

3216
path_search_result::~path_search_result() noexcept
3317
{
34-
if (_node && _node->vec.capacity() > 0) [[likely]]
18+
if (_node && _node->vec.capacity() > 0)
3519
{
3620
_node->vec.clear();
3721
_node->_next = move(_pool);
@@ -52,7 +36,7 @@ path_search_result& path_search_result::operator=(const path_search_result& x) n
5236
{
5337
fm_debug_assert(_node);
5438
fm_debug_assert(!_node->_next);
55-
if (&x != this)
39+
if (&x != this) [[likely]]
5640
_node->vec = x._node->vec;
5741
_cost = x._cost;
5842
return *this;
@@ -79,20 +63,65 @@ path_search_result& path_search_result::operator=(path_search_result&& other) no
7963
return *this;
8064
}
8165

82-
size_t path_search_result::size() const { return _node->vec.size(); }
83-
bool path_search_result::empty() const { return _node->vec.empty(); }
66+
void path_search_result::allocate_node()
67+
{
68+
constexpr auto min_length = TILE_MAX_DIM*2;
69+
70+
if (_node)
71+
return;
72+
73+
if (_pool)
74+
{
75+
auto ptr = move(_pool);
76+
fm_debug_assert(ptr->vec.empty());
77+
auto next = move(ptr->_next);
78+
_node = move(ptr);
79+
_pool = move(next);
80+
}
81+
else
82+
{
83+
_node = Pointer<node>{InPlaceInit};
84+
_node->vec.reserve(min_length);
85+
}
86+
}
87+
88+
ArrayView<const point> path_search_result::path() const
89+
{
90+
if (!_node)
91+
return {};
92+
return { _node->vec.data(), _node->vec.size() };
93+
}
94+
95+
vector_wrapper<point, vector_wrapper_repr::ref> path_search_result::raw_path()
96+
{
97+
if (!_node)
98+
allocate_node();
99+
return {_node->vec};
100+
}
101+
102+
size_t path_search_result::size() const
103+
{
104+
return _node ? _node->vec.size() : 0;
105+
}
106+
107+
bool path_search_result::empty() const
108+
{
109+
return !_node || _node->vec.empty();
110+
}
111+
112+
path_search_result::operator bool() const
113+
{
114+
return _node && !_node->vec.empty();
115+
}
116+
84117
path_search_result::node::node() noexcept = default;
85118
float path_search_result::time() const { return _time; }
86-
87119
uint32_t path_search_result::cost() const { return _cost; }
88120
void path_search_result::set_cost(uint32_t value) { _cost = value; }
89121
void path_search_result::set_time(float time) { _time = time; }
90122
bool path_search_result::is_found() const { return _found; }
91123
void path_search_result::set_found(bool value) { _found = value; }
92124
uint32_t path_search_result::distance() const { return _distance; }
93125
void path_search_result::set_distance(uint32_t dist) { _distance = dist; }
94-
path_search_result::operator bool() const { return !_node->vec.empty(); }
95-
ArrayView<const point> path_search_result::path() const { fm_assert(_node); return {_node->vec.data(), _node->vec.size()}; }
96-
vector_wrapper<point, vector_wrapper_repr::ref> path_search_result::raw_path() { fm_assert(_node); return {_node->vec}; }
97126

98127
} // namespace floormat

src/search-result.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ struct path_search_result final
3737
~path_search_result() noexcept;
3838

3939
private:
40+
void allocate_node();
41+
4042
Pointer<node> _node;
4143
float _time = 0;
4244
uint32_t _cost = 0, _distance = (uint32_t)-1;

test/search-result.cpp

+53-24
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "app.hpp"
22
#include "compat/assert.hpp"
3+
#include "compat/vector-wrapper.hpp"
34
#include "src/search-result.hpp"
45
#include "src/search-node.hpp"
56

@@ -15,34 +16,62 @@ struct path_search_result_pool_access<Test_PathPool> final
1516
{
1617
static const Pointer<node>& get_node(const path_search_result& p) { return p._node; }
1718
static const auto& get_pool() { return path_search_result::_pool; }
19+
static size_t pool_size();
1820
};
1921

22+
size_t path_search_result_pool_access<Test_PathPool>::pool_size()
23+
{
24+
size_t ret = 0;
25+
for (const auto* pool = get_pool().get(); pool; pool = pool->_next.get())
26+
ret++;
27+
return ret;
28+
}
29+
2030
void test_app::test_astar_pool()
2131
{
22-
auto& pool = psrpa::get_pool();
23-
fm_assert(!pool);
24-
{
25-
auto a = path_search_result{};
26-
fm_assert(!pool);
27-
}
28-
fm_assert(pool);
29-
auto* pool2 = pool.get();
30-
{
31-
auto b = path_search_result{};
32-
fm_assert(psrpa::get_node(b).get() == pool2);
33-
auto c = path_search_result{};
34-
fm_assert(!pool);
35-
fm_assert(psrpa::get_node(c).get() != pool2);
36-
fm_assert(psrpa::get_node(b).get() == pool2);
37-
fm_assert(!psrpa::get_node(b)->_next);
38-
fm_assert(!psrpa::get_node(c)->_next);
39-
}
40-
{
41-
auto count = 0uz;
42-
for (const auto* ptr = pool.get(); ptr; ptr = ptr->_next.get())
43-
count++;
44-
fm_assert(count == 2);
45-
}
32+
const auto& pool = psrpa::get_pool();
33+
fm_assert(psrpa::pool_size() == 0);
34+
35+
auto a = path_search_result{};
36+
fm_assert(psrpa::pool_size() == 0);
37+
fm_assert(!psrpa::get_node(a));
38+
39+
a = {};
40+
fm_assert(!psrpa::get_node(a));
41+
fm_assert(psrpa::pool_size() == 0);
42+
43+
a = path_search_result{};
44+
(void)a.raw_path();
45+
fm_assert(psrpa::get_node(a));
46+
fm_assert(psrpa::pool_size() == 0);
47+
const void* const first = psrpa::get_node(a).get();
48+
fm_assert(first);
49+
50+
a = {};
51+
fm_assert(!psrpa::get_node(a));
52+
fm_assert(psrpa::pool_size() == 1);
53+
fm_assert(pool.get() == first);
54+
55+
a = path_search_result{};
56+
(void)a.raw_path();
57+
fm_assert(psrpa::get_node(a));
58+
fm_assert(psrpa::get_node(a).get() == first);
59+
fm_assert(psrpa::pool_size() == 0);
60+
61+
auto b = path_search_result{};
62+
(void)b.raw_path();
63+
64+
fm_assert(psrpa::get_node(a));
65+
fm_assert(psrpa::get_node(b));
66+
fm_assert(psrpa::pool_size() == 0);
67+
68+
b = {};
69+
a = {};
70+
71+
fm_assert(!psrpa::get_node(a));
72+
fm_assert(!psrpa::get_node(b));
73+
fm_assert(psrpa::pool_size() == 2);
74+
fm_assert(pool.get() == first);
4675
}
4776

4877
} // namespace floormat

0 commit comments

Comments
 (0)