Get better at coding or get better at arguing

by Rob Galanakis on 21/04/2011

A while ago, one of the junior TA’s here was frustrated with all the code critiquing I was giving him, and exclaimed: “In 6 months, we haven’t had an argument about my code which I’ve won.”

I replied, “Well, get better at coding or get better at arguing.”

He got better at both.

No Comments

It is 2011. Start building responsive UIs.

by Rob Galanakis on 19/04/2011

In February, I finally figured out my New Year’s Resolution.  It was to build no more UIs that lock up, ever (except in exceptional circumstances where there is no other choice).  It spawned this post that I’ve finally gotten around to finishing (and some of the topics I have started queuing up posts for).

It is a well known customer-service mantra we have that, any response is better than no response. If you can or cannot help someone- or you are in the midst of doing so- you should still tell them what’s going on. It builds better relationships, communication, and confidence in your team.

So it goes with UIs. Nothing is so frustrating to users as a slow UI. Here’s a quick checklist to see whether your UI behaves as it should:

  1. A UI should always stay responsive and never lock up.
  2. A UI should give feedback about what it is doing, and the more detailed feedback the better.
  3. The user should be able to cancel something taking too long.

The frustrating thing to me is that so many of our UIs aren’t responsive, and the only reason is laziness or ignorance. I’ve written my fair share of unresponsive UIs, but I am smarter and more experienced and I say, no more! Threading APIs are sophisticated enough where any programmer really needs to know how to write asynchronous applications. Here’s what you need to learn to create a good UI (my advice is specific to .NET/Windows but the advice should apply to most platforms). I’m going to cover each topic in some detail in later posts (and maybe add/remove/modify topics).

The Windows Message Loop

To understand why your application locks up, you need to understand Windows Messages, the Main Message Loop, and other basic threading concepts. The gist is, your Main thread is what receives messages like user input and is responsible for redrawing, so it needs to be free to act on events. So that means 1) you need it to work asynchronously, so it can act on a message in the queue and go back to doing work, and 2) most processing needs to happen on a background thread. This is a highly discussed topic and much literature is available but I’ll try to give a good summary.

Offloading Work to Background Threads

Offloading work to backgrounds threads means more than just putting long-running tasks into a BackgroundWorker.  Understanding tricks for putting as much on the background as possible can make your UIs much more responsive.

System.ComponentModel.BackgroundWorker

This is the most basic way of keeping your UI responsive, and once you understand how to use it, can be incredibly effective and simple. I consider BackgroundWorkers almost trivial to set up after you create a few. They can be limiting, however, and they do incur some architectural overhead and you may have to make code design compromises. They need to be a tool in your toolbox, but you need to go further.

Tasks Parallel Library (TPL) and Task Parallelism

.NET 4.0 (and 3.5 with Reactive Extensions) has a System.Threading.Tasks namespace filled with all sorts of goodies. The Parallel class is excellent for data parallelism, so you can easy multithread foreach loops and LINQ queries. Task parallelism is much more sophisticated, however, and not too much has been written about it because it is complex. .NET 5.0 is going to be focused on asynchronous programming with the ‘await’ and ‘async’ keywords, which is mostly handled under the hood with the TPL. So you can find tons of good articles about task parallelism by searching for info about the .NET 5.0 CTP (community technology preview).

Immutability

Lots of complexity comes with asynchrony, and especially multithreaded programming. What happens if something fails, or more pertinent to UI programming, the user wants to cancel (what’s the point of having a responsive UI if the user can’t do anything?). Having a situation where we need to be able to roll back/cancel any changes means we need a way to store how things were when the process was started. You can do this by storing state (cloning, essentially), which is difficult to implement and maintain well because it is so unclear (does everything in the object’s references need to clone? What if you have something you can’t clone), or more preferably, having data that cannot change state. To be a good asynchronous programmer, you need to be good at creating and working with immutable data. If your data is immutable, you are safe- cancellation, undos, exception recovery, etc., is trivial because you have data in a good known state that nothing can change.

No Comments

My time at BioWare in numbers

by Rob Galanakis on 17/04/2011

36 The number of months of been working at BWA

5 The number of job titles I’ve held

3 The number of teams I’ve been on/bosses I’ve reported to

2 The number of departments I’ve worked for

1 The number of projects I’ve worked on at BWA

3 The number of times I’ve spoken at GDC *

I started at BWA in April 2008 as an Associate Technical Animator. I was promoted to Tech Animator after several months. After several more months, I helped ‘found’ the Tech Art Team and disband the Tech Animation team (moved from Animation Team to Tech Art Team, and changing bosses). I was promoted to Senior Tech Artist after several more months. I was responsible for hiring 2 additional Tech Artists. I moved over to the Tools Team as a Senior Tools Programmer (moved from Tech Art Team/Art Dept, to Tools Team/Prog Dept, and changing bosses).

