Thread: Solutions for slow performance?

  1. #31
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Originally posted by Sebastiani
    I have not looked over your code. But I can tell you that IO operations are always several orders of magnitude slower than calculations. But I guess you already discovered that. Rendering in general is slow on pre-gigahertz machines, so limit the time spent drawing backgrounds. Another significant improvement can be achieved with separate threads of execution. If you would like a simple library to begin with, just PM or email me. But beware. Threads can cause a lot of headaches and often require severe restructuring of the program. Nonetheless, giving each sprite it's own thread makes the game flow more naturally, and this is one of the main advantages of using them.


    Macros are indeed ugly, but they ARE faster. Try this simple test:


    Code:
    double mult( double a, double b){ return a * b; }
    
    #define MULT(a, b) ((a)*(b))
    
    int main() {
    
    time_t start, stop;
    
    double iter, x = 1, y = 3;
    
    start = clock();
    
    for(iter = 0; iter < 100000000; iter++)
    x = mult(x, y);
    
    stop = clock();
    
    printf("(Function) Result: %d Seconds Elapsed\n\n", (stop-start)/1000);   
    
    //...48 - 52 seconds on my machine...
    
    
    
    x = 1, y = 3;
    
    start = clock();
    
    for(iter = 0; iter < 100000000; iter++)
    x = MULT(x, y);
    
    stop = clock();
    
    printf("(MACRO) Result: %d Seconds Elapsed\n\n", (stop-start)/1000);
    
    //...35 - 38 seconds on my machine...
    
    
    getch();
    
    return 0;
    }

    On my system, the macro was roughly 20%-30% faster.

    BTW:

    Don't waste your time with FillRect(), you can get by without it.

    Oh, and far as speed goes, DirectX and OpenGL have much faster bit-block transfers than BitBlt().

    Anyway, good luck on the game!
    I was referring to inline functions vs. macros only. Test it with inline functions then I will be interested in the results.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  2. #32
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Ah, yes, you're right. Thanks for pointing that out
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #33
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Originally posted by Sebastiani
    Ah, yes, you're right. Thanks for pointing that out
    No problem. Hey I like macros just as much as the next guy, especially for typeless quick math operations. I just didn't want someone who didn't know much to get the wrong impression.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  4. #34
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    You should though!
    True, but I've had it up to here (------------------) with that stupid vector. This is what goes on:
    Code:
    void removeFighters()
    {
         while(fighters.size() > 0)
         {
              delete fighters[0];
              fighters.erase(&fighters[0]);
         }
    }
    And about 75% of each time I call this, I get a 'debug assertion error' or something to that effect. So I got PO'ed and cut the delete out, and it fixed Unfortunately, of course, it creates a memory leak.... But it gets called very seldom (only when the program quits, or at the end of a specific LimitBreak), so there can't be tooo much memory leaking, can there? (of course it's bad, but I can't think of what's wrong.)
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #35
    Visionary Philosopher Sayeh's Avatar
    Join Date
    Aug 2002
    Posts
    212
    Also, your comment about C vs. C++ as far as speed goes kind of bothered me. Now, when you get into inheritance and all that garbage yes speed can drastically be affected. However, in this game I didn't see a lot of this and from my own experience on simple programs C and C++ are about the same.
    You are exactly right. It's inheritance, and using the higher-level OO aspect of C++ that bogs it down. If you aren't using that stuff, then you are basically using C.

    Use macros instead of functions? Well I guess it really depends on what you doing with the function.
    It has nothing to do with 'typeless functions'.

    If you run your code through a preprocessor, you will find that macros get inserted directly into the code wherever they are called. No stack setup & teardown.

    Everytime a function is called, stack setup and teardown has to be performed. That's why recursive functions get progressively slower the longer they run (every watch a recursive floodfill?).

    Of course you can't replace every function with a macro-- NOR WOULD YOU WANT TO. But as with all things, there are spots where you definitely want to avoid wasting time on maintenance.

    A perfect example is a multiply function (let's say you were using fixed notation and had to write a multiply function for it)-- over a period of 30 seconds of animation, using a code profiler, you might find that that function gets called 100,000,000 times!! I kid you not. As such, if you can shave just 1 clock-cycle off every pass-- look at the SAVINGS! That's what performance is all about.

    80% of your code's time will be spent in 10% of your code. It's that code that needs to be optimized and checked. You're looking to get every erg of energy out that you can.

    If you can put it in an effecient macro and you've done the other optimizations I suggest, then the next step is turning macros into assembler, and a few other algorithms, as well. But at this stage, if you've done everything right, going from C to assembler will only gain you 1 to 4 frames per second more.

    Having worked in the game industry (6DOF engines) for some years on both PCs and Macs, I have a _very good_ understanding of how to get performance out of either platform.
    It is not the spoon that bends, it is you who bends around the spoon.

  6. #36
    Visionary Philosopher Sayeh's Avatar
    Join Date
    Aug 2002
    Posts
    212
    The 32-bit compiler does not honor user requests for register variables. Instead it makes its own register choices when global optimizations are on. However, all other semantics associated with the register keyword are honored by the 32-bit compiler.
    The semantics are as you suspected. However Microsoft's definition doesn't surprise me. They were too lazy to do it right, but did just enough to allow code portability. Just like MS to always cut corners.

    If the compiler can't be trusted to do what you tell it to do, how reliable is it, anyway? I'd switch to another if I were you.

    But what does 'touch each pixel once' mean?
    In most cases, you should only need to touch a pixel once. For example, rather than erasing a block and drawing new data onto it, just draw the correct data onto to begin with. Hence, touch it once.
    It is not the spoon that bends, it is you who bends around the spoon.

  7. #37
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Ah.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  8. #38
    Nick
    Guest
    This has already said but the windows gdi is slow and
    drawing text with gdi functions is slow. There's
    almost nothing you can do to make it run faster. It wouldn't
    take too long to recode it in directx or the sdl www.libsdl.org
    and it would be alot faster. Your wasting your time if you
    are using the gdi and are trying to optimize it. A directx
    visual basic program would be faster.

    If you do use register it's supposed to warn you
    about when you use it in a situation where it a register
    is inappropriate so it still has it's uses.

  9. #39
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Originally posted by Sayeh

    It has nothing to do with 'typeless functions'.

    If you run your code through a preprocessor, you will find that macros get inserted directly into the code wherever they are called. No stack setup & teardown.

    Everytime a function is called, stack setup and teardown has to be performed. That's why recursive functions get progressively slower the longer they run (every watch a recursive floodfill?).

    Of course you can't replace every function with a macro-- NOR WOULD YOU WANT TO. But as with all things, there are spots where you definitely want to avoid wasting time on maintenance.

    A perfect example is a multiply function (let's say you were using fixed notation and had to write a multiply function for it)-- over a period of 30 seconds of animation, using a code profiler, you might find that that function gets called 100,000,000 times!! I kid you not. As such, if you can shave just 1 clock-cycle off every pass-- look at the SAVINGS! That's what performance is all about.
    Just to clarify I was talking about inline functions, which to my knowledge, insert the code as would a macro. I realize that inline keyword is only a suggestion to the compiler but lets be honest, if its a simple multiplication function or macro , it will be placed inline if you request it.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  10. #40
    Visionary Philosopher Sayeh's Avatar
    Join Date
    Aug 2002
    Posts
    212
    Use macros instead of functions? Well I guess it really depends on what you doing with the function.
    Sorry, I misunderstood-- you didn't say inline. Not all compilers support the 'inline' directive on procs/funcs-- many will only support that with assembler.
    It is not the spoon that bends, it is you who bends around the spoon.

  11. #41
    Registered User
    Join Date
    Apr 2002
    Posts
    1,571
    Originally posted by Sayeh


    Sorry, I misunderstood-- you didn't say inline. Not all compilers support the 'inline' directive on procs/funcs-- many will only support that with assembler.
    No I suppose it was my fault for forgetting to put the inline keyword in my original statement. It's hard to believe anyone would be so naive to think that 'regular' functions are faster than macro's. Do you know any compilers that don't support inline? I'll steer clear of those.
    "...the results are undefined, and we all know what "undefined" means: it means it works during development, it works during testing, and it blows up in your most important customers' faces." --Scott Meyers

  12. #42
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Alright Mr. Nick, could you please wait a minute while I bang my head against the wall?

    I KNOW THAT DIRECTX WILL RUN SEVERAL BILLION TIMES FASTER THAN GDI AND THAT THERES NOTHING I CAN DO ABOUT GDI RUNNING SLOW AND THAT GDI RUNS SLOW AND THAT GAMES ARE NOT MADE IN GDI AND SEVERAL OTHER THINGS THAT PEOPLE TELL ME EVERY DAY.

    Okee, now that I've calmed down a bit, let me assure you of this: I intend to begin recoding the stupid game in directx within this week. It has been on my agenda for the past (large number here) months, but as I have just started learning to program in Windows but a wee little short while ago, I felt that it would be important for me to familiarize myself with GDI first. IF I learned DirectX but was helplessly unacquainted with Windows' base services, then I would count myself among the stupid people who try running before they learn to crawl. Understood? And personally, I have a gut feeling that DirectX just might be a wee bit more complex than GDI, and as this is my first game ever (minus Tic Tac Toe), I'd prefer learning one thing at a time (i.e. figure out how to make a game now, figure out how to make DirectX work later.)

    Sorry if I've been overly harsh with you, but I am sick and tired and blue in the face from hearing the same thing over and over from many multitudes of people, all of whom doubtlessly have good intentions, but don't realize that just maybe somebody might have mentioned it some time ago.


    P.S. Thanks for the pointer
    Last edited by Hunter2; 08-22-2002 at 07:20 PM.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  13. #43
    Nick
    Guest
    You have to
    be careful with stuft like

    for (int i = 0; i < 40; i++)
    /* do more stuft */

    for ( i = 0; i < 40; i++)
    /* do more stuft */

    All of your classes with virtual functions must have a
    virtual destructor.

  14. #44
    Nick
    Guest
    I think this part in TransBlit is slowing it down
    Code:
    for(int i = 0; i < width * height * 3; i += 3)
    {
        if(imageBits[i] == 0 && imageBits[i + 1] == 0 && imageBits[i + 2] == 0)
        {	//if it's black, make it white
    	imageBits[i] = 255;
    	imageBits[i + 1] = 255;
                    imageBits[i + 2] = 255;
        }
        else
        {	//if it's not, make it black
    	imageBits[i] = 0;
    	imageBits[i + 1] = 0;
     	imageBits[i + 2] = 0;
         }
    }
    Your best off generating the mask ahead of time
    somehow.

  15. #45
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    void removeFighters()
    {
    while(fighters.size() > 0)
    {
    delete fighters[0];
    fighters.erase(&fighters[0]);
    }
    }
    You can't just delete the head of the vector like that! And the loop goes nowhere! I don't personally used that crumby STL(sorry), but I believe you need an iterator to traverse it for the deletions. Still, it should be overloaded so that you can do:

    Code:
    void removeFighters()
    {
     int iter = 0;
    
         while(fighters.size() > 0)
         {          
            fighters[iter++].erase();
         }
    }
    ...and don't delete the actual vector cells, since the STL will do that for you. BTW, never do:

    delete x;

    Instead,

    if(x) //...or if you like, if(x != NULL)
    delete x;

    This will ensure that you don't crash the proggie from deleting a NULL pointer...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Performance and footprint of virtual function
    By George2 in forum C++ Programming
    Replies: 8
    Last Post: 01-31-2008, 07:34 PM
  2. File map performance
    By George2 in forum C++ Programming
    Replies: 8
    Last Post: 01-04-2008, 04:18 AM
  3. Observer Pattern and Performance questions
    By Scarvenger in forum C++ Programming
    Replies: 2
    Last Post: 09-21-2007, 11:12 PM
  4. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  5. inheritance and performance
    By kuhnmi in forum C++ Programming
    Replies: 5
    Last Post: 08-04-2004, 12:46 PM