Q is for Heat
Saturday, November 07, 2009
  The Secret to a Great Cartoon


"Dad, why don't we have a panic room?"

When it comes to questions from kids, I consider myself well prepared. If they want to know why the sky is blue, I can give an age-appropriate description of Rayleigh scattering. If they want to know about the "birds and the bees," I'm ready for that talk too. Nothing is taboo; good, honest, unbiased information is what kids need.

But this question from Nicholas threw me. "Where did you hear about panic rooms?" I asked, wondering if the kids at his school were watching a Jodie Foster marathon and if I'd have to explain what exactly Hannibal Lecter was trying to smell in that one scene.

"It was on Phineas and Ferb. Candace said she was going down to the panic room for a while."

"Oh!" I said with relief. "Basically, it's because it's too expensive. We're saving for your college first. And frankly, our house will need a new roof before it needs a panic room." Truth is, I'd love having a panic room, but I would make mine look more like a finished game room, complete with TV, pool table, and fridge. (Wouldn't a fridge stocked with glucagon have come in handy during the movie!)

If you've never seen Phineas and Ferb, you are missing out on a great show. I've known and watched all the shows that Nicholas has been into, ever since Elmo and the Playhouse Disney days. I'm a fan of SpongeBob Squarepants (although I didn't see the latest special yet), I can quote episodes of Chowder, I love Penguins of Madagascar and Back at the Barnyard, and I can even identify a good number of Pokémon. So when Nicholas was getting bored with TV, I suggested to him what some of my coworkers suggested: switch over to the Disney channel (of all things!) and give Phineas and Ferb a try. We both love the show! I won't go into too many details about the show -- you can read about it anywhere on the web -- but believe me, you are in for a treat.

So I got to thinking of what makes a great cartoon. And when I mean great, I mean timeless. Every once in a while, I'll pop a Warner Brothers DVD in and watch "Baseball Bugs." ("Wham! A homer! Wham! Another homer!") Still great stuff, but why?

The obvious answer is, well it's because of all the adult humor. But it's more than that. True, you do need humor in a cartoon, as well as good strong characters. I think the main measure of a cartoon's staying power is how well it relates to the real world. If a cartoon is grounded in real-world references, it will appeal to adults as well as children and it will be talked about by everyone. Phineas and Ferb references a lot of cultural icons, like 80's hair bands ("Love Handel"), monster trucks, and, of course, panic rooms. The same thing can be said of SpongeBob Squarepants; one episode ("The Krusty Sponge") actually mocked SpongeBob merchandising itself. And you can't help but laugh at the American Idol parody "Do You Gots It?" found in an episode of Back at the Barnyard.

Contrast this with shows like Ben Ten. Oh it's a good show, don't get me wrong, but it has limited appeal. It just doesn't tie into anything in the real world. And I challenge you to look at Chaotic or Bakugon and pick out anything "real" about them. You'll hear very few adults yelling "Bakugon Brawl!" in the workplace, and those that do will get very strange looks.

But sing "Agent P!" in the office, and watch how many parents will sing back "Doofenshmirtz Evil Incorporated!" (Of course, you have to sing it the right way...)


 
Sunday, September 06, 2009
  Did 1996 music really suck that much?
I don't have satellite radio. So whenever I drive to other cities, I have to use the seek button and look for good stations. Ok, it's a bit of a pain, but I do love it when I find a good station. And when I went to Baltimore last week, I found one of those "play whatever we want" stations. In this case, it was WQSR 102.7 -- or as they say it, 102.7 JACK FM.

It was Monday morning, around 9am. They had a segment where they would play 15 songs from a given year, and that day, they chose 1996. So I turned my personal wayback machine to 1996, and got myself back into that state of mind. It was the year that Lisa and I bought our house. I was working at Betz Laboratories, at my first "real" programming job. Cool! So what was playing? Here's what I heard:

Then it was time for a commercial.

Good God, I thought. Did all the music from 1996 suck that much? There had to be something good from that year. It was the year after Alanis Morissette released "Jagged Little Pill", so maybe one of those songs would be there, hopefully? And what about "I Love You Always Forever" by Donna Lewis? That was a cute little song, and I remember it was playing the night when Lisa and I drove to our new house. So even though we had almost arrived at the Baltimore Aquarium, I thought I'd give it a few more minutes, hoping that a "good" song from 1996 would be played after the commercial break.

