Useful XNA Framework tips

Last post 11-20-2007, 6:26 AM by TeaBean. 26 replies.
Page 1 of 2 (27 items)   1 2 Next >
Sort Posts: Previous Next
  •  03-29-2007, 10:53 AM

    Useful XNA Framework tips

    Not sure if this is what you're looking for, but here's a quick tip:

    In the SpriteBatch.Draw calls that take an origin vector, the origin is specified in source resolution, so no matter how the sprite is scaled, the origin will remain the same. This caused me all sorts of trouble but once I got used to it, it actually makes the code much simpler when scaling to multiple resolutions.


    Bill Reiss - XNA Tutorials for Beginners at bluerosegames.com
  •  03-30-2007, 11:48 AM

    Re: XNA Fun Facts

    Here is a fun fact. The X in the XNA logo is morse code.
    Michael Coles
    Senior Programmer
    Digini Inc.
    http://www.blade3d.com
  •  03-31-2007, 4:08 AM

    Re: XNA Useful Facts

    float aspectRatio = (float)1024 / 768; or 1024.0f / 768.0f

     otherwise it will cast to int and return 0.

  •  04-02-2007, 12:11 AM

    Re: XNA Useful Facts

    Check out the different overloaded version of the SpriteBatch Begin() function and you'll different useful versions of it.  One of them allows you to save the state of the graphics device which gets reset again when you call the End() function.                                                  


    Currently working on TerraSuite, a world-building tool built using XNA!
  •  04-02-2007, 12:11 AM

    Re: XNA Useful Facts

    This isn't necessarily related to XNA but more towards game programming.  If you're creating a ton of objects that are updated and drawn the system can slow down to a crawl within minutes and you'll find yourself getting less than 1 frames per second.  A good strategy is to develop an object manager that recycles the objects that you're using when they die or are removed from the game world.  This way when you need to get a new object, instead of calling new and use memory allocation all over again you can just get the references from the manager, reset a few properties, and get a "new" object without the cost of allocating new memory on the heap.

     
    Currently working on TerraSuite, a world-building tool built using XNA!
  •  04-02-2007, 1:49 AM

    Re: XNA Useful Facts

    EyeCrust... I love you :) That's a great idea.

    As for me... Uhm... When you're creating a 3D game, and such have lots of level-geometry and models running around, using "foreach" to render all of the meshes is a bad idea. This is because whenever you hit a foreach, it actually creates allocates a new object, which results in many, many unnecessary object allocations per second.

    If efficiency is a must, don't use foreach. Make your own way of looping through all the meshes.

  •  04-02-2007, 10:12 PM

    Re: XNA Useful Facts

    EyeCrust:
    ... without the cost of allocating new memory on the heap ...

    Just for the record, the cost of allocating things in .NET is near nothing ... almost literally just incrementing a pointer.  The real cost of "new" objects comes when the garbage collector runs and tries to reclaimed unused objects.  This is particularly true on the xbox360. 



    Joel Martinez
    Blog: http://codecube.net
    Play Videos on an XNA Texture: Scurvy Media
  •  04-03-2007, 10:29 AM

    Re: XNA Useful Facts

    I've gotten killed by GC before.  My main conclusions were:

    - don't use String.toLower() and

    - don't use collections.

     

    Based on the profiler and performance monitor, using 4 technique collections per render was giving me 4000ms of GC per collection.
     


    skasoftware.com
  •  04-03-2007, 11:31 AM

    Re: XNA Useful Facts

    Jamezila:

    - don't use collections. 

    Erm GL trying to write a game with more than a handfull of objects then


    Phantom
    www.PlasmaFlux.com
  •  04-03-2007, 12:32 PM

    Re: XNA Useful Facts

    Jamezila:

    - don't use collections.

    That seems a little over the top to me - collections are useful! If you're going that far, why not just say "don't write any code at all", which would run incredibly fast, but not be very interesting :-)

    Certainly there are some things you can do with collections (as with any complicated code) that will cause lots of garbage. The tricks is to understand how to use them well. This is a good place to start:

    http://blogs.msdn.com/etayrien/archive/2007/03/17/foreach-garbage-and-the-clr-profiler.aspx
     


    --
    XNA Framework Developer
    blog - homepage
  •  04-03-2007, 1:44 PM

    Re: XNA Useful Facts

    I'll change to:

    - don't use collections for reference values where said collections are instantiated several times per frame

     

    And fyi, I think I've managed pretty well in spite of being deathly scared of foreach.  A long time ago, in a land far far away, people got along just fine with arrays :)

    Shawn, I read your blog all the time; I read your post on optimizing for readability, performance, etc.  I believe readability is important, and think a for(i = 0; i < array.length; i++) loop is just as readable as a foreach loop.  However, when doing a bit of snippet pasting, I (irresponsible young C# developer) accidentally introduced about 4000ms of GC at least once a minute which had a substantial effect on gameplay--I had to run the Performance Monitor and CLR Profiler to find the culprit foreach calls.

    I just think it bears mentioning that [irresponsibly] using foreach, unlike using straight up arrays, can lead to a few days of lost productivity and hair-pulling.

     


    skasoftware.com
  •  04-03-2007, 2:06 PM

    Re: XNA Useful Facts

    Well, instantiating collections several times per frame is far different than enumerating them!  You wont get anywhere near 4 seconds of garbage collection time per minute by enumerating collections, but you will get 4 seconds per minute if you are allocating several megabytes of memory per frame.  The belief that "foreach" is slow is misguided in the majority of cases: http://blogs.msdn.com/brada/archive/2004/04/29/123105.aspx

    I also suggest reading the msdn patterns and practices guidelines on collections that are referenced from that page.

  •  04-03-2007, 2:50 PM

    Re: XNA Useful Facts

    I found the culprit.  MSDN!

    http://msdn2.microsoft.com/en-us/library/bb203872.aspx 

    Scroll way down, it's that foreach that was giving me all sorts of problems on Xbox360.


    skasoftware.com
  •  04-03-2007, 10:40 PM

    Re: XNA Useful Facts

    Hah! What'd I tell you about the foreach loops? ;)
  •  04-03-2007, 11:10 PM

    Re: XNA Useful Facts

    Well, like they keep saying, they're not evil; you just have to know how to use them, etc.  I'm just in the habit of using arrays and then for loops to iterate through them, and it just so happens that the one time I use foreach (from an official msdn snippet, mind you) I end up in a heap of trouble.

    But I believe that what they're trying to tell me is that if I have

    BloodyHead [] bloodyhead = new BloodyHead[64];

    ...

    for (int i = 0; i < bloodyhead.length; i++)

    is exactly the same as

    foreach(BloodyHead bh in bloodyhead)

    in the final build.  Which is well and good, and I guess it can be better for readability, but I suppose for someone who grew up on for loops and fears change, does it really make that much of a difference?


    skasoftware.com
  •  04-04-2007, 12:35 AM

    Re: XNA Useful Facts

    Jamezila:
    Which is well and good, and I guess it can be better for readability, but I suppose for someone who grew up on for loops and fears change, does it really make that much of a difference?

    Nope, you should use whichever you find most readable and easy to program.  I think what Shawn and others (including me) have been trying to negate is the idea that foreach, or collections, or passing large structures by value are always bad and need to be avoided at all costs for performance reasons. 

    The idea that foreach is bad is just not true.  Which I know you know, but apparently some others here are slower at picking up on the message!  ;-)

    Tom


    Advice from the Swamp
  •  10-25-2007, 2:06 PM

    Re: XNA Useful Facts

    Bapabooiee:

    As for me... Uhm... When you're creating a 3D game, and such have lots of level-geometry and models running around, using "foreach" to render all of the meshes is a bad idea. This is because whenever you hit a foreach, it actually creates allocates a new object, which results in many, many unnecessary object allocations per second.

    If efficiency is a must, don't use foreach. Make your own way of looping through all the meshes.

    Lies, all lies. =P  The amount of time used in allocating an enumerator is extremely short in comparison to the amount of time spent drawing all the meshes.  Here it is in math terms:

    Let us say that drawing one mesh takes 0.1 ms.  We have 1000 meshes we want to draw, so they will take 100 ms.  Now we have the option of a for loop or a foreach loop.  Let us say that the for loop takes 0.001 ms, one hundreth of the time to draw one mesh, to initialize and that the foreach loop takes 0.01 ms, ten times as long as the for loop and one tenth as long as drawing an entire mesh, to initialize.  Then the total times for the for loop and foreach loop methods are 100.001 ms and 100.01 ms respectively.  Going from the foreach lopp method to the for loop method is a percent change of [(100.001 - 100.01) / 100.01] * 100% = -0.009% change.  That's practically nothing!

    The values I used in my example were probably not accurate at all, but I think we can agree that they were accurately proportioned.  The foreach loop is clearer and more "to-the point" than the for loop.  The extra time spent initializing it is negligible.

  •  10-25-2007, 2:49 PM

    Re: XNA Useful Facts

    Swordshock:
    Bapabooiee:

    As for me... Uhm... When you're creating a 3D game, and such have lots of level-geometry and models running around, using "foreach" to render all of the meshes is a bad idea. This is because whenever you hit a foreach, it actually creates allocates a new object, which results in many, many unnecessary object allocations per second.

    If efficiency is a must, don't use foreach. Make your own way of looping through all the meshes.

    Lies, all lies. =P  The amount of time used in allocating an enumerator is extremely short in comparison to the amount of time spent drawing all the meshes.

    To put Baabooiee's idea into a better stated way. Each time you hit a foreach loop you generate a new object on the heap. After that loop ends the GC has to take care of it. If you do a lot of foreach's each frame, you will get lots of unnecessary garbage. We should try and emphasize to everyone that allocations aren't the problem, it's the resulting object being sent to the GC that will potentially cause you problems.

    Of course do read Shawn's post. For beginners with not a lot going on in their game, you can probably get away with using the foreach loop. If you are rendering lots of models and doing lots of computations, you may want to avoid the foreach so that you don't generate the unnecessary garbage.



    Nick Gravelyn -- Microsoft XNA MVP
    XNA Wiki | Zune Games
  •  10-25-2007, 3:09 PM

    Re: XNA Useful Facts

    foreach doesn't ALWAYS create enumerators see http://blogs.msdn.com/etayrien/archive/2007/03/17/foreach-garbage-and-the-clr-profiler.aspx

     



    The ZBuffer - News and information for XNA and Managed DirectX
  •  10-25-2007, 3:21 PM

    Re: XNA Useful Facts

    Also, in the 2.0 framework we have improved several collection types that used to create enumerator garbage so they no longer do so.

    The theory that foreach is slower than for is simply not true.

    For some types of collection, a foreach loop will create garbage. Depending on your game, collecting that garbage may take time, but it may also be very quick. It depends.

    For other types of collection, foreach will not create garbage.

    For some types of collection, using a for loop and indexing into the collection may cause slow index validation tests, which could be avoided if you used foreach.

    For other types of collection, for and foreach will both require the same amount of validation work.

    It depends.

    But it is just flat out wrong to say that one is always going to be faster than the other.

    --
    XNA Framework Developer
    blog - homepage
  •  10-25-2007, 3:35 PM

    Re: XNA Useful Facts

    Shawn Hargreaves:
    The theory that foreach is slower than for is simply not true.

    I definitely didn't try to say either was faster than the other. I actually always did assume the foreach would be faster by using an enumerator instead of indexing. I was speaking more in terms of garbage creation.

    For some types of collection, a foreach loop will create garbage. Depending on your game, collecting that garbage may take time, but it may also be very quick. It depends.

    For other types of collection, foreach will not create garbage.

    I didn't know there were types that didn't generate garbage. That's one thing I didn't actually know. I figured all uses of foreach created an enumerator which later got fed to the GC. Learning something new each day I suppose.


    Nick Gravelyn -- Microsoft XNA MVP
    XNA Wiki | Zune Games
  •  10-26-2007, 2:20 AM

    Re: XNA Useful Facts

    Bapabooiee:

    using "foreach" to render all of the meshes is a bad idea. This is because whenever you hit a foreach, it actually creates allocates a new object, which results in many, many unnecessary object allocations per second.



    The overhead in startup for a foreach is typically insignificant compared to what is being performed inside the loop.

    Cheers,
    Michael

    Member
  •  10-26-2007, 2:45 AM

    Re: XNA Useful Facts

    Nick Gravelyn:
    Swordshock:
    Bapabooiee:

    As for me... Uhm... When you're creating a 3D game, and such have lots of level-geometry and models running around, using "foreach" to render all of the meshes is a bad idea. This is because whenever you hit a foreach, it actually creates allocates a new object, which results in many, many unnecessary object allocations per second.

    If efficiency is a must, don't use foreach. Make your own way of looping through all the meshes.

    Lies, all lies. =P  The amount of time used in allocating an enumerator is extremely short in comparison to the amount of time spent drawing all the meshes.

    To put Baabooiee's idea into a better stated way. Each time you hit a foreach loop you generate a new object on the heap. After that loop ends the GC has to take care of it. If you do a lot of foreach's each frame, you will get lots of unnecessary garbage. We should try and emphasize to everyone that allocations aren't the problem, it's the resulting object being sent to the GC that will potentially cause you problems.

    Of course do read Shawn's post. For beginners with not a lot going on in their game, you can probably get away with using the foreach loop. If you are rendering lots of models and doing lots of computations, you may want to avoid the foreach so that you don't generate the unnecessary garbage.



    Hmmm...perhaps but where do you want to stop?  I can call any method in any API and I'm pretty sure that somewhere within the confines of the code an object will be created for one reason or another.  Whether I made a call to read from a file; play a sound; or read from the keyboard.

    It all depends on HOW many objects in question.  Allocating < 100 per second is insignificant.

    Objects are inevitable.   I really doubt that a few enumerator objects being created per frame are going to significantly impact performance.  The MSDN and Creators Club samples run quite well with enumerators.  This issue is not specific to XNA but .NET as a whole.  .NET has been around for some time now and much performance testing has been done.  

    My c# raytracer just loves enumerators. It's only 10% slower than the original c++ which is the approximate performance hit of moving away from c++ anyway. :)

    Cheers,
    Michael

    Member
  •  10-31-2007, 7:57 PM

    Re: XNA Useful Facts

    Michael Duncan:
    The overhead in startup for a foreach is typically insignificant compared to what is being performed inside the loop.

    In fact, sometimes it's free. The JITter is smart enough to convert a 'foreach' to a 'for' when used on Arrays, for instance (disclaimer: I know this is true on the desktop CLR).

    The bigger issue with foreach over meshes to draw stuff (as the OP was talking about) is that if you are really worried about performance, chances are you are sorting things by material anyway and you have a custom system for that. Making that adjustment will save you dozens of GC's worth of time per frame.

  •  11-05-2007, 10:42 AM