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:
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user