It was "Macarena" by Los Del Rios. What's even sadder is that I like that song more than the first three!

So I made a note to check with the Internet. I said to the Internet: Hey Internet! What were the popular songs from 1996? And by using a clever little query, Google gave me this site. And I was right. The music from 1996 did suck, at least in my opinion. Go have a look!

Well, not all of it. Two songs from Jagged Little Pill did make the list: "Ironic" and "You Learn", which are two of the better songs (especially"You Learn.") "I Love You Always Forever" was there as well. And I could only find two other songs that didn't suck: "1979" by Smashing Pumpkins, and "Name" by the Goo Goo Dolls. Too bad "Name" was overplayed -- it became the "tired song" on the "tired radio."

Even Rush's album "Test for Echo" wasn't that great, although I love "Half the World."
 
Monday, August 10, 2009
 
And now for something unexpected... coding! Since this is the first time that my blog is hooked to my FaceBook account, I feel I should give this warning: Geeky article ahead! Seriously, if you're not a programmer, you won't find this article very interesting.

In this case, I'm talking about SharePoint -- not just SharePoint, but a SharePoint publishing site that we recently deployed. I won't bore you with the details on how we settled on SharePoint. But I will share a little story about how I forgot the finer details of thread synchronization. I spend way too much time on nontechnical tasks, but that's another article.

Here's a quick overview of our publishing site. Think of it as a knowledge base. Each article gets its own page (e.g., /Pages/Abc.aspx). Each article also gets a folder with the same name (/Documents/Abc). On the page, we have a web part that displays a list of the documents in the folder, as well as some custom properties. So far, so good. For performance reasons, once the list of documents is read, the web part caches it inside the HttpRuntime cache. (The cache gets invalidated if a new document is published, and once each night during the app pool recycle.)

To further increase performance, I intended to use a lock so that if 50 users request a page, the web part would only build the list once, and the other 49 users would simply wait for the list. Simple locking scheme, eh? I thought so. Remember, I said it's what I intended to do. What follows is a reasonable representation of my code. Here I show a DataSet used as a cached object, but in reality I used a custom data structure. Plus, I'm leaving a lot out. Anyway, here's the first pass:


private static object _lockObj = new object;

...


DataSet ds = HttpRuntime.Cache.Get(key) as DataSet;
if ( ds == null )
{
  lock ( _lockObj )
  {
    ds = HttpRuntime.Cache.Get(key) as List;
    if ( ds == null )
    {
      try
      {
        ds = FetchDataSet(...);
        HttpRuntime.Cache.Insert(key, ds);
      }
      catch ( Exception e )
      {
        LogException(e);
      }
    }
  }
}


Great, except for one problem. See that static object used as a lock? Well it can't be a local object, that's for sure -- each page request would get a brand new local object, which would be useless for locking purposes. But the problem with a static object is that it is common for the entire application. Which means, that if 10 users are querying 10 different pages, each page would encounter the same lock and wait for the previous one to finish! As you can imagine, performance was dreadful. Even worse, our performance tests did not account for this use case -- which was, in some ways, a more serious flaw than the code itself.

What I wanted was page-level locking. So what to do? Well, I remembered an article I had read waaay back in MSJ -- but I can't seem to find it (and I've looked!) The article was written back in the days of C++ and Win32 critical sections. It explained a technique that let you have thousands of objects appear to each have its own private critical section. The idea was simple -- create a fixed pool of critical sections, store them in an array, then have each object always use a dedicated critical section. The odds that two objects would use the same critical section were low. A well-written, reliable hash function would do the trick.

So I adopted this technique to our web part. The code remained relatively unchanged, except for the part that determined which object to use as a lock. In this case, I took the key and used its hash code to determine which lock was used.


private const int LOCK_POOL_SIZE = 50;
private static object[] _lockPool = new object[LOCK_POOL_SIZE];
static Class1()
{
  for (int i = 0; i < LOCK_POOL_SIZE; i++)
    _lockPool[i] = new object();
}

