Functions inefficient *

0 favourites
From the Asset Store
Template for dungeon/maze generation, using wave function collapse
  • 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.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • 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.

  • 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.

  • 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?

  • 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.

  • 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.

  • 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

  • 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.

  • 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.

  • 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...

  • i've done my testing in debugger

    1st test - 1% cpu

    2nd test - 3% cpu

    3rd test - 3% cpu

    4th test - 3% cpu

    5th test -5-6% cpu

    6th test - 20% CPU - uses function

    7th test - 24% CPU - uses function

    8th test - 24% CPU - uses function

    so i've ran the benchmark he gave, but this seems very odd to me. 25% CPU ? that's one CORE - also that last test never stops, so your code might be buggy (i'll check in more detail tommorow). Also i've got 4860M (quad 3.6GHz) and eating 25% with functions is wtf. I mean i've made a game / template / with long and loads of functions (check link in my signature) and i've never went over 15% while playin, only when loads of particles went on screen - then i'd go up to 70%. But going over 15% with functions... i'm pretty positive your code is buggy

  • No long in-call loops, no every tick triggers, seems fairly reasonable.

    I generally try to avoid them anyway.

    A variable comparison, while harder to set up, should perform even better.

  • newt - For sure, if I understand what you mean by setting up a variable comparison, I do that lots now. conditions = set variable to 1. After that check the variable, if it is 1 then do stuff, or similar setups.

    My biggest trouble is that I've noticed you need* "for each family loop"s with multiple function calls for scaleability. When functions are used as a design element to make your game scalable and manageable. For example, in my game, every dynamic object affected by world forces (gravity, wind, etc) is in a family called characters. The player, bullets, enemies, etc, are all in this family and this family must call 3-4 functions minimum but may call more. If you only have a few characters, no problem, but for every function I add, I exponentially impact my performance. Knowing this, I design more around less function calls. I'll see what my performance is in the end before taking drastic measures though

  • whaaaat?? I get 54% cpu usage for the functions, and about 7-10% without.

  • Just ran into this issue again.. I had an event that was using 0.1% cpu, and when put in a function it became 1.5%

    That's a 1500% increase just because it was put in a function!

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)