Friday, August 31, 2012

Eat That Frog: A Helpful Philosophy

I've been following this philosophy for about a week now, both at my job and working on my Android game on the side. It really does help! I feel like I'm getting a lot more done, and the 'frog' doesn't taste as bad going down as I think it will looking at it. There is a lot to be said for just rolling up your sleeves and diving in to a problem.

Check it out!

Feeling pretty accomplished at the moment. I would love to hear someone else's opinion on it! Does it work for you, or if not, what does?

Tuesday, August 28, 2012

Android Apps and Image Memory Management


Recently I discovered an interesting (and somewhat counter-intuitive) feature of drawing drawables as bitmaps in an Android game.

The intent: Produce a refreshed canvas at something around 30 to 50 FPS, using about a dozen images.

I had already made several of the images into sprites with source rectangles to handle grabbing the different frames: if you want to know more about what I'm referring to, Google 'drawing animated sprites', and do some digging into the concepts of source rectangles vs destination rectangles.

The responsible programmer in me approached this problem with the idea that I was going to load all my images, draw them, and then recycle and clear them. That would allow the garbage collector to come along and efficiently manage my memory.

After dealing with the surprising limitations of bitmap sizes in the Android VM (a simple 1024x768 background image caused an OutOfMemory exception initially), I was still not drawing nearly as fast as I wanted to.

For reference, one way to load larger images is to use temp storage when loading the drawables into bitmaps, like this 16k buffer I typically use:

        Options options = new Options();
        options.inTempStorage = new byte[16*1024];
        _image = BitmapFactory.decodeResource(_context.getResources(),
                resourcePointer, options);

The goal was 30 to 50 times a second, the initial reality was about 1 frame every 30 seconds. What I was seeing was that the GC was happily gobbling my memory... and taking about 100ms for every image cleanup. Adding that to the load times from the BitmapFactory, and multiply by 12, and there you go.

The solution? At first, it was 'blindly frontload the images'. That way I could avoid the load/dispose delays, but it kept a lot of data around in memory that I wasn't thrilled with. I had to reconcile my need to clean up with the reality that if I needed it again in 20ms, I probably wanted to keep it around.

Eventually I wrote a piece of dynamic code that iterated over all my image processing classes and said 'load or unload based on game state' and returned a boolean telling me to run GC when I was done with the processors. That code ran every frame draw, but only caused delays when changing game state, which I had written such that it happened asychronously when I finished fading out the previous screen but before fading in the new one.

    private void Redraw(Canvas canvas)
    {
    LoadUnloadImages();
        switch (_game.State)
        {
            case X:
                RedrawX(canvas);
                break;
(...)
        }
    }

    private void LoadUnloadImages()
    {
    Boolean runGC = false;
    runGC |= xProcessor.LoadUnloadImages(_game.State);
(...)    
    if (runGC)
    System.gc();
    }


xProcessor.LoadUnloadImages(_game.State) has another switch in it that says to Load or Unload based on state, and the loads/unloads only happen if the image is actually there to unload (or not there to load) so it doesn't waste time on pointless executions. GC only comes back on successful unloads, since the only time I need to explicitly clean up is after I recycle the bitmaps.

That way, each state has only the images it needs, and kills them as soon as the state changes (typically a screen change: menu, paused, main game screen, cutscenes, etc). The combination of all these responsible memory changes have allowed me to easily achieve the 50FPS goal I set out for at the start.

Another thing I should note: this is the only place in the entire app I call System.gc(), because that command WILL slow down your execution if you call it too much / inappropriately. Let the gc work on it's own if you can afford to, but you might still want to think about recycling your unused bitmaps and nulling them out.

Hope this helps all you Android devs out there with similar image delays!

Friday, August 3, 2012

Calling an Asmx Service using PowerShell

So a recent problem we had at work was calling a one-way asmx service on some kind of repeatable schedule; no security concerns to speak of, it was all internal-facing. So it became my job to write something as small and light as possible.

My first approach involved jumping into what I will call our 'existing' ticketing system. The popular analogy we were using was 'using an ICBM to kill a mosquito'. It involved a windows scheduler waking up an executable to drop a message onto an MSMQ, that was picked up by a BizTalk service, and was routed to some command processor. In this case, that would have been an HTML send port in same said BizTalk world... not simple, not quick, and pretty much vomit-inducing complexity for what should be REALLY dumb and simple.

My next approach, somewhat better: a quick console app, pulling the configurable values (server, command parameters) from the app.config. It looked something like this:


        static void Main()
        {
            try
            {
                var username = ConfigurationManager.AppSettings["username"];
                var password = ConfigurationManager.AppSettings["password"];

                var client = new XXXSoapClient();
                client.ProcessXXX(username, password);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                Console.ReadLine();
            }
        }

Better, and certainly usable in our current world. Our Enterprise Architect made a great suggestion to me though; check out  PowerShell, see if there is some really light way to just 'get' the proxy and make the call. Turns out, there was:


        $page = New-WebServiceProxy -Uri 'http://server/InternalServices/XXX.asmx'
        $page.ProcessXXX('USER','PASS');

And there you have it. Two PowerShell lines to call the server, get a proxy, and make the call.