A new player by the name of constrat reported some increased lag with Rev 1.4/1.5 on steam. We got talking and it turns out he has quite a special case. He has over 200 land turrets!
Now, this is a pretty good stress test case, and I’d been meaning to explore an avenue of potential performance increase.
One of the speed-ups I mentioned in earlier posts was to use x^0.5 instead of math.sqrt(x). One of the reasons that math.sqrt(x) is slightly slower partly because it involves a call out of lua into the native math library in C. The extra function call, and boxing/unboxing of the values adds some overhead.
Looking at CC2, the lua scripting makes heavy use of vehicle objects. These are all implemented in C/C++, calls from lua to the various methods on these objects reach down into the native code. This is generally pretty fast, but what if we could cache these?
In my previous post I got a significant speedup by using my new get_vehicles_table() function. Returning only one copy of each unit in a fast-to-iterate table.
get_vehicles_table() turns out to be a pretty good spot to try something clever!
I have created a proxy class for vehicles that I call VProxy. get_vehicles_table() now returns instances of this class.
In here, I can cache a lot of stuff right away. I can store things like the unit type (definition_index), it’s location, waypoint counts etc. I can store these in my lua object, and add methods for all the various real vehicle functions.
552 lines of lua later and we have it working!
Using my perftest map and call timer. With the original vehicle objects (plus some minor speedups) I get:
start timer 3 1752189005 10748
done timer 1752189025
calls 8607
calls/sec 430.35
Using my new proxy objects instead, and using the same map/timings I now get:
start timer 3 1752189090 12589
done timer 1752189110
calls 13522
calls/sec 676.1
Holy rusty metal Batman! a 57% speed increase!
It’s not simply caching calls into the native layer that got this speed up. Having a lua object means I can cache a lot more of the revolution extra computation onto each object.
Previously, to find out if a unit had a RADAR fitted, I would look at the unit’s attachment points each time. With the proxy object I can now do this once and cache the result for the rest of the tick. This is especially a benefit as things like “is this seen by a radar?” checks are all over the place. I can now cache all of these in the proxy object.
There were a few other things that are slow-ish in lua that I mentioned before. Use of the local keyword can speed things up. Partly this is due to local things being on the stack, but also partly that it is faster to lookup stack variables than it is to lookup globals.
It is also pretty slow to use the “index” accessor of a table.
Previously I had some caches that were global tables indexed by vehicle ID. I would access them like so:
function _get_is_seen_by_friendly_modded_radar(vehicle)
if vehicle and vehicle:get() then
local vid = vehicle:get_id()
local exists = g_seen_by_friendly_radars[vid]
if exists ~= nil then
return true
end
end
return false
end
The g_seen_by_friendly_radars line is actually quite slow
But with my new proxy object I can cache all this in one place!
function _get_is_seen_by_friendly_modded_radar(vehicle)
if vehicle and vehicle:get() then
if vehicle.extended then
return vehicle:get_is_seen_by_friendly_modded_radar()
end
local vid = vehicle:get_id()
local exists = g_seen_by_friendly_radars[vid]
if exists ~= nil then
return true
end
end
return false
Here, if I am handed one of my new objects (test for vehicle.extended being non nil) I can just call a method and get a cached value after the first call.

For now this is in my experimental branch as there are at least 260 calls to vehicle objects in the vehicle control screen alone. I need to be sure I’ve proxied and cached them correctly in all cases before this goes live.
Fly safe!



2 responses to “Even More Optimal!”
[…] the progress recently and you can read back about my experiments along the way in earlier posts Even More Optimal! and Beta 2 […]
LikeLike
[…] my Even More Optimal! post, I show Rev 1.5 clocking in on my test map and test call at about 676 calls per second as a […]
LikeLike