Showing posts with label XACT. Show all posts
Showing posts with label XACT. Show all posts

Sunday, 9 December 2012

One Line Of Code

I am sure that everyone has these days when coding.  This is just a quick note to remind people to keep on going no matter how bleak things appear!

I had been working away on the new weapons and effects and got round to testing everything on the Xbox.  I do this from time to time because the Xbox does not perform in the same way as the PC does.  Much to my surprise the performance was a disaster on the Xbox!

That was late yesterday and I was going out in the evening so I left it wondering how long it would take to find whatever it was I had done to cause a frame rate of just 9 frames per second!  It was perfect on the PC but the Xbox was unplayable!

I had thoughts of the level being too complicated and having to come up with some clever code to cull more efficiently, or that the texture files were too large, so I would have to reduce the quality.  I had quickly ruled out the particle effects because although they were pretty the code, quantity and textures sizes were unchanged to effects I had been using for years and the performance graphs did not change when they were on the screen.



I've been working in I.T. long enough to know that whatever you last changed is the most likely cause for whatever problem you are now investigating.  This morning I therefore thought through all the changes since the last time I had successfully tested on the Xbox...

I thought it was a fairly easy non-performance affecting change but I have completely re-written the Audio Manager to change from using XACT to using the SoundEffect classes.

Some quick commenting out and I very rapidly confirmed that somewhere in my conversion I had made a mistake.  To cut an hours searching down I found it.

Just one very short line of code:
nextSong = "";

I had an endless loop that would start playing the next waiting piece of background music every frame because I had not cleared the variable once it started playing!

I am a lot happier now and I can go back to creating assets and effects for the game.

Friday, 13 July 2012

Performance Solved

I have just had the oddest result by fixing one problem I have solved another.  As my wife just pointed out normally it works the other way round.  I normally solve one problem and create two other problems!  Not this time. :-)



To monitor performance while I play the game I use some graphs to avoid creating garbage.  These I display at the sides of the screen to show me memory allocations and CPU usage.  The memory bar goes up and eventually I can see garbage being collected with the momentary slow down on the Xbox.



On the other side I have a performance monitor that measures the time that hardware thread one Update and Draw methods take to complete and a third bar that measures the time taken for the Update that runs on hardware thread four.  These are my primary methods.  The graph is in milliseconds (ms) up to 17 and the bar changes colour to red when any result exceeds 16ms (one frame). 


For a long time I have known that looking in some directions causes a noticeable slowdown and the third bar shows red and off the top of the chart!  Visually the screen would stutter because the position of the view was not being updated quickly enough!  It was probably as annoying as the glitch caused by garbage collection.

As I had run out of things to try to get rid of my remaining garbage I decided it was time that I needed to deal with the performance related hiccup to make it feel nicer to play.

After a bit of fiddling I decided I could not guess where the problem was I needed some way to measure it.  I created myself a simple timer.








    ///  

    /// A static timer which displays the duration of a method in the trace output. 

    /// This is NOT thread safe and cannot be nested. 

    ///  

    public class MethodTimer 
        public static System.Diagnostics.Stopwatch Clock = new Stopwatch(); 
        public static TimeSpan StartTime = TimeSpan.Zero; 
 
        ///  

        /// Mark the starting time to measure from. 

        /// This also starts the timer if it is not already running. 

        ///  

        [Conditional("DEBUG")] 
        public static void Start() 
            if (!Clock.IsRunning) 
                Clock.Start(); 
            StartTime = Clock.Elapsed; 
 
        ///  

        /// Output to the trace window if the duration measured is greater than that specified. 

        ///  

        [Conditional("DEBUG")] 
        public static void Stop(string logName, TimeSpan logDurationOver) 
            if (Clock.IsRunning) 
                TimeSpan duration = Clock.Elapsed; 
                duration -= StartTime; 
                if (duration > logDurationOver) 
                    System.Diagnostics.Debug.WriteLine("Method: " + logName + " took " + duration.TotalMilliseconds.ToString() + " milliseconds!"); 
                return
            System.Diagnostics.Debug.WriteLine("The clock was not running when the Stop method was called!"); 
 




I put it either side of a method and get it to log a result if the time that method takes is longer than I expect.

I was surprised how quickly I got it down to one method causing my problem.  I won't go in to detail about the specific method.  It just simply attempted to do far to much every frame to get more accuracy than I needed.  I produced a much quicker but less accurate version.

Now for the great news.  When I tested that on the Xbox not only had my performance problem completely gone but so had ALL of my memory allocations, no garbage collection!  Two in one.

It's not entirely true that all my memory allocations have gone, but as long as you don't make any new sounds (XACT) or respawn there are none and the tiny allocations that do happen from those methods take a very long time before they would trigger the garbage collection :-)

==

Downloads:
'Performance Tools' including the graphs mentioned above:
http://code.google.com/p/xna-game-menu/downloads/list

Update: 27 July 2012
I have just come across an article written a few years ago  suggesting the same method as above:
http://blogs.msdn.com/b/shawnhar/archive/2009/07/07/profiling-with-stopwatch.aspx

Monday, 24 May 2010

Sounds

I got side tracked again. I was bored play testing in silence so I have added gun shot sounds. I already had music for the menus and a click for menu choices, so I was not starting from scratch.

Basic sounds fitted in nicely. I already had enough code to display a decal when the round hits a structure. That same code path was perfect for putting in the play command for a sound and storing what sound each round made, both at the muzzle and upon impact of an object.

The problems came when making them 3D! Sounds further away need to sound quieter. There is an Apply3D method but to go with it I had to learn how to set this up in XACT. Not as difficult as I thought, but getting it right for my scale, 1 unit = 1m, took some tweeking.

The other problem I have is that for some reason the 3D sounds don't work on my main development PC but are clearly audible on the 360 and on my secondary PC. Odd but it just means I have to test more frequently on the Xbox.

The bit I don't like is that XACT still creates a tiny bit of garbage. I'd avoided the obvious areas but eventually after lots of searches on forums decided the last bit of garbage is unavoidable. Garbage is any object that uses memory on the heap and then needs disposing of during the game. It can interrupt game play. My aim is to avoid any garbage collection during a normal game. My target is 10 minutes between garbage collections.

At the moment I am well within target so I've added sound to my list of areas that create some garbage. It's a short list because the only other thing on it is particle emitters. I'm sure I'll come back to that when I decide I must reduce garbage further.

Back to animating my alien character.