Change LinkGraph::EdgeMatrix to a sparse storage format

Use a btree_map instead of a SmallMatrix.
This avoids excessive storage requirements for large graphs,
and overly expensive edge matrix resize operations.
Remove next_edge iteration mechanism.
This commit is contained in:
Jonathan G Rennison
2022-12-05 18:17:25 +00:00
parent c457dc680b
commit e647075870
16 changed files with 353 additions and 470 deletions

View File

@@ -27,6 +27,7 @@ typedef LinkGraph::BaseEdge Edge;
static uint16 _num_nodes;
static LinkGraph *_linkgraph; ///< Contains the current linkgraph being saved/loaded.
static NodeID _linkgraph_from; ///< Contains the current "from" node being saved/loaded.
static NodeID _edge_next_edge;
class SlLinkgraphEdge : public DefaultSaveLoadHandler<SlLinkgraphEdge, Node> {
public:
@@ -36,21 +37,13 @@ public:
SLE_CONDVAR(Edge, travel_time_sum, SLE_UINT64, SLV_LINKGRAPH_TRAVEL_TIME, SL_MAX_VERSION),
SLE_VAR(Edge, last_unrestricted_update, SLE_INT32),
SLE_CONDVAR(Edge, last_restricted_update, SLE_INT32, SLV_187, SL_MAX_VERSION),
SLE_VAR(Edge, next_edge, SLE_UINT16),
SLEG_VAR("next_edge", _edge_next_edge, SLE_UINT16),
};
inline const static SaveLoadCompatTable compat_description = _linkgraph_edge_sl_compat;
void Save(Node *bn) const override
{
uint16 size = 0;
for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
size++;
}
SlSetStructListLength(size);
for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetDescription());
}
NOT_REACHED();
}
void Load(Node *bn) const override
@@ -58,22 +51,18 @@ public:
uint16 max_size = _linkgraph->Size();
if (IsSavegameVersionBefore(SLV_191)) {
/* We used to save the full matrix ... */
for (NodeID to = 0; to < max_size; ++to) {
SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetLoadDescription());
}
return;
NOT_REACHED();
}
size_t used_size = IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) ? max_size : SlGetStructListLength(UINT16_MAX);
/* ... but as that wasted a lot of space we save a sparse matrix now. */
for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _linkgraph->edges[_linkgraph_from][to].next_edge) {
for (NodeID to = _linkgraph_from; to != INVALID_NODE; to = _edge_next_edge) {
if (used_size == 0) SlErrorCorrupt("Link graph structure overflow");
used_size--;
if (to >= max_size) SlErrorCorrupt("Link graph structure overflow");
SlObject(&_linkgraph->edges[_linkgraph_from][to], this->GetLoadDescription());
SlObject(&_linkgraph->edges[std::make_pair(_linkgraph_from, to)], this->GetLoadDescription());
}
if (!IsSavegameVersionBefore(SLV_SAVELOAD_LIST_LENGTH) && used_size > 0) SlErrorCorrupt("Corrupted link graph");