From 319c12670757595a9a4c3ecd00c4388572ed6ebc Mon Sep 17 00:00:00 2001 From: GoogleFrog Date: Sat, 10 Apr 2021 13:54:15 +1000 Subject: [PATCH] Synced luarules load performance. * wake_fx 2.15 -> 0.001 by making it load wake defs as units are created. There is some ingame overhead on new unit type creation, the code really needs improvement. * unit_target_priority 1.61 -> 0.375 mostly by reducing WeaponDefs access by a factor of #UnitDefs. There are still #UnitDefs*#WeaponDefs entries of the target priority table to generate, so to make this much faster requires pre-loading data generation. * unit_target_features 0.98 -> 0.044 by caching ud.weapons. * unit_show_shooter 0.91 -> 0.05 by caching ud.weapons. --- LuaRules/Configs/target_priority_defs.lua | 123 +++++++++++++++------- LuaRules/Gadgets/unit_show_shooter.lua | 7 +- LuaRules/Gadgets/unit_target_features.lua | 8 +- LuaRules/Gadgets/wake_fx.lua | 96 +++++++++-------- 4 files changed, 143 insertions(+), 91 deletions(-) diff --git a/LuaRules/Configs/target_priority_defs.lua b/LuaRules/Configs/target_priority_defs.lua index 4d11ef2355..d643f4a2cf 100644 --- a/LuaRules/Configs/target_priority_defs.lua +++ b/LuaRules/Configs/target_priority_defs.lua @@ -5,23 +5,34 @@ local DISARM_BASE = 0.3 local DISARM_ADD = 0.2 local DISARM_ADD_TIME = 10*30 -- frames -local weaponBadCats = {} +local weaponBadCats_fixedwing = {} +local weaponBadCats_gunship = {} +local weaponBadCats_ground = {} +local weaponBadCats_heavy = {} local weaponIsAA = {} -for wid = 1, #WeaponDefs do - weaponBadCats[wid] = {} -end +local wdCount = #WeaponDefs +local udCount = #UnitDefs + +--local lastTime = Spring.GetTimer() +--local function Time(name) +-- local timeDiff = Spring.DiffTimers(Spring.GetTimer(), lastTime) +-- Spring.Echo(name, timeDiff) +-- lastTime = Spring.GetTimer() +--end + +--Time("START TARGET PRIORITY DEFS") -- Find the weapon bad target cats -for i=1, #UnitDefs do +for i = 1, udCount do local ud = UnitDefs[i] local weapons = ud.weapons for j = 1, #weapons do local wd = weapons[j] local realWD = wd.weaponDef if wd.badTargets and realWD ~= 0 then - weaponBadCats[realWD].fixedwing = wd.badTargets["fixedwing"] - weaponBadCats[realWD].gunship = wd.badTargets["gunship"] + weaponBadCats_fixedwing[realWD] = wd.badTargets["fixedwing"] + weaponBadCats_gunship[realWD] = wd.badTargets["gunship"] end if wd.customParams and realWD ~= 0 and wd.customParams.isaa then weaponIsAA[realWD] = true @@ -29,12 +40,14 @@ for i=1, #UnitDefs do end end +--Time("Find bad target cats") + -- Find the things which are fixedwing or gunship local unitIsGunship = {} local unitIsFixedwing = {} local unitIsGround = {} local getMovetype = Spring.Utilities.getMovetype -for i=1, #UnitDefs do +for i = 1, udCount do local ud = UnitDefs[i] local unitType = getMovetype(ud) --1 gunship, 0 fixedplane, 2 ground/sea, false everything-else if unitType == 1 then @@ -46,9 +59,11 @@ for i=1, #UnitDefs do end end +--Time("Find fixedwing or gunship") + -- Find the things which are unarmed local unitIsUnarmed = {} -for i=1, #UnitDefs do +for i = 1, udCount do local ud = UnitDefs[i] local weapons = ud.weapons if (not weapons or #weapons == 0) and not ud.canKamikaze then @@ -56,6 +71,8 @@ for i=1, #UnitDefs do end end +--Time("Find unitIsUnarmed") + -- Don't shoot at fighters or drones, they are unimportant. local unitIsFighterOrDrone = { [UnitDefNames["planefighter"].id] = true, @@ -207,6 +224,8 @@ local gravityWeaponDefs = { [WeaponDefNames["jumpsumo_gravity_pos"].id] = true, } +--Time("Load tables") + -- for heatrays local proximityWeaponDefs = {} for wdid = 1, #WeaponDefs do @@ -218,6 +237,8 @@ for wdid = 1, #WeaponDefs do end end +--Time("Find heatrays") + local radarWobblePenalty = { [WeaponDefNames["vehheavyarty_cortruck_rocket"].id] = 5, -- [WeaponDefNames["shipcarrier_armmship_rocket"].id] = 5, @@ -231,49 +252,67 @@ local radarDotPenalty = { [WeaponDefNames["shieldarty_emp_rocket"].id] = 100, } -for i = 1, #UnitDefs do +--Time("Load more tables") + +for i = 1, udCount do local ud = UnitDefs[i] if unitIsBadAgainstGround[i] then local weapons = ud.weapons for j = 1, #weapons do local wd = weapons[j] local realWD = wd.weaponDef - weaponBadCats[realWD].ground = true + weaponBadCats_ground[realWD] = true end elseif unitIsHeavyHitter[i] then local weapons = ud.weapons for j = 1, #weapons do local wd = weapons[j] local realWD = wd.weaponDef - weaponBadCats[realWD].cheap = true - weaponBadCats[realWD].heavy = true + weaponBadCats_heavy[realWD] = true end end end +--Time("Load more weaponBadCats") + -- Generate transport unit table local transportMult = {} -for uid = 1, #UnitDefs do +for uid = 1, udCount do local ud = UnitDefs[uid] if ud.isTransport then transportMult[uid] = 0.98 -- Priority multiplier for transported unit. end end +--Time("Generate transport") + +-- Reduce WeaponDefs access from #UnitDefs*#WeaponDefs to #WeaponDefs +local weaponDamage = {} +for wid = 1, wdCount do + local wd = WeaponDefs[wid] + weaponDamage[wid] = wd.damages +end + +--Time("Reduce WeaponDefs access") + -- Generate full target table local targetTable = {} -for uid = 1, #UnitDefs do +local priority, damage +for uid = 1, udCount do local ud = UnitDefs[uid] local unitHealth = ud.health - local unitCost = ud.buildTime + local inverseUnitCost = 1 / ud.buildTime local armorType = ud.armorType targetTable[uid] = {} - for wid = 1, #WeaponDefs do - local wd = WeaponDefs[wid] - local damage = wd.damages[armorType] - local priority = math.max(damage, unitHealth)/unitCost + for wid = 1, wdCount do + damage = weaponDamage[wid][armorType] + if damage > unitHealth then + priority = damage * inverseUnitCost + else + priority = unitHealth * inverseUnitCost + end if priority > 12 then priority = 12 + 0.1*priority end @@ -282,30 +321,33 @@ for uid = 1, #UnitDefs do targetTable[uid][wid] = priority + 35 elseif unitIsClaw[uid] then targetTable[uid][wid] = priority + 1000 - elseif (weaponBadCats[wid].fixedwing and unitIsFixedwing[uid]) - or (weaponBadCats[wid].gunship and unitIsGunship[uid]) - or (weaponBadCats[wid].ground and unitIsGround[uid]) then - targetTable[uid][wid] = priority + 15 + elseif (weaponBadCats_fixedwing[wid] and unitIsFixedwing[uid]) or (weaponBadCats_gunship[wid] and unitIsGunship[uid]) or (weaponBadCats_ground[wid] and unitIsGround[uid]) then + targetTable[uid][wid] = priority + 15 elseif (unitIsFighterOrDrone[uid]) then - --or (weaponBadCats[wid].cheap and unitIsCheap[uid]) then - targetTable[uid][wid] = priority + 10 - elseif (unitIsBomber[uid] and weaponIsAA[wid]) - or (weaponBadCats[wid].heavy and unitIsHeavy[uid]) then + targetTable[uid][wid] = priority + 10 + elseif (unitIsBomber[uid] and weaponIsAA[wid]) or (weaponBadCats_heavy[wid] and unitIsHeavy[uid]) then targetTable[uid][wid] = priority*0.3 else targetTable[uid][wid] = priority end - - -- Autogenerate some wobble penalties. - if not radarWobblePenalty[wid] then - local weaponType = wd.type - if weaponType == "BeamLaser" or weaponType == "LaserCannon" or weaponType == "LightningCannon" then - radarWobblePenalty[wid] = 5 - end + end +end + +--Time("Generate full target table") + +-- Autogenerate some wobble penalties. +for wid = 1, wdCount do + if not radarWobblePenalty[wid] then + local wd = WeaponDefs[wid] + local wType = wd.type + if wType == "BeamLaser" or wType == "LaserCannon" or wType == "LightningCannon" then + radarWobblePenalty[wid] = 5 end end end +--Time("Autogenerate some wobble penalties") + -- Modify the velocity penalty defs to implement 'additional penantly per excess velocity' for weaponDefID, data in pairs(velocityPenaltyDefs) do data[2] = data[2] or VEL_DEFAULT_BASE @@ -314,13 +356,18 @@ for weaponDefID, data in pairs(velocityPenaltyDefs) do data[2] = data[2] - data[1]*data[3] end +--Time("Modify the velocity penalty") + local reloadTimeAlpha = 1.8 --seconds, matches Ripper's reload time local highAlphaWeaponDamages = {} -for wid = 1, #WeaponDefs do +for wid = 1, wdCount do local wd = WeaponDefs[wid] - if wd.customParams and wd.customParams.shot_damage and wd.reload >= reloadTimeAlpha then - highAlphaWeaponDamages[wid] = tonumber(wd.customParams.shot_damage) + local shotDamage = wd.customParams and wd.customParams.shot_damage + if shotDamage and wd.reload >= reloadTimeAlpha then + highAlphaWeaponDamages[wid] = tonumber(shotDamage) end end +--Time("highAlphaWeaponDamages") + return targetTable, disarmWeaponTimeDefs, disarmPenaltyDefs, captureWeaponDefs, gravityWeaponDefs, proximityWeaponDefs, velocityPenaltyDefs, radarWobblePenalty, radarDotPenalty, transportMult, highAlphaWeaponDamages, DISARM_BASE, DISARM_ADD, DISARM_ADD_TIME diff --git a/LuaRules/Gadgets/unit_show_shooter.lua b/LuaRules/Gadgets/unit_show_shooter.lua index 1a55d92efa..584c7d4072 100644 --- a/LuaRules/Gadgets/unit_show_shooter.lua +++ b/LuaRules/Gadgets/unit_show_shooter.lua @@ -45,10 +45,11 @@ end for i = 1, #UnitDefs do local ud = UnitDefs[i] - if ud.weapons then + local weapons = ud.weapons + if weapons then immobileUnits[i] = true - for j = 1, #ud.weapons do - local weaponDefID = ud.weapons[j].weaponDef + for j = 1, #weapons do + local weaponDefID = weapons[j].weaponDef if fakeWeapons[weaponDefID] then fakeWeaponByNum[i] = fakeWeaponByNum[i] or {} fakeWeaponByNum[i][j] = true diff --git a/LuaRules/Gadgets/unit_target_features.lua b/LuaRules/Gadgets/unit_target_features.lua index d4dfce8e7b..c4dc3cf430 100644 --- a/LuaRules/Gadgets/unit_target_features.lua +++ b/LuaRules/Gadgets/unit_target_features.lua @@ -41,12 +41,12 @@ local ignoreGroundWeapons = {} for i = 1, #UnitDefs do local ud = UnitDefs[i] - local weapons = (ud.weapons and #ud.weapons > 0 and #ud.weapons) - if weapons then + local weapons = ud.weapons + if weapons and #weapons > 0 then weaponCounts[i] = weapons local ignoreGround - for j = 1, weapons do - local weaponDefID = ud.weapons[j].weaponDef + for j = 1, #weapons do + local weaponDefID = weapons[j].weaponDef local weaponParam = WeaponDefs[weaponDefID].customParams or {} if weaponParam.force_ignore_ground then ignoreGround = ignoreGround or {} diff --git a/LuaRules/Gadgets/wake_fx.lua b/LuaRules/Gadgets/wake_fx.lua index ca7ea5e6d6..7e94997b64 100644 --- a/LuaRules/Gadgets/wake_fx.lua +++ b/LuaRules/Gadgets/wake_fx.lua @@ -26,63 +26,65 @@ local fold_frames = 7 -- every seventh frame local n_folds = 4 -- check every fourth unit local current_fold = 1 -local spGetUnitIsCloaked = Spring.GetUnitIsCloaked -local spGetUnitPosition = Spring.GetUnitPosition -local spGetUnitVelocity = Spring.GetUnitVelocity +local spGetUnitIsCloaked = Spring.GetUnitIsCloaked +local spGetUnitPosition = Spring.GetUnitPosition +local spGetUnitVelocity = Spring.GetUnitVelocity +local spGetUnitDefDimensions = Spring.GetUnitDefDimensions local spusCallAsUnit = Spring.UnitScript.CallAsUnit local spusEmitSfx = Spring.UnitScript.EmitSfx local wadeDepth = {} local wadeSfxID = {} -do - local smc = Game.speedModClasses - local wadingSMC = { - [smc.Tank] = true, - [smc.KBot] = true, - } - local SFXTYPE_WAKE1 = 2 - local SFXTYPE_WAKE2 = 3 - - local UD = UnitDefs - local function checkCanWade(unitDef) - local moveDef = unitDef.moveDef - if not moveDef then - return false - end - - local smClass = moveDef.smClass - if not smClass or not wadingSMC[smClass] then - return false - end - return true +local smc = Game.speedModClasses +local wadingSMC = { + [smc.Tank] = true, + [smc.KBot] = true, +} +local SFXTYPE_WAKE1 = 2 +local SFXTYPE_WAKE2 = 3 + +local function checkCanWade(unitDef) + local moveDef = unitDef.moveDef + if not moveDef then + return false end + local smClass = moveDef.smClass + if not smClass or not wadingSMC[smClass] then + return false + end + return true +end - local spGetUnitDefDimensions = Spring.GetUnitDefDimensions - for unitDefID = 1, #UD do - local unitDef = UD[unitDefID] - if checkCanWade(unitDef) then - wadeDepth[unitDefID] = -spGetUnitDefDimensions(unitDefID).height - - local cpR = unitDef.customParams.modelradius - local r = cpR and tonumber(cpR) or unitDef.radius - wadeSfxID[unitDefID] = (((r > 50) or unitDef.customParams.floattoggle) and SFXTYPE_WAKE2) or SFXTYPE_WAKE1 - else - -- there are ~400 wadables but the highest one's ID is >512, so we also assign `false` - -- instead of keeping them `nil` to keep the internal representation an array (faster) - wadeDepth[unitDefID] = false - wadeSfxID[unitDefID] = false - end +local function GetUnitWakeParams(unitDefID) + if wadeDepth[unitDefID] ~= nil then + return wadeDepth[unitDefID], wadeSfxID[unitDefID] + end + + local unitDef = UnitDefs[unitDefID] + if checkCanWade(unitDef) then + wadeDepth[unitDefID] = -spGetUnitDefDimensions(unitDefID).height + + local cpR = unitDef.customParams.modelradius + local r = cpR and tonumber(cpR) or unitDef.radius + wadeSfxID[unitDefID] = (((r > 50) or unitDef.customParams.floattoggle) and SFXTYPE_WAKE2) or SFXTYPE_WAKE1 + else + -- there are ~400 wadables but the highest one's ID is >512, so we also assign `false` + -- instead of keeping them `nil` to keep the internal representation an array (faster) + wadeDepth[unitDefID] = false + wadeSfxID[unitDefID] = false end + + return wadeDepth[unitDefID], wadeSfxID[unitDefID] end function gadget:UnitCreated(unitID, unitDefID) - local maxDepth = wadeDepth[unitDefID] + local maxDepth, fxID = GetUnitWakeParams(unitDefID) if maxDepth then unitsCount = unitsCount + 1 unitsData[unitsCount] = unitID - unit[unitID] = {id = unitsCount, h = maxDepth, fx = wadeSfxID[unitDefID]} + unit[unitID] = {id = unitsCount, h = maxDepth, fx = fxID} end end @@ -108,11 +110,13 @@ function gadget:GameFrame(n) local x,y,z = spGetUnitPosition(unitID) local h = data.h - local _, _, _, speed = spGetUnitVelocity(unitID) - if speed and y > h and y <= 0 and speed > 0 and not spGetUnitIsCloaked(unitID) then - -- 1 is the pieceID, most likely it's usually the base piece - -- but even if it isn't, it doesn't really matter - spusCallAsUnit(unitID, spusEmitSfx, 1, data.fx) + if y and h and y > h and y <= 0 and not spGetUnitIsCloaked(unitID) then + local _, _, _, speed = spGetUnitVelocity(unitID) + if speed and speed > 0 then + -- 1 is the pieceID, most likely it's usually the base piece + -- but even if it isn't, it doesn't really matter + spusCallAsUnit(unitID, spusEmitSfx, 1, data.fx) + end end end current_fold = (current_fold % n_folds) + 1