...

DataSet ds = HttpRuntime.Cache.Get(key) as DataSet;
if ( ds == null )
{
  int lockIdx = Math.Abs(key.GetHashCode()) % LOCK_POOL_SIZE;
  object lockObj = _lockPool[lockIdx];
  lock ( lockObj )
  {
    ds = HttpRuntime.Cache.Get(key) as List;
    if ( ds == null )
    {
      try
      {
        ds = FetchDataSet(...);
        HttpRuntime.Cache.Insert(key, ds);
      }
      catch ( Exception e )
      {
        LogException(e);
      }
    }
  }
}


This worked well enough -- except for one further problem. What if, for some reason, the code that loaded the data failed? What if FetchDataSet throws an exception? Well, the cache would never be filled -- which would result in many requests waiting, waiting for a cache that would never fill, essentially backing up the requests until ASP.NET started queueing requests.

My solution to that was to insert a "poison" object into the cache -- but for only a few minutes. In this case, the "poison" object was an empty DataSet, but you could put in whatever you need. This would alleviate the lock condition, allow the code to display an error, but also allow the problem to be addressed and the code to self-correct. (Sidebar: When dealing with SharePoint, 99% of the time, these "problems" are permissioning setup problems. And yes, we developer have had to solve a fair number of these.)


private const int LOCK_POOL_SIZE = 50;
private static object[] _lockPool = new object[LOCK_POOL_SIZE];
static Class1()
{
  for (int i = 0; i < LOCK_POOL_SIZE; i++)
    _lockPool[i] = new object();
}

...

DataSet ds = HttpRuntime.Cache.Get(key) as DataSet;
if ( ds == null )
{
  int lockIdx = Math.Abs(key.GetHashCode()) % LOCK_POOL_SIZE;
  object lockObj = _lockPool[lockIdx];
  lock ( lockObj )
  {
    ds = HttpRuntime.Cache.Get(key) as List;
    if ( ds == null )
    {
      try
      {
        ds = FetchDataSet(...);
        HttpRuntime.Cache.Insert(key, ds);
      }
      catch ( Exception e )
      {
        LogException(e);
        HttpRuntime.Cache.Insert(key, new DataSet(), null, DateTime.UtcNow.AddSeconds(120), System.Web.Caching.Cache.NoSlidingExpiration);

      }
    }
  }
}


And there you have it. Note that you can change the lock pool size to fit your own needs.
 
Tuesday, January 27, 2009
  She's coming back!
Yep, she's back.



I'm talking about Asli Bilgin, of course. A few years ago, she (along with some other Microsofties) came to Merrill Lynch and talked about .NET 3.5. Well now she's back and she's going to be talking about .NET 4.0. Can you tell I'm excited! What's not to love... a cute babe talking about technology.

This time, however, I won't be asking about the Gaming Engine. For the moment, I've lost the passion for the Gaming Engine. Hopefully, it will return someday.

But for now, I'll just enjoy the talk from Ms. Bilgin.
 
Saturday, December 27, 2008
  Lazer Tag is Tres Cool!
I have a love-hate relationship with Hasbro. For a while there, it seemed the company had lost its creative edge, and only made lame toys or re-hashed versions of older toys. Being a fan of the old Worlds Of Wonder Lazer Tag from the late 80's, I was reasonably suspicious of the new Lazer Tag game by Hasbro. But oh was I pleasantly surprised... this new version is a cool product, and in my opinion is way superior to the WOW version.

Nicholas got it for Christmas. Naturally, guess who he's playing it with?



This is what you get in the box (plus instructions):



You can see that the guns (or "taggers", as they are called) have the target mounted right on the guns themselves (the red dome at the top). The guns also come with the ability to add attachments. The big attachment shown above is the "Shot Blast" attachment, which adds grenade-throwing ability. (More on this in a sec.) Instead of the Shot Blast, you can attach the video game module (that blue thing on the right) instead. Alas, the video game module only works with old-fashioned CRT televisions, and you need a video attachment as well. The other little attachment that goes on top of the gun is a scope, which displays a little green dot to help you aim better. Each gun takes six AA batteries.

The first thing you notice is the array of switches all over the gun. Here are the various switches:

