Opened 3 years ago

Last modified 2 years ago

#5962 new enhancement

UnitAI Gathering optimisations

Reported by: wraitii Owned by:
Priority: Should Have Milestone: Backlog
Component: Simulation Keywords: performance, simple
Cc: Patch:

Description

UnitAI's "GATHER.GATHERING" is called often (1/rate, which is around once per second) for each gathering entity. Because it does a fair few computations in its Timer Handler (checking if we still can gather, checking the range, gathering, possibly doing some dropsite related checks), it ends up being a large part of the sim Update in the late game (easily taking upwards of 10ms/frame).

There are two main things we could do:

  • Avoid sending 2 messages in Perform Gather (resource Carrying & resource Supply changes). Only AIProxy subscribes, and the messages are usually redundant because multiple entities generally gather from one Supply. From profiling I'd guess this cuts time by ~10-20%.
    • Here the solution would be to dynamically subscribe resourceSupply/Gatherer AIProxy (_maybe_ just supply) so that on turn's end, it queries its state and sends it to the AI. Avoids redundant work. When playing with no AI, could be de-activated entirely.
  • Increase the timer interval. We currently collect one resource each "timer", but we could run the timer 2x less often and just collect 2 resources. I think given the capacities our entities have, this would be a good optimisation, effectively reducing work by 2x, and thus possibly saving up to 50% computation time.

Change History (8)

comment:1 by wraitii, 3 years ago

(Note that this is a particularly bad problem in MP, because 500ms turns means that timers fire almost every turn for each entity, meaning there is very little 'smoothing' effect from doing X% of entities every turn, unlike in SP where 200ms turns means that any individual turn is faster even if the total computation cost isn't decreased).

comment:2 by Freagarach, 3 years ago

(Do notice carrying capacity is increased by 5 on storehouse techs.)

comment:3 by Silier, 3 years ago

Component: UI & SimulationSimulation

comment:4 by wraitii, 3 years ago

Milestone: Alpha 25Alpha 26

I think the 500->200ms turn change has indirectly helped with this. Pushing & should be reevaluated for A26

comment:5 by Silier, 3 years ago

Keywords: simple removed
severity: simple

comment:6 by Silier, 3 years ago

Keywords: simple added

comment:7 by wraitii, 2 years ago

In 26274:

Run the AI in the same Compartment as the simulation. Let the AI access Sim data.

This is a paradigm change for AI computation.
Historically, the AI was intended to be run in a separate thread from the simulation. The idea was that slow AI wouldn't stop the renderer from being smooth.

In that original design, the AI received a copy of the game world and used that to run its logic. This meant the simulation could safely do whatever it wanted in the meantime. This copy was done via AIProxy & AIInterface.

This design ended up having significant flaws:

  • The copying impacts the simulation negatively, particularly because AIProxy subscribes to a lot of messages (sometimes sent exclusively to it). This time cannot be threaded, and impacts MP games without AIs.
  • Copying the data is increasingly difficult. Modifiers are a headache, LOS is not implemented. Lots of logic is duplicated.

The intended benefits of the design also failed to realise somewhat:

  • The AI was never threaded, and in fact, it is probably better to try and thread Sim + AI from the renderer than just the AI, at which point threading the AI specifically brings little benefit.

The new design is much simpler and straighforward, but this has some side-effects:

  • The AI can now change the simulation. This can be used for cheating, or possibly for a tutorial AI.
  • The AI runs in the same GC zone as the simulation, which may lead to more frequent Sim GCs (but overall we might expect a reduction in temporary objects).
  • The AI state was essentially cached, so replacing some functions with Engine.QueryInterface might be slower. The tradeoff should be balanced by lower AIProxy computation times.

Future work:

  • Threading some specific AI tasks could still be worthwhile, but should be done in specific worker threads, allowed to run over several turns if needed.

Technical note: the AI 'global' is in its own Realm, which means name collisions with the same are not possible.

Other notes:

  • The RL Interface uses the AI Interface and thus will gradually lose some data there. Given that the RL Interface can now request data however, this should be dine.

Refs #5962, #2370

Differential Revision: https://code.wildfiregames.com/D3769

comment:8 by Freagarach, 2 years ago

Milestone: Alpha 26Backlog
Note: See TracTickets for help on using tickets.