Functions inefficient *

Discussion and feedback on Construct 2

Post » Sun Nov 08, 2015 10:25 pm

Howdy,

I've been playing around with event based procedual terrain generation and I noticed something interesting.

A function impacts performance up to 5x more than another simple event call (calling function vs Adding to avariable, for example). The more you do within the function the less that becomes in relation. But if you call a function simply to perform 1-2 events, just copying and pasting those 1-2 events saves mucho cpu time, if you do this many times.

I'm not sure why the performance hit is so great, but once a game is all done and made, if you have performance issues you may try replacing function calls with the code. This makes your code base unmaintainable and awful to look at but you can gain a bit of performance by doing it. This should only* be considered if you are struggling with performance and have eliminated other bottlenecks. Obviously if you have 1000 physics based objects, you may find that reducing function calls is a waste of time in the grand scheme of things.

Better yet, use the event system only to tie scripts together. Do everything else in scripts. That saves over 9000, a whopping 500% to 1000 points more . Ya..


I often like to make dynamic function call systems in placement of switch statements (as construct has none) and event driven dispatch systems, but this may not be as efficient as simply going through a giant condition list. :(
Last edited by ruskul on Wed Nov 11, 2015 5:35 pm, edited 2 times in total.
Image
B
33
S
11
G
2
Posts: 564
Reputation: 5,173

Post » Sun Nov 08, 2015 11:06 pm

I think it depends more on what you are doing in the function call.
It's basically telling the cpu hey drop what you are doing, and do this, then do pick up where you left off.
Image ImageImage
B
172
S
50
G
182
Posts: 8,439
Reputation: 115,097

Post » Sun Nov 08, 2015 11:08 pm

That's crazy. That's incredibly crazy. Can you provide a capx. I would like to see this. I'm not not believing you. But wow. yeah. I've come across other performance hitting issues that stand out in C2. I'm just surprised that Function does. But you know what. I'm not actually surprised thinking about. I spend 1/4 of day tracking down when and where the Function call finally executes. And the function call is extremely nested down in the data referencing. Possibly 10 references and a number of loops deep. And in this case because of how C2 is constantly dumping unused CPU cache data by doing this. I could see this actually happening.

I knew C2 was GPU memory optimized, but I've called for CPU cache optimization a few times. Which I think is what's directly hurting C2 performance in relation to every other engine, and my mobile is such and issue. In a case like Function that numerous nesting is probably doing many, many cache misses and burning a lot of wasted CPU cycles. However its' speculation of what the exact cause is. But having sat down to C2runtime.js CPU cache misses are all over the place.

http://gameprogrammingpatterns.com/data-locality.html

my suggestion. Create a CAPX of this performance difference and file it in the bugs list.
B
92
S
18
G
9
Posts: 2,455
Reputation: 15,113

Post » Sun Nov 08, 2015 11:09 pm

ruskul wrote:Howdy,

I've been playing around with event based procedual terrain generation and I noticed something awful.

A function impacts performance 5x more than another event call. The more you do within the function the less that becomes in relation. But if you call a function simply to perform 1-2 events, just copying and pasting those 1-2 events saves mucho cpu time.

I'm not sure why the performance hit is so great, but once a game is all done and made, if you have performance issues you may try replacing function calls with the code. This makes your code base unmaintainable and awful to look at but you can gain a bit of performance by doing it. This should only* be considered if you are struggling with performance and have eliminated other bottlenecks. Obviously if you have 1000 physics based objects, you may find that reducing function calls is a waste of time in the grand scheme of things.

Better yet, use the event system only to tie scripts together. Do everything else in scripts. That saves over 9000, a whopping 500% to 1000 points more . Ya..


I often like to make dynamic function call systems in placement of switch statements (as construct has none) and event driven dispatch systems, but this may not be as efficient as simply going through a giant condition list. :(


Interesting. In did they can tidy up the code immensely. But I did notice functions being not efficient long time ago already. Unfortunately for some systems they are a must. I'm even wandering, just right now, moment before seeing your post, if should keep using families, or just making events for each type of object separately,and will that give me better performance?
And what do you mean by "scripts" - do you mean actual scripting, programming own scripting language within c2 (which I often do), or just events?
My professional Royalty Free Music at Scirra Assets Store
--------------------------------
Specs: i5 2500, 16gb of ram, gtx 770, win 7, Focusrite Scarlett 8i6, Mackie mr8mk2, Alesis 320, browsing the net on chrome.
B
93
S
30
G
22
Posts: 1,987
Reputation: 20,203

Post » Mon Nov 09, 2015 8:21 am

@ruskul

Post a bug report with .capx and exact steps to reproduce.

I'm sure Ashley will be interested if this is indeed the case.
If your vision so exceeds your ability, then look to something closer.
Moderator
B
137
S
31
G
87
Posts: 5,548
Reputation: 60,440

Post » Mon Nov 09, 2015 11:40 am

Can you post a .capx demonstrating the performance overhead of functions with actual measurements? Then I can investigate and see if anything can be optimised.

However if the function does a very small amount of work, it's actually a normal result to see a performance hit. Even in traditional programming languages, if you move a tiny amount of work to a separate function, the overhead of calling the function can be larger than the amount of work done, and appear to make everything slower. However in absolute terms function calls are still fast, it's just that they can appear slow relative to tiny, even faster amounts of work.

Moving the contents of a function to the call site is an optimisation called inlining. I think it could be difficult to implement that automatically in the event system, I'm not sure. It's something you can do manually where it makes a difference though. However if the function does any significant amount of work, the call overhead should not matter at all.
Scirra Founder
B
402
S
238
G
89
Posts: 24,628
Reputation: 196,023

Post » Wed Nov 11, 2015 5:33 pm

@newt @jayderyu @megatronx @Ashley,

I should be clear, the actual time it takes construct 2 to execute a function can be up to 5x longer than another action single action. Just the calling of the function. (You may say, well of course you would never simply just call a function, but that is not true, (dynamics switch replacements may call functions that don't exist and other cool function uses may call a blank function)). As Ashley pointed out, a tiny thing can execute fast, and even though the functions take longer than that, they are still fast. Compared to a simple event like adding 1 to a variable, calling a function and doing nothing is quite a bit slower.

Its nothing I would worry about, unless you are like me, where in my project I had been willy nilly splitting everything out into functions. I was never repeating code. But usually, a function can require much more than simply calling it. You must construct its name in a dynamic system, pass it a parameter (usually a uid) pick the object by uid once in the function, and finnaly do what needs done. Usually another function is called where you pass parameters and then use the return value. Thus functions are in functions. Its something that happens alot in programming.

Now if you are doing this everywhere and only doing a few things in each function (maybe 2-3 conditions, 2-5 actions), you are really decreasing performance relative to the alternative. If you are doing many more things, like running an entire ai tree from one function call, the function use is irrelevant and has basically 0 impact on performance (unless you need to call it 1000 times a tick, but still, you probably have other worries at that point in terms of performance)

I have attached a capx that hopefully demonstrates the problem. The capx shouldn't be too hard to understand so if a test doesn't make sense, just read the events in the relevant group or ask me. I chose 1000 cycles every tick arbitrarily. I would say, in a decent sized project, it is easy to expect to be doing at least that much work every tick, but it really depends right?

For the most part, If you do everything in javascript that you can, and use the event system to wire everything together performance will be great. and has been my dev method for the last year. I once made a collision detection algorithm in construct, it was around 2,000 events. I thought it would be fun lol. The java script version barely has an impact while the event based version took a chunk of cpu to run eveyrtick. I think this is to be expected...

Anyway, I like to create tests just to see what takes time and what doesn't, it has helped me to determine when and where I should put things in javascript rather than events. I also am master and chief at prematurely optimizing, but its my favorite part about coding. If I am in a hurry I don't fiddle too much with it lol.

https://www.dropbox.com/s/0xhwlwrwq9b1xtx/EventTypePerformanceTest.capx?dl=0
Image
B
33
S
11
G
2
Posts: 564
Reputation: 5,173

Post » Wed Nov 11, 2015 6:01 pm

ruskul wrote:@newt @jayderyu @megatronx @Ashley,

I should be clear, the actual time it takes construct 2 to execute a function can be up to 5x longer than another action single action. Just the calling of the function. (You may say, well of course you would never simply just call a function, but that is not true, (dynamics switch replacements may call functions that don't exist and other cool function uses may call a blank function)). As Ashley pointed out, a tiny thing can execute fast, and even though the functions take longer than that, they are still fast. Compared to a simple event like adding 1 to a variable, calling a function and doing nothing is quite a bit slower.

Its nothing I would worry about, unless you are like me, where in my project I had been willy nilly splitting everything out into functions. I was never repeating code. But usually, a function can require much more than simply calling it. You must construct its name in a dynamic system, pass it a parameter (usually a uid) pick the object by uid once in the function, and finnaly do what needs done. Usually another function is called where you pass parameters and then use the return value. Thus functions are in functions. Its something that happens alot in programming.

Now if you are doing this everywhere and only doing a few things in each function (maybe 2-3 conditions, 2-5 actions), you are really decreasing performance relative to the alternative. If you are doing many more things, like running an entire ai tree from one function call, the function use is irrelevant and has basically 0 impact on performance (unless you need to call it 1000 times a tick, but still, you probably have other worries at that point in terms of performance)

I have attached a capx that hopefully demonstrates the problem. The capx shouldn't be too hard to understand so if a test doesn't make sense, just read the events in the relevant group or ask me. I chose 1000 cycles every tick arbitrarily. I would say, in a decent sized project, it is easy to expect to be doing at least that much work every tick, but it really depends right?

For the most part, If you do everything in javascript that you can, and use the event system to wire everything together performance will be great. and has been my dev method for the last year. I once made a collision detection algorithm in construct, it was around 2,000 events. I thought it would be fun lol. The java script version barely has an impact while the event based version took a chunk of cpu to run eveyrtick. I think this is to be expected...

Anyway, I like to create tests just to see what takes time and what doesn't, it has helped me to determine when and where I should put things in javascript rather than events. I also am master and chief at prematurely optimizing, but its my favorite part about coding. If I am in a hurry I don't fiddle too much with it lol.

https://www.dropbox.com/s/0xhwlwrwq9b1xtx/EventTypePerformanceTest.capx?dl=0


Will look at your benchmark, thought to me it was visible, without any specific benchmarks. But I did thought that small functions would work better then big ones. I also noticed a problem with triggers including functions, that they not always allow loop to complete in full. Probably a bug.
My professional Royalty Free Music at Scirra Assets Store
--------------------------------
Specs: i5 2500, 16gb of ram, gtx 770, win 7, Focusrite Scarlett 8i6, Mackie mr8mk2, Alesis 320, browsing the net on chrome.
B
93
S
30
G
22
Posts: 1,987
Reputation: 20,203

Post » Wed Nov 11, 2015 7:10 pm

Your test includes things like comparing adding 1 to a variable to adding 1 to a variable in a function. That's exactly the kind of a test that basically just measures the overhead of a function. Functions already pretty much do the minimum work they can do, I'm not sure there's any obivous way to speed them up, but that's not to say they're slow. But I guess you might want to avoid them in long loops and such.
Scirra Founder
B
402
S
238
G
89
Posts: 24,628
Reputation: 196,023

Post » Thu Nov 12, 2015 10:57 pm

Ashley wrote:Your test includes things like comparing adding 1 to a variable to adding 1 to a variable in a function. That's exactly the kind of a test that basically just measures the overhead of a function. Functions already pretty much do the minimum work they can do, I'm not sure there's any obivous way to speed them up, but that's not to say they're slow. But I guess you might want to avoid them in long loops and such.


For sure, I was basically looking at function overhead, comparing using functions vs not using them. I was curious though... would there be a way to create event sheet references? Sometimes a function only makes sense from a readability people thinking sort of way if that makes sense. Sometimes functions make sense from a program design standpoint. Would there be a way to have event sheet functions that are only in the event sheet?

For example:

If (object.A overlaps Family.Tilemaps) && (object.A.bool == Family.Tilemaps.bool)
----Do this, do that, push out of solids, bla, bla, bla, bla.
If (object.A overlaps Family.SolidBlocks) && (object.A.bool == Family.SolidBlocks.bool)
----Do this, do that, push out of solids, bla, bla, bla, bla 20 actions.
If (object.A overlaps Family.MobileBlocks) && (object.A.bool == Family.MobileBlocks)
----Do this, do that, push out of solids, bla, bla, bla, bla.
REpeat for a few more condistions

The above can be split into functions, and is preferable for readability and making changes to what happens, But in a game with many itterations through this, the function adds overhead. Whats more the function isn't needed, just a convenience for later editing. If there was an editor side function that could be called that would inline the events on export so that no overhead was created, that would be preferable.

At the same, the only reason this pattern exists is because there are no combo or/ands in a condition tree. But that is a separate topic. (why is this?)

for example : (A over B && A.x == b.x) || (A over C && A.x == C.x) || so on...
Image
B
33
S
11
G
2
Posts: 564
Reputation: 5,173

Next

Return to Construct 2 General

Who is online

Users browsing this forum: Anonnymitet and 3 guests