From c0d71b84f983070462a83cc60a17083d5ede4e50 Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 4 Mar 2009 23:32:23 +0000 Subject: (svn r15617) -Change [FS#2694]: vehicle variables 40-43 weren't cached (though spec stated they are). Caching these variables can yield a 10+% speed increase when those vehicle variables are queried often. --- src/misc_cmd.cpp | 7 +++ src/newgrf_engine.cpp | 150 +++++++++++++++++++++++++++++--------------------- src/train_cmd.cpp | 3 + src/vehicle_base.h | 6 ++ 4 files changed, 104 insertions(+), 62 deletions(-) diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index d12b57743..aeda6f754 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -19,6 +19,7 @@ #include "company_base.h" #include "company_gui.h" #include "settings_type.h" +#include "vehicle_base.h" #include "table/strings.h" @@ -118,6 +119,12 @@ CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1, } ResetVehicleColourMap(); MarkWholeScreenDirty(); + + /* Company colour data is indirectly cached. */ + Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->owner == _current_company) v->cache_valid = 0; + } } return CommandCost(); } diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 2d4a5bcef..eb2e6d011 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -442,10 +442,35 @@ static uint8 LiveryHelper(EngineID engine, const Vehicle *v) return l->colour1 + l->colour2 * 16; } +/** + * Helper to get the position of a vehicle within a chain of vehicles. + * @param v the vehicle to get the position of. + * @param consecutive whether to look at the whole chain or the vehicles + * with the same 'engine type'. + * @return the position in the chain from front and tail and chain length. + */ +static uint32 PositionHelper(const Vehicle *v, bool consecutive) +{ + const Vehicle *u; + byte chain_before = 0; + byte chain_after = 0; + + for (u = v->First(); u != v; u = u->Next()) { + chain_before++; + if (consecutive && u->engine_type != v->engine_type) chain_before = 0; + } + + while (u->Next() != NULL && (!consecutive || u->Next()->engine_type == v->engine_type)) { + chain_after++; + u = u->Next(); + } + + return chain_before | chain_after << 8 | (chain_before + chain_after + consecutive) << 16; +} static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, byte parameter, bool *available) { - const Vehicle *v = GRV(object); + Vehicle *v = const_cast(GRV(object)); if (v == NULL) { /* Vehicle does not exist, so we're in a purchase list */ @@ -476,80 +501,81 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by /* Calculated vehicle parameters */ switch (variable) { case 0x40: // Get length of consist + if (!HasBit(v->cache_valid, 0)) { + v->cached_var40 = PositionHelper(v, false); + SetBit(v->cache_valid, 0); + } + return v->cached_var40; + case 0x41: // Get length of same consecutive wagons - { - const Vehicle *u; - byte chain_before = 0; - byte chain_after = 0; + if (!HasBit(v->cache_valid, 1)) { + v->cached_var41 = PositionHelper(v, true); + SetBit(v->cache_valid, 1); + } + return v->cached_var41; - for (u = v->First(); u != v; u = u->Next()) { - chain_before++; - if (variable == 0x41 && u->engine_type != v->engine_type) chain_before = 0; + case 0x42: // Consist cargo information + if (!HasBit(v->cache_valid, 2)) { + const Vehicle *u; + byte cargo_classes = 0; + CargoID common_cargo_best = CT_INVALID; + uint8 common_cargos[NUM_CARGO]; + uint8 common_subtype_best = 0xFF; // Return 0xFF if nothing is carried + uint8 common_subtypes[256]; + byte user_def_data = 0; + CargoID common_cargo_type = CT_PASSENGERS; + uint8 common_subtype = 0; + + /* Reset our arrays */ + memset(common_cargos, 0, sizeof(common_cargos)); + memset(common_subtypes, 0, sizeof(common_subtypes)); + + for (u = v; u != NULL; u = u->Next()) { + if (v->type == VEH_TRAIN) user_def_data |= u->u.rail.user_def_data; + + /* Skip empty engines */ + if (u->cargo_cap == 0) continue; + + cargo_classes |= GetCargo(u->cargo_type)->classes; + common_cargos[u->cargo_type]++; } - while (u->Next() != NULL && (variable == 0x40 || u->Next()->engine_type == v->engine_type)) { - chain_after++; - u = u->Next(); + /* Pick the most common cargo type */ + for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) { + if (common_cargos[cargo] > common_cargo_best) { + common_cargo_best = common_cargos[cargo]; + common_cargo_type = cargo; + } } - return chain_before | chain_after << 8 | (chain_before + chain_after + (variable == 0x41)) << 16; - } + /* Count subcargo types of common_cargo_type */ + for (u = v; u != NULL; u = u->Next()) { + /* Skip empty engines and engines not carrying common_cargo_type */ + if (u->cargo_cap == 0 || u->cargo_type != common_cargo_type) continue; - case 0x42: { // Consist cargo information - const Vehicle *u; - byte cargo_classes = 0; - CargoID common_cargo_best = CT_INVALID; - uint8 common_cargos[NUM_CARGO]; - uint8 common_subtype_best = 0xFF; // Return 0xFF if nothing is carried - uint8 common_subtypes[256]; - byte user_def_data = 0; - CargoID common_cargo_type = CT_PASSENGERS; - uint8 common_subtype = 0; - - /* Reset our arrays */ - memset(common_cargos, 0, sizeof(common_cargos)); - memset(common_subtypes, 0, sizeof(common_subtypes)); - - for (u = v; u != NULL; u = u->Next()) { - if (v->type == VEH_TRAIN) user_def_data |= u->u.rail.user_def_data; - - /* Skip empty engines */ - if (u->cargo_cap == 0) continue; - - cargo_classes |= GetCargo(u->cargo_type)->classes; - common_cargos[u->cargo_type]++; - } - - /* Pick the most common cargo type */ - for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) { - if (common_cargos[cargo] > common_cargo_best) { - common_cargo_best = common_cargos[cargo]; - common_cargo_type = cargo; + common_subtypes[u->cargo_subtype]++; } - } - - /* Count subcargo types of common_cargo_type */ - for (u = v; u != NULL; u = u->Next()) { - /* Skip empty engines and engines not carrying common_cargo_type */ - if (u->cargo_cap == 0 || u->cargo_type != common_cargo_type) continue; - common_subtypes[u->cargo_subtype]++; - } - - /* Pick the most common subcargo type*/ - for (uint i = 0; i < lengthof(common_subtypes); i++) { - if (common_subtypes[i] > common_subtype_best) { - common_subtype_best = common_subtypes[i]; - common_subtype = i; + /* Pick the most common subcargo type*/ + for (uint i = 0; i < lengthof(common_subtypes); i++) { + if (common_subtypes[i] > common_subtype_best) { + common_subtype_best = common_subtypes[i]; + common_subtype = i; + } } - } - uint8 common_bitnum = (common_cargo_type == CT_INVALID ? 0xFF : GetCargo(common_cargo_type)->bitnum); - return cargo_classes | (common_bitnum << 8) | (common_subtype << 16) | (user_def_data << 24); - } + uint8 common_bitnum = (common_cargo_type == CT_INVALID ? 0xFF : GetCargo(common_cargo_type)->bitnum); + v->cached_var42 = cargo_classes | (common_bitnum << 8) | (common_subtype << 16) | (user_def_data << 24); + SetBit(v->cache_valid, 2); + } + return v->cached_var42; case 0x43: // Company information - return v->owner | (GetCompany(v->owner)->is_ai ? 0x10000 : 0) | (LiveryHelper(v->engine_type, v) << 24); + if (!HasBit(v->cache_valid, 3)) { + v->cached_var43 = v->owner | (GetCompany(v->owner)->is_ai ? 0x10000 : 0) | (LiveryHelper(v->engine_type, v) << 24); + SetBit(v->cache_valid, 3); + } + return v->cached_var43; case 0x44: // Aircraft information if (v->type != VEH_AIRCRAFT) return UINT_MAX; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 008cbfb42..d327c3f3a 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -257,11 +257,13 @@ void TrainConsistChanged(Vehicle *v, bool same_length) /* Set user defined data to its default value */ u->u.rail.user_def_data = rvi_u->user_def_data; + u->cache_valid = 0; } for (Vehicle *u = v; u != NULL; u = u->Next()) { /* Update user defined data (must be done before other properties) */ u->u.rail.user_def_data = GetVehicleProperty(u, 0x25, u->u.rail.user_def_data); + u->cache_valid = 0; } for (Vehicle *u = v; u != NULL; u = u->Next()) { @@ -347,6 +349,7 @@ void TrainConsistChanged(Vehicle *v, bool same_length) if (!same_length) u->u.rail.cached_veh_length = veh_len; v->u.rail.cached_total_length += u->u.rail.cached_veh_length; + u->cache_valid = 0; } /* store consist weight/max speed in cache */ diff --git a/src/vehicle_base.h b/src/vehicle_base.h index a1ff402da..b4ae0be97 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -323,6 +323,12 @@ public: VehicleShip ship; } u; + /* cached oftenly queried NewGRF values */ + uint8 cache_valid; ///< Whether the caches are valid + uint32 cached_var40; ///< Cache for NewGRF var 40 + uint32 cached_var41; ///< Cache for NewGRF var 41 + uint32 cached_var42; ///< Cache for NewGRF var 42 + uint32 cached_var43; ///< Cache for NewGRF var 43 /** * Allocates a lot of vehicles. -- cgit v1.2.3-54-g00ecf