*Tech Art Techniques Panel (2009), The Old Republic’s Object Model Pipeline (2010), Tech Art Bootcamp: Ending the Culture War: Building a Better Pipeline by Uniting Tech Art and Tools Engineering (2011)

1 Comment

Augmented Coding

by Rob Galanakis on 15/04/2011

First, a shout-out for the inspiration for this post: Patrick Smacchia and the NDepend developers have given me my first free software license as a result of this blog. NDepend is a pretty awesome static code analysis tool. You can find more info here: http://www.ndepend.com/Features.aspx

NDepend, or any static code analysis tool, is one of many tools in a toolbox that contribute to something I’m now calling ‘Augmented Coding ™’. We’re turning a corner with code development, where we need to get past the idea that coding is just typing text into a window. Joel Spolsky and numerous others have commented how a programmer’s job is more assembling components, rather than actually coding. The most productive programmers understand, and have learned to embrace, this (or they’ve gotten the fuck out to lower-level areas where they can just program closer to the metal).

We need to progress out of the age of the Text Editor.

Skills of ‘principle’ are essential, obviously. But actual ‘technical/trade’ skills will help you develop those skills of principle much more effectively. Great programmers need to be touch typists.  My naive college professors for 3D art used to say, they are supposed to teach you the principles, not how to use the programs. But somehow, myself, a middling artist at best, had some of the best work, because I could fly around Maya, and understood and could writer shaders, and knew all the shortcuts in Photoshop (oh and I taught myself ZBrush, which makes even crap look decent). And now somehow I, a middling typist, can create proper code in a fraction of the time, because I keep my hands off my mouse, because I have ReSharper and use it, and use shortcuts as much as possible (when I say ‘proper’, I mean, things readonly are marked readonly, I have truly immutable classes instead of private setters, things are named/laid out according to conventions, I don’t have unused or improperly scoped members, etc.).  And particularly with NDepend and code analysis tools, codebases are too big for a single person to intrinsically know areas of dead code, unused or heavily used code, non-conforming standards, etc.  If you’re working in a codebase with more than a few other devs, and you think you don’t need static code analysis in your codebase, or it isn’t worth the hassle of getting it setup, you’re wrong- do it and thank me later.

In future posts I may go over what exactly I do and look for when assessing the necessary technical attributes of the fully Augmented Coder- both technical aides like code generation and static code analysis, and better use of existing tools like your IDE or version control.

1 Comment

Lazy iteration, potential benefit

by Rob Galanakis on 10/04/2011

At this point, most people are familiar with the deferred evaluation model of LINQ, using ‘yield’ statements. Since this is new for some teams at work, there’s been a question of when is it appropriate. Deferred evaluation is of most benefit when there is some chance the entire Enumerable will not be evaluated. And it is of dubious use when the source of the enumeration may change. Those are the two extremes- where and when one uses ‘yield’ and deferred evaluation will of course vary according to the task. But regardless, anyone using IEnumerable in .NET 3.5+ needs to understand the deferred evaluation model of LINQ/yield or they will introduce any number of subtle bugs.

Sorry for the length between posts, there was a lot of work and career stuff going on that should be winding down now (and I’ve been doing a lot of travel lately so I have a few blog posts queued up).

No Comments

Great men don’t swaddle themselves in warm blankets

by Rob Galanakis on 17/03/2011

During a discussion today about some necessary-but-scary infrastructural changes, someone (a Lead, mind you) described the status quo as a warm, comforting blanket he wasn’t ready to leave. Horrified, I replied: Great men don’t swaddle themselves in warm blankets.

No Comments

Naive Programming and Multithreading

by Rob Galanakis on 16/03/2011

I on almost weekly basis, I run into some example of naive programming regarding threading. Generally they have the following in common:
1- Uses Thread.Start
2- Show no understanding of CPU-vs-IO bound operations
3- Show no understanding of how a computer manages threads

Take this psuedocode for some widely-used routines I ran into today (actually our custom File.Copy method uses this internally!):

function CopyFiles(fromFilenames, toFilenames):
   for i = 0 to fromFilenames.Count - 1:
      System.IO.File.Copy(fromFilenames[i], toFilenames[i])

function FastCopyFiles(fromFilenames, toFilenames):
   #Bucket filenames into arrays, one for each core
   bucketedFromFiles = BucketFiles(fromFilenames)  
   bucketedToFiles = BucketFiles(toFilenames)
   for i = 0 to bucketedFromFiles.Count - 1:
      Thread.Start(CopyFiles(bucketedFromFiles[i], bucketedToFiles[i]))
   waitForAllThreadsToFinish() #implemented with some counter system

