The forums have permanently moved to forum.kirupa.com. This forum will be kept around in read-only mode for archival purposes. To learn how to continue using your existing account on the new forums, check out this thread.


Results 1 to 14 of 14

Thread: What would be faster

  1. What would be faster

    Hey,

    I'm creating an RTS, see my signature. And it's going pretty well, obviously there is always the problem of lag. Now I wonder what to do. Should I see if a unit is on-screen and only render it when it is on-screen or should I just always render it.

    Rendering would be copypixeling a 70x70 pixel picture to a bitmapdata that the user can't always see. Obviously this is useless and uses precious cpu time. But maybe checking if a unit is on screen takes more cpu then the rendering part. Obviously the time spend on calculating if it's on-screen is wasted when it appears that it is on-screen.

    The user sees a screen of 500x500 pixels with the left top being the coordinate: (offSetX, offSetY). So the code would look something like this:

    Code:
    if (_x > offSetX && 
        _x < offSetX + 500 &&
        _y > offSetY &&
        _y < offSetY + 500)
        {
        render();
        }
    What do you guys think? I think I'll write a short program to see which one takes up the most cpu if you guys don't know this exactly though .

    Thanks,

    ArmoredSandwich AKA ImWithNoob.

    Edit:

    Code:
    Testing copy pixels, we're gonna copy pixel a picture of: 70x70 100000 times
    It took: 204 ms.
    Testing the calculation too see if a unit should be rendered or not, 100000 times, unit is off-screen
    It took: 155 ms.
    Testing the calculation too see if a unit should be rendered or not, 100000 time, unit is on-screen.
    It took: 241 ms.
    Even if it was faster the unit would still have to render itself. So nope, it's not faster.
    Last edited by ArmoredSandwich; April 13th, 2008 at 01:14 PM. Reason: See edit

  2. #2
    Rendering is almost always slower than a couple of simple calculations. That's why 3d engines usually use backface culling, to reduce the amount of rendering, not the amount of calculations.

    Your code will be faster most of the time if you break up your if statement into it's components. Something like:
    PHP Code:
    if (_x offsetX ) {
        if(
    _x offsetX 500 ) {
            if(
    _y offsetY ) {
                if(
    _y offsetY 500 ) {
                    
    render();
                }
            }
        }

    It usually runs faster this way because if a top level condition is not met, lower level conditions are not evaluated, therefor less processing time in the majority of cases.

  3. #3
    Out of sight, Out of Mind!

  4. #4
    Quote Originally Posted by Jerryscript View Post
    It usually runs faster this way because if a top level condition is not met, lower level conditions are not evaluated, therefor less processing time in the majority of cases.
    Not true. I've always thought that in
    PHP Code:
    if(foo() && bar()) {} 
    bar() would not be evaluated if foo() returned false. But I decided to test it before posting this.

    My test confirms my assumption.
    PHP Code:

    function foo(){
       echo 
    "foo";
       return 
    false;
    }

    function 
    bar(){
       echo 
    "bar";
       return 
    false;
    }

    if(
    foo() && bar()){
       
    //do whatever here

    This code snippet outputs "foo" but not "bar".

    foo is evaluated to false, the if-statement breaks and doesn't evaluate the remaining conditions (i.e. bar()).

    Conclusion: the reason you stated is invalid. However I haven't run any test that would compare execution times. I still don't know which is faster but IMO you'd be better off using the "inline" && syntax. Nested logic is just a pain to maintain when it gets more and more complicated.

  5. True, which also explains why it takes longer if the unit is on screen

  6. #6
    You are correct, my logic failed.

    However, it is still true that nested if statements are faster than using && or || in a single statement. Try the following code to see:
    PHP Code:
    createTextField('stuff1'getNextHighestDepth(), 1001004020);
    stuff1.border true;
    createTextField('stuff2'getNextHighestDepth(), 1001404020);
    stuff2.border true;
    createTextField('stuff3'getNextHighestDepth(), 1001804020);
    stuff3.border true;


    function 
    foo() { 
        
    stuff1.text 'foo';
        return 
    true;
    }
    function 
    bar() {
        
    stuff2.text 'bar';
        return 
    true;
    }

    _root.onMouseDown = function(){
        
    stuff1.text stuff2.text stuff3.text '';
        var 
    now getTimer();
        var 
    0;
        if(
    Key.isDown(Key.SHIFT)){
            for(var 
    010000i++){
                if(
    foo() && bar()){
                    
    c++;
                }
            }
            
    stuff3.text getTimer() - now;
        }else{
            for(var 
    010000i++){
                if(
    foo()){
                    if(
    bar()){
                        
    c++;
                    }
                }
            }
            
    stuff3.text getTimer() - now;
        }
    }; 

  7. #7
    I don't think I'm getting what you're getting. I'm getting very similar results for each case.

    pressing shift: (&&)
    1- 352
    2- 355
    3- 351
    4- 385
    5- 365

    361.6

    not pressing shift: (nested)
    1-374
    2-370
    3-366
    4-349
    5-365

    364.8

    in this particular run, && ran faster. but it's way too small to be statistically significant. I don't know if this is a valid way to test it in the 1st place. I still believe that the fastest way hasn't been determined yet. I would say that it really doesnt matter at this point since we can see that the times are so close together.

    For the hell of it, I decided to add a zero to your loop so that it runs 100000 times instead of 10000 which should give more consistent results.

    nested vs && step#: time


    nested step1: 3570
    nested step2: 3752
    nested step3: 3590
    nested step4: 3622
    nested step5: 3669
    && step1: 3694
    && step2: 3512
    && step3: 3570
    && step4: 3567
    && step5: 3613

    nested avg:3640.6
    && avg: 3591.2


    nested step1: 3604
    && step1: 3603
    nested step2: 3512
    && step2: 3524
    nested step3: 3501
    && step3: 3536
    nested step4: 3551
    && step4: 3524
    nested step5: 3566
    && step5: 3576

    nested avg:3546.8
    && avg: 3552.6


    && step1: 3615
    && step2: 3574
    && step3: 3574
    && step4: 3517
    && step5: 3520
    nested step1: 3534
    nested step2: 3526
    nested step3: 3539
    nested step4: 3498
    nested step5: 3644

    nested avg: 3548.2
    && avg:3560


    we're talking about a 5-10 milliseconds difference on average (worst case being 50ms difference) which is ridiculously small when you see that it takes about ~3600ms to execute.

  8. #8
    And this is why I quit making flash games. All the headaches you get trying to optimize the perfect code when in realty the flash player only has access to like 30% of the cpu power on the machine.

  9. #9
    In a way, you're both correct. Inline conditions are usually faster when you expect all of the conditions to evaluate as true.

    Nested conditions are generally faster when you expect any of the conditions to evaluate as false but this depends on where the condition lies within the nested chain. The greater the number of conditions, and the further down the chain that your false condition resides, the less net gain in speed:
    Code:
    // ------------------------------------
    function testOne() {
    	var a = true;
    	var b = true;
    	var c = true;
    	startTime1 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a && b && c) {
    			// do something
    		}
    	}
    	trace("All inline conditions are true = " + (getTimer() - startTime1));
    }
    // ------------------------------------
    function testTwo() {
    	startTime2 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a) {
    			if (b) {
    				if (c) {
    					// do something
    				}
    			}
    		}
    	}
    	trace("All nested conditions are true = " + (getTimer() - startTime2));
    }
    // ------------------------------------
    function testThree() {
    	var a = false;
    	var b = true;
    	var c = true;
    	startTime3 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a && b && c) {
    			// do something
    		}
    	}
    	trace("Condition a is false (inline) = " + (getTimer() - startTime3));
    }
    // ------------------------------------
    function testFour() {
    	var a = false;
    	var b = true;
    	var c = true;
    	startTime4 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a) {
    			if (b) {
    				if (c) {
    					// do something
    				}
    			}
    		}
    	}
    	trace("Condition a is false (nested) = " + (getTimer() - startTime4));
    }
    // ------------------------------------
    function testFive() {
    	var a = true;
    	var b = false;
    	var c = true;
    	startTime5 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a && b && c) {
    			// do something
    		}
    	}
    	trace("Condition b is false (inline) = " + (getTimer() - startTime5));
    }
    // ------------------------------------
    function testSix() {
    	var a = true;
    	var b = false;
    	var c = true;
    	startTime6 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a) {
    			if (b) {
    				if (c) {
    					// do something
    				}
    			}
    		}
    	}
    	trace("Condition b is false (nested) = " + (getTimer() - startTime6));
    }
    // ------------------------------------
    function testSeven() {
    	var a = true;
    	var b = true;
    	var c = false;
    	startTime7 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a && b && c) {
    			// do something
    		}
    	}
    	trace("Condition c is false (inline) = " + (getTimer() - startTime7));
    }
    // ------------------------------------
    function testEight() {
    	var a = true;
    	var b = true;
    	var c = false;
    	startTime8 = getTimer();
    	for (var i = 0; i < 100000; i++) {
    		if (a) {
    			if (b) {
    				if (c) {
    					// do something
    				}
    			}
    		}
    	}
    	trace("Condition c is false (nested) = " + (getTimer() - startTime8));
    }
    testOne();
    testTwo();
    testThree();
    testFour();
    testFive();
    testSix();
    testSeven();
    testEight();
    trace ("----------------------------");
    Typical output:
    Code:
    All inline conditions are true = 168
    All nested conditions are true = 256
    Condition a is false (inline) = 140
    Condition a is false (nested) = 84
    Condition b is false (inline) = 151
    Condition b is false (nested) = 108
    Condition c is false (inline) = 171
    Condition c is false (nested) = 134
    ----------------------------
    Conclusion? If you expect all of your conditions to evaluate as true most of the time, use inline conditional statements. If you expect any of your conditions to evaluate as false, use nested conditions but place the condition you expect to evaluate as false higher up the conditional chain. If you don't, you might as well stick with inline conditional statements for the sake of clarity.
    2006-11 GlosRFC - Searching 8,168,684,336 brain cells

  10. #10
    Quote Originally Posted by glosrfc View Post
    Inline conditions are usually faster when you expect all of the conditions to evaluate as true.

    Nested conditions are generally faster when you expect any of the conditions to evaluate as false but this depends on where the condition lies within the nested chain. The greater the number of conditions, and the further down the chain that your false condition resides, the less net gain in speed
    Interesting. Thanks for shedding light on this.

    I guess I'd like to ask a question to anyone who cares to answer:

    When trying to speed things up, how often have you actually rewritten your code from inline to nested (or nested to inline)?

    If I'm trying to optimize my code for speed, this is the last place I'd look into. IMO, there are far more important things to look at, like the order of magnitude of your algorithm depending on your input, etc...

    However, I'll keep this in mind if I need a couple millisecond improvement.

  11. #11
    I have a pretty well set coding practice that I follow (set in my ways, not necessarily well as in good), which I've developed over the past 6 years working with flash, altering it as new AS versions appeared. Many of my practices are based on optimizations, which I've found by reading various blog posts on the subject, and as well as benchmark tests performed by members of various flash forums.

    The times I've found optimizations such as this are important are primarily those involving either spreadsheet type apps, or 3d games. For example, using as many optimization tricks as possible, I was able to increase the performance of my terrain rendering engine from a jumpy 12 fps to a usable 32 fps (quick tip, never create any geom objects inside a function or loop, they take forever to initiate, rectangle objects are insanely slow).

    Bottom line for me, I begin a project by keeping it as readable as possible. Once functioning properly, I then begin optimizations to increase perfromance, always attempting to get greater performance than necessary.

    One other thing to remember, not everyone has a blazing fast computer. What may be a 1 millisecond improvement on your speed demon computer could turn into a 50+ millisecond improvement on some less capable systems. I learned an important lesson back in my WebTV days: if you want the greatest number of people to be able to use what you code, code it for the least common denominator! (slow computers)
    Last edited by Jerryscript; April 14th, 2008 at 04:53 PM. Reason: typo: replaced [I]Math[/I] object typo with [I]geom[/I] object

  12. What's the problem with Math objects in loops? It's just a static function right?

    And what would be an alternative for the cos, sin etc?
    Last edited by ArmoredSandwich; April 14th, 2008 at 01:04 PM.

  13. #13
    I never optimized trivial things. I just rework algorithms to have less run-time. This might not mean much to you right now, but as you study algorithm designs more closely you'll learn a lot of interesting data structures to solve problems. Often the more complex solutions will run much faster.

    A good example is this problem. Instead of optimizing by trying to figure out what to render, what ArmoredSandwich might need is a solid spatial partitioning system. I'd recommend a grid as it will work well for a large map and can be used along with A* and such algorithms. It's a good idea to get out some paper and imagine a large map then draw a 100x100 grid over it. What if every cell in that grid had a linked list capable of holding entities. Static objects in the game don't move and thus by inserting them into their respective cells you can cull the game very quickly when performing collision detection and rendering. (hint Cell is a class and the grid is just a 2D array of the Cells such that you can access them like grid[x][y]). You might wonder how to find out where to insert the object. Well an axis aligned boundary box of the object will have a top left and a bottom right point. If you imagine this on a grid then you'd have a nested for loop starting from the coordinate in the grid of (object1.aabb.min.x/cellSize, object1.aabb.min.y/cellSize) and you'd iterate to (object1.aabb.max.x/cellSize, object1.aabb.max.y/cellSize) inserting the object into each cell. You'd need methods to remove the objects quickly so you might store the list of the nodes in the object and if you know how linked lists work then you just remove them by pulling them out of each list. These algorithms can get complex and speed up program much more than any little optimization. In fact a solid spatial partitioning system will make the size of the map meaningless for the most part.

    About the sin and cos stuff it depends. Sometimes it's needed, but most of the time it's not. Once you learn vector math or complex imaginary number kind of math you'll figure out tons of ways to optimize things.

  14. #14
    Dadgummit, there I go again with a typo, I meant the geom classes, such as rectangle, point, etc. (though there is a lot of speed to be gained from preprocessed lookup tables as opposed to calculating in many cases).

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

Home About kirupa.com Meet the Moderators Advertise

 Link to Us

 Credits

Copyright 1999 - 2012