Download

Can a function execute over more than one tick to save performance?

I have a fairly simple function that regularly needs to run once for every character in my game, and since I have thousands of characters it can quickly add up. Is there any simple way I can configure it so instead of executing in one big lump, it kind of trickles in the background and resolves for a handful of characters every tick until it’s finished?

If you keep a list or array of all of your characters, then you could keep a variable that contains the last index looked at (let’s call it N, and set it to 0 at game start) and another variable for max characters per tick (let’s call it X). Start at index N, and execute your function X times, then store the index number you stopped at + 1 in N. Next tick, just run the same code again.

You’ll need to do some array bounds checking and such so you don’t run beyond the end of the array, and when you get to the end, reset N to 0 again. Miscellaneous housekeeping like that.

It’s a pretty naive algorithm, but it might work in a pinch.

Hmm, that’s an interesting idea… is there any way to keep it out of tick, though? This will likely only need to run once a minute, if that, so even with thousands of characters, it would end up cycling through all of them within a few seconds, then checking itself every tick for 45-50 second without anything to do.

you are asking for multi-threading. there is the task graph system https://wiki.unrealengine.com/Multi-Threading:_Task_Graph_System

Perhaps a timer then? I’m not overly familiar with them in a C++ context, but I know you can set them up to fire at whatever interval you choose. Here’s some official doc info on them. Steps 5 and 6 show you how to set one up.

Ooh the timer will probably do it perfectly, thank you!!

Timers ‘tick’ internally anyway, they’re just managed by a single ticking object.

Timers will help you schedule when a function is executed but if the function call itself is expensive then it won’t solve your problem. IE if the function is a loop that iterates over 1000 characters like you subscribed, even if you execute it only once per second it will give a performance spike every second. What you can do is move the body of the loop to a separate function and schedule that using timers, for example: process character 1 in 0.1 seconds, process character 2 in 0.2 seconds, etc. That would achieve what you want but keep in mind that starting many timers will affect performance as well.

Ideally you schedule the character processing in batches, i.e. starting a timer that processes the first 100 characters, then one that processes the second 200, and so on and make sure the timers don’t fire in the same frame.

NissjokuZk is right.

IF you have a poorly written function when it fires its going to lag your game.

I once made game map generator, and when I attempted to generate the whole map in one frame it ran like ****.
Crashed, would not even work at all on big maps.

But when I stopped to think about how much work I need to do each frame and instead started to build the map in sections over a period of frame…
Performance skyrocked and I gained the ability to support very large maps.

So… In short… look at what your doing overall and see if you can break it down to small work loads over a period of frames.

The best approach to splitting the work up is still to iterate over the array one chunk at a time. Timers are all well and good but have overhead of their own and in this case, will be more difficult to manage. They will also, stack up over time if your frames are dropping.

This is so easy to do I even typed the code out below, which is like 10 lines. You set the amount of objects you want to iterate over in one frame, say 50. Each tick, you iterate over 50 objects and store the last index you used. You then Iterate the next fifty objects.



for (int i = 0; i < LastIndex + NumObjectsPerTick; i++)
{
    // Do Stuff

    if (i = LastIndex + NumObjectsPerTick)
    {
         LastIndex = i;
    }
}


Man, there’s a lot more to this than I originally thought; I seriously underestimated how much consideration the performance on timers bears. Your array-based approach is a great idea, I realy appreciate your taking the time to expand on it like that! :slight_smile:

Why not just do what we do in database world and make a queue.

You make a list of items to process, and when new stuff comes in you add it to the end of the list, and when you need to process the next thing, you take one off the top of the list.

That means your “queue” will need to be able to grow/shrink and/or be maanged, but it is the best practice way to process items the way you describe.

If said items are atomic (i.e. self contained) then this is also a good place to “multithread” as well.

The other suggestion of batching is also great if you simply want it to work ASAP.

The hardest part is getting to know:

How many items per tick (X)
How many items roughly in total (Y)

just to make sure Y / X == batches AND

Process all Batches time < total time you want to spend processing everything each time