There are also two gauges on the rear of the pistol. The one on the left shows your strength (i.e., health or hit points), the one on the right displays your ammo:



It's one thing when you hold one of these pistols in your hand. But when you fire it -- wow! Inside the gun there is a recoil mechanism, which gives a satisfying kick to your hand and an even more satisfying clicking sound. It actually feels like you fired a round. And the speed! You can easily shoot 3 rounds a second. (The old WOW pistols could barely shoot once per second.) If you have the Shot Blast attachment on, then you have grenade-launcher ability. Simply pump the gun, then fire, and you essentially do a triple-shot. The gun also rumbles when you are hit.

One big difference is the reload feature. After six shots, you have to reload. But Hasbro took this potentially annoying feature and made it fun. You hit the lever with your thumb, which extends the "clip" out about half an inch (it also lights up). A quick, satisfying slap with your free hand, and you're good to go. The grenade launcher does not use any ammo.

Another difference is the shield. During a game, you get 10 seconds of health during a 10-strength game, 25 seconds during a 25-strength game.

I've been playing this with Nicholas, and I cannot wait to introduce this to my friends.

I'm still lukewarm on Hasbro's online presence. If you go to LazerTag.com, it simply redirects to Hasbro's site. According to the directions, the site would list the products that Lazer Tag was compatible with. Yeah, at the bottom of the "Game Tips" section, I found a paragraph that states the game is compatible with Lazer Tag Team Ops, an earlier Hasbro product. The rest of the site has a few interesting things (like various ideas of games you can play).

Ok, but is the game compatible with the old WOW Lazer Tag? No, it isn't -- I tried. That would have been nice. But after playing with these pistols, I don't even want to touch my old Lazer Tag. Seriously. It's that good.
 
Thursday, December 04, 2008
  Gotta get in the picks
Here's what my program picked for week 14. And I swear it didn't know that San Diego is currently killing Oakland:

OAK at SD: SD
JAC at CHI: CHI
CLE at TEN: TEN
PHI at NYG: NYG
MIN at DET: MIN
HOU at GB: GB
ATL at NO: NO
CIN at IND: IND
MIA at BUF: BUF
NE at SEA: NE
KC at DEN: DEN
NYJ at SF: NYJ
STL at ARI: ARI
DAL at PIT: PIT
WAS at BAL: BAL
TB at CAR: CAR
 
Thursday, November 27, 2008
  Still More Football
Happy Thanksgiving!

Just for the record... my program's Week 13 Picks:

TEN at DET: TEN
SEA at DAL: DAL
ARI at PHI: ARI
NO at TB: NO
IND at CLE: IND
SF at BUF: BUF
BAL at CIN: BAL
MIA at STL: MIA
NYG at WAS: NYG
CAR at GB: CAR
ATL at SD: ATL
PIT at NE: PIT
KC at OAK: KC
DEN at NYJ: DEN
CHI at MIN: CHI
JAC at HOU: JAC
 
James Q. Murphy's notes and observations about .NET programming, astronomy, television, and other facets of life.

Name: James Murphy
Location: Hamilton, New Jersey, United States

I'm a software developer at Merrill Lynch, working on Benefits OnLine®, a retirement website. Well, okay, my middle initial is not really Q. But back in college, a friend of mine was calling me "James Q. Murphy," kind of like John Q. Public I suppose. I didn't really like it, and after one particular thermodynamics class, I decided to tell him so. We had just learned about adiabatic systems -- those where there is no heat energy transferred in or out of the system, meaning Q=0. When my friend called me by the dreaded moniker, I simply replied, "Not today, I'm feeling adiabatic." Well he just doubled over, and amongst my friends, the name stuck. Eventually, I grew to like it as well. Don't you love happy endings?

Archives
December 2005 / January 2006 / May 2006 / June 2006 / August 2006 / September 2006 / October 2006 / December 2006 / January 2007 / March 2007 / May 2007 / August 2007 / September 2007 / October 2007 / December 2007 / January 2008 / April 2008 / September 2008 / November 2008 / December 2008 / January 2009 / August 2009 / September 2009 / November 2009 /


Powered by Blogger

Subscribe to
Posts [Atom]