There are so many things wrong with this. I totally understand the idea- the Thread is waiting during IO, so just new up threads to send more IO, while each thread waits for the IO to complete. Here are the major problems:

  1. Newing threads are expensive! Each thread requires a 1MB stack and takes a significant amount of time to create and destroy.
  2. Managing threads is expensive! Each core on your computer can only run 1 thread at a time (basically). There are other programs running on your computer, as well as possibly other threads in your program. Windows allows ‘context switching’, which means a CPU binds to a different thread- which requires unloading and loading a thread’s cache onto the CPU, and a host of other stuff. Creating more threads than you have cores means context switches happen more often. More threads will get created in your program when the CLR detects a thread is blocked and there are things to do, or you request one with Thread.Start.
  3. Your threads are doing NOTHING! While each thread is waiting for the IO to complete, it is doing absolutely nothing. It is just killing time, and your performance.

Naive programming involves parallelizing a process, but not making it asynchronous. Parallelization (especially custom algorithms, not using the built-in ThreadPool/Threading.Tasks.Parallel.ForEach/PLINQ/etc) is good, but you NEED to be wary of IO-bound operations (or threads that launch a separate process, etc.).

The correct approach here is to basically have a single thread (well, just let the ThreadPool manage the threads) to begin an asynchronous write operation, and Wait for the tasks to finish. The ideal is that a thread gets a ‘BeginWrite’ request, runs to the HDD, drops off the request, then comes back up and does more work (probably running back to the HDD to drop off another request). As the HDD finishes the requests, a thread (the same or different ones) can pick up the notification and run a callback, signal that the original request has finished, etc. So no threads are sitting idle waiting for the HDD- they are running around frantically doing work. Which is fine- what we want to avoid is 1) creating new threads, 2) context switches, and 3) inactive threads while there’s other CPU work to do (which means wasted resources).

I’ll go more into the explanation/example for the proper way to implement that FastFileCopy method in a future post (actually probably after I rewrite the one at work). There are already lots of examples of asynchronous IO so you should be able to figure it out yourself. Which you must do if you want to write multithreaded programs. Because you don’t want to be a smart person doing naive programming.

No Comments

Video interview with me at GDC2011

by Rob Galanakis on 12/03/2011

Here’s a video interview I did with Bill Crosbie, a member of the IGDA’s Education SIG. He was interviewing tech artists at GDC to get ideas for a curriculum the IGDA can give to educators, to help grow and raise awareness of the tech art discipline.

The last part of the video is where I talk about how tech artists need to be ‘ruthless.’ It certainly caught Bill offguard, and gave me a focal attribute to talk about for the rest of the week. “Ruthlessness” will of course need to be a topic for a future post.

Thanks a lot to Bill for doing all this!

2 Comments

GDC Slides/Notes online: Ending the Culture War

by Rob Galanakis on 7/03/2011

I’ve uploaded my GDC slides (with full notes/narration). Here’s the link:

Rob Galanakis: Ending the Culture War, GDC 2011 TA Bootcamp (PDF slides/notes)

The main point of the presentation is understanding how to get your Tech Art and Tools Engineering teams to work together effectively (and why they aren’t working effectively now). I go over each team’s strengths (have you ever considered how differently TA and Engineering are set up?!), how to turn adversarial relationships into positive structures (how are tools supposed to get made when all three departments are competing for the same people’s time?), and actual technical strategies for working together (defining strong data interfaces and laying boundaries for a common codebase).

Please download it, read it over, and tell me what you think!

3 Comments

GDC 2011 Wrapup

by Rob Galanakis on 6/03/2011

So, GDC 2011 was fantastic. Really, truly fantastic, on an industry, discipline, and personal level.

This was the largest GDC yet, with something like 18,000 attendees and 600+ speakers.

Our Tech Art Bootcamp was a huge success. Almost filled room from 10am to 6pm on Tuesday. Incredible. The Tech Art Roundtables were packed every day, and the Tech Animator Roundtables seemed to go better than last year.

I think my speech, entitled “Ending the Culture War: Uniting Tech Art and Engineering to Create a Better Pipeline” went incredibly well. Not a repeat of last year’s disastrous presentation.

Going forward:
I’ll get the bootcamp slides up this week.
I’m going to be posting about some of the trends I’ve noticed and challenges we’re facing as a discipline.
Tech-artists.org will be moving into the mobile/social age soon with some much needed site improvements.

No Comments

Switch to our mobile site