simutrans-0001: rebuild_linked_connections() append_unique O(C*H^2) MEDIUM 97x
- vector_tpl::append_unique linear scan inside double loop over
goods categories x connections to collect unique connected halts
- fix: inthashtable_tpl for O(1) membership test
simutrans-0002: add_grund() registered_convoys.is_contained O(C*R) MEDIUM 45x
- iterates ALL world convoys, each with linear scan of registered
convoy vector to check membership
- fix: pre-build hash set of registered convoy IDs for O(1) lookup
simutrans-0003: rebuild_connections() consecutive_halts append_unique O(S^2) MEDIUM 24x
- append_unique on consecutive halt vectors per category inside
nested loop over schedules x entries during halt reconnection
- fix: parallel inthashtable_tpl for O(1) dedup
All three defects are in simhalt.cc halt reconnection paths, triggered
whenever schedules change (line added/removed, schedule edited, station
built). In large games with hundreds of halts and convoys, these
compound during reconnection sweeps.
MOAD-0002: welt (karte_t) is a god object but standard Simutrans architecture
MOAD-0003: CLEAN (no thread_local usage)
MOAD-0004: CLEAN (nettool password printf is by-design tool output)
MOAD-0005: CLEAN (save cache uses hashtable, no unsynchronized pattern)
69 lines
3.2 KiB
Diff
69 lines
3.2 KiB
Diff
--- a/src/simutrans/simhalt.cc
|
|
+++ b/src/simutrans/simhalt.cc
|
|
@@ -1222,6 +1222,10 @@
|
|
sint32 haltestelle_t::rebuild_connections()
|
|
{
|
|
// halts which either immediately precede or succeed self halt in serving schedules
|
|
static vector_tpl<halthandle_t> consecutive_halts[256];
|
|
+ // hash sets for O(1) dedup of consecutive halts (replaces append_unique
|
|
+ // linear scan which was O(S^2) per category where S = schedule entries)
|
|
+ static inthashtable_tpl<uint16, bool> consecutive_halts_seen[256];
|
|
// halts which either immediately precede or succeed self halt in currently processed schedule
|
|
static vector_tpl<halthandle_t> consecutive_halts_schedule[256];
|
|
+ static inthashtable_tpl<uint16, bool> consecutive_halts_schedule_seen[256];
|
|
// remember max number of consecutive halts for one schedule
|
|
uint8 max_consecutive_halts_schedule[256];
|
|
@@ -1234,6 +1238,8 @@
|
|
for( uint8 i=0; i<goods_manager_t::get_max_catg_index(); i++ ){
|
|
all_links[i].clear();
|
|
consecutive_halts[i].clear();
|
|
+ consecutive_halts_seen[i].clear();
|
|
}
|
|
old_sort_mode = 255; // might result in error in routing
|
|
|
|
@@ -1296,6 +1302,7 @@
|
|
for(uint8 const catg_index : *goods_catg_index) {
|
|
if( is_enabled(catg_index) ) {
|
|
supported_catg_index.append(catg_index);
|
|
previous_halt[catg_index] = self;
|
|
consecutive_halts_schedule[catg_index].clear();
|
|
+ consecutive_halts_schedule_seen[catg_index].clear();
|
|
}
|
|
}
|
|
|
|
@@ -1320,8 +1327,18 @@
|
|
if( current_halt == self ) {
|
|
// check for consecutive halts which precede self halt
|
|
for(uint8 const catg_index : supported_catg_index) {
|
|
if( previous_halt[catg_index]!=self ) {
|
|
- consecutive_halts[catg_index].append_unique(previous_halt[catg_index]);
|
|
- consecutive_halts_schedule[catg_index].append_unique(previous_halt[catg_index]);
|
|
+ uint16 halt_id = previous_halt[catg_index].get_id();
|
|
+ if( !consecutive_halts_seen[catg_index].get(halt_id) ) {
|
|
+ consecutive_halts_seen[catg_index].put(halt_id, true);
|
|
+ consecutive_halts[catg_index].append(previous_halt[catg_index]);
|
|
+ }
|
|
+ if( !consecutive_halts_schedule_seen[catg_index].get(halt_id) ) {
|
|
+ consecutive_halts_schedule_seen[catg_index].put(halt_id, true);
|
|
+ consecutive_halts_schedule[catg_index].append(previous_halt[catg_index]);
|
|
+ }
|
|
previous_halt[catg_index] = self;
|
|
}
|
|
}
|
|
@@ -1338,8 +1355,16 @@
|
|
if( current_halt->is_enabled(catg_index) ) {
|
|
// check for consecutive halts which succeed self halt
|
|
if( previous_halt[catg_index] == self ) {
|
|
- consecutive_halts[catg_index].append_unique(current_halt);
|
|
- consecutive_halts_schedule[catg_index].append_unique(current_halt);
|
|
+ uint16 halt_id = current_halt.get_id();
|
|
+ if( !consecutive_halts_seen[catg_index].get(halt_id) ) {
|
|
+ consecutive_halts_seen[catg_index].put(halt_id, true);
|
|
+ consecutive_halts[catg_index].append(current_halt);
|
|
+ }
|
|
+ if( !consecutive_halts_schedule_seen[catg_index].get(halt_id) ) {
|
|
+ consecutive_halts_schedule_seen[catg_index].put(halt_id, true);
|
|
+ consecutive_halts_schedule[catg_index].append(current_halt);
|
|
+ }
|
|
}
|
|
previous_halt[catg_index] = current_halt;
|