(svn r3954) - Explicitly update v->first in TrainConsistChanged() if necessary, as this is far faster than brute forcing it later. 0.4.5
authorDarkvater
Sat, 18 Mar 2006 15:22:27 +0000
branch0.4.5
changeset 9924 0d005642432e
parent 9923 4bafc584ea69
child 9925 30810c6f84c6
(svn r3954) - Explicitly update v->first in TrainConsistChanged() if necessary, as this is far faster than brute forcing it later.
- When loading a game, call TrainConsistChanged() for each train head separately before updating images, as v->first is used extensively in GetTrainImage() for custom graphics. This gives a significant speed improvement on loading a game.
- Rewrite GetFreeUnitNumber() so that only one loop of vehicles is required. Instead a list of used/unused numbers is created and the first unused number is chosen. This significantly improves performance in large games.
- Improve game-load times. Backport of r3570-3572 from trunk
train_cmd.c
vehicle.c
--- a/train_cmd.c	Sat Mar 18 15:19:30 2006 +0000
+++ b/train_cmd.c	Sat Mar 18 15:22:27 2006 +0000
@@ -93,6 +93,9 @@
 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
 		uint16 veh_len;
 
+		// Update the v->first cache. This is faster than having to brute force it later.
+		if (u->first == NULL) u->first = v;
+
 		// update the 'first engine'
 		u->u.rail.first_engine = (v == u) ? INVALID_VEHICLE : first_engine;
 
--- a/vehicle.c	Sat Mar 18 15:19:30 2006 +0000
+++ b/vehicle.c	Sat Mar 18 15:22:27 2006 +0000
@@ -218,6 +218,11 @@
 
 	FOR_ALL_VEHICLES(v) {
 		v->first = NULL;
+		if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v)))
+			TrainConsistChanged(v);
+	}
+
+	FOR_ALL_VEHICLES(v) {
 		if (v->type != 0) {
 			switch (v->type) {
 				case VEH_Train: v->cur_image = GetTrainImage(v, v->direction); break;
@@ -234,9 +239,6 @@
 
 			v->left_coord = INVALID_COORD;
 			VehiclePositionChanged(v);
-
-			if (v->type == VEH_Train && (IsFrontEngine(v) || IsFreeWagon(v)))
-				TrainConsistChanged(v);
 		}
 	}
 }
@@ -1999,20 +2001,42 @@
 
 UnitID GetFreeUnitNumber(byte type)
 {
-	UnitID unit_num = 0;
-	Vehicle *u;
+	UnitID unit, max;
+	const Vehicle *u;
+	static bool *cache = NULL;
+	static UnitID gmax = 0;
 
-restart:
-	unit_num++;
+	switch (type) {
+		case VEH_Train:    max = _patches.max_trains; break;
+		case VEH_Road:     max = _patches.max_roadveh; break;
+		case VEH_Ship:     max = _patches.max_ships; break;
+		case VEH_Aircraft: max = _patches.max_aircraft; break;
+		default: assert(0);
+	}
+
+	if (max > gmax) {
+		gmax = max;
+		free(cache);
+		cache = malloc((max + 1) * sizeof(*cache));
+	}
+
+	// Clear the cache
+	memset(cache, 0, (max + 1) * sizeof(*cache));
+
+	// Fill the cache
 	FOR_ALL_VEHICLES(u) {
-		if (u->type == type && u->owner == _current_player &&
-		    unit_num == u->unitnumber)
-					goto restart;
+		if (u->type == type && u->owner == _current_player && u->unitnumber != 0 && u->unitnumber <= max)
+			cache[u->unitnumber] = true;
 	}
-	return unit_num;
+
+	// Find the first unused unit number
+	for (unit = 1; unit <= max; unit++) {
+		if (!cache[unit]) break;
+	}
+
+	return unit;
 }
 
-
 // Save and load of vehicles
 const SaveLoad _common_veh_desc[] = {
 	SLE_VAR(Vehicle,subtype,					SLE_UINT8),