By Jim, on May 8th, 2012 Let’s say that you have a particular task in your program that is executed as the result of an external signal, but you don’t want the task to execute more often than once per second. This is different from a periodic task that you want to execute once per second. This one, you don’t want to execute unless the external signal is received. Your first cut of the function might look like this:
// The last time a signal was processed
// Initialized to DateTime.MinValue so the first signal received
// will not be lost
DateTime LastSignalTime = DateTime.MinValue;
// Lock object to prevent re-entrancy
object SignalLock = new object();
// Minimum time between invocations
static readonly TimeSpan MinimumTime = TimeSpan.FromSeconds(1.0);
void SignalReceived(SomeObject dataObject)
{
if (!Monitor.TryEnter(SignalLock))
{
// Currently processing. Exit.
return;
}
try
{
if ((DateTime.Now - LastSignalTime) < MinimumTime)
{
// Already processed within the last second.
return;
}
// ...
// do processing here
// ...
// And then save the last signal time.
LastSignalTime = DateTime.Now;
}
finally
{
Monitor.Exit(SignalLock);
}
}
That looks reasonable. I covered all the bases, protecting the processing with a Monitor to prevent re-entrant use, and checking the time to ensure that I don’t process a signal more often than once per second.
There’s only one problem. The program assumes that DateTime.Now will increase by one second for every wall clock second. This code does not take into account Daylight Saving Time changes, changes caused by updating with an NTP service, or the user resetting the clock. If one of those events occurs, things fall apart.
For example, when we set the clocks ahead in the spring, this code could process twice in a very short period of time. Imagine that you processed a signal at 01:59:59.800. 200 milliseconds later, the time will be 03:00:00.000. Your code would then process another signal, even though less than one second has passed.
It’s worse when the time is set back in the fall. Say you process a signal at 01:59:59.100. 900 milliseconds after that, the time is changed to 01:00:00.000, and it will be another hour before the code does any more processing.
You can avoid those DST errors by using DateTime.UtcNow in place of DateTime.Now, but that won’t solve the problem that occurs with NTP or user-initiated time changes.
The problem here is that your code is depending on the system clock, which the program doesn’t control. The clock can change at any time, and if you depend on it for critical processing you’re going to be sorry.
You can remove that dependency by using a Stopwatch, which measures elapsed time independent of the system clock. In the code below, I initialize a Stopwatch when the program starts. I’ve modified the logic slightly to save a NextSignalTime, which represents the time when another signal can be processed.
// The amount of time elapsed since the program started
static readonly Stopwatch ProgramTimer = Stopwatch.StartNew();
// The next time a signal can be processed.
TimeSpan NextSignalTime = TimeSpan.Zero;
// Lock object to prevent re-entrancy
object SignalLock = new object();
// Minimum time between invocations
static readonly TimeSpan MinimumTime = TimeSpan.FromSeconds(1.0);
void SignalReceived(SomeObject dataObject)
{
if (!Monitor.TryEnter(SignalLock))
{
// Currently processing. Exit.
return;
}
try
{
if (ProgramTimer.Elapsed < NextSignalTime)
{
// Already processed within the last second.
return;
}
// ...
// do processing here
// ...
// And then save the next signal time.
NextSignalTime = ProgramTimer.Elapsed + MinimumTime;
}
finally
{
Monitor.Exit(SignalLock);
}
}
This code can’t be affected by system time changes because it doesn’t depend on the system time.
You don’t control the system clock. Don’t depend on it for measuring elapsed time. It’s fine to depend on it to tell you what time of day it is. If the user changes his clock, that’s his problem. But you can’t be at the mercy of the system clock if you want accurate elapsed time measurements.
By Jim, on May 7th, 2012 I’d go crazy if all I carved was those little birds. I’m up to 40 different types of wood now, and am still on track to make 100 by the end of the year.
I wanted to make a spoon a few weeks back, and ended up carving this one. Then I got involved in other things. I found this almost done spoon on my desk over the weekend and took the time to sand and finish it.


Click on the pictures to get a larger image.
The spoon is carved from a piece of mesquite that I trimmed from one of my trees last year. I cut out the rough shape on the bandsaw, shaped the handle and bowl with the Foredom power carver. I started to use the Foredom to hollow out the bowl, but the only hollowing bit I had at the time is very small and not very aggressive. So I clamped the spoon in my vise and took a gouge to the bowl.


The spoon is right at 12 inches long. The bowl is 3 inches long and 2.5 inches wide. It’s about 3/4 inch deep at the back.
As you can see, there are several largish cracks. I filled those with two part epoxy and then sanded them. There was also a much larger worm hole on the handle (the discolored part in the first picture) that I filled with epoxy. Next time I’ll think about doing some kind of inlay there. Perhaps some crushed turquoise.
I usually use an oil and wax finish on my spoons because I like simple finishes. But there were enough little cracks in this piece of wood that I thought I’d go with something else. I used Salad Bowl Finish, which is a pretty popular finish for wooden utensils. It’s durable and food safe. But a pain in the neck to apply. You have to apply it, wait 12 hours, sand, and repeat. They recommend at least three coats, which is what I applied. I think I’ll go with two coats the next time I use this stuff. And I might have to sand a little better between coats.
I like that the finish doesn’t darken the wood like the oil finishes I’ve used. But I don’t much like the shiny look. I think next time I’ll try melting some beeswax. I know of some people who use that to great effect.
Still, I like the spoon. I hope Debra gets good use from it.
By Jim, on April 25th, 2012 I headed south to New Braunfels, TX yesterday to get a look at the Texas Woodcarvers Guild Spring Round-Up. The Round-Up is a week-long event that features classes, a banquet, a Whittlin’ Contest, and a few vendors set up to sell things that carvers buy. A lot of carvers are unabashed tool junkies, there were lots of tools available for sale.
The Spring Round-Up does not feature a show or any real “public” appeal. The general public is welcome to come in and look around, of course, but there are no tables set up with pieces on display, and there is no judged contest. The judged show takes place in the fall–typically the last week of September or first week of October.
I had two goals for my trip: to participate in the Whittlin’ Contest, and to buy some tools. I’m decidedly not a tool junkie, but I’ve been carving for three years with just a knife (okay, I own a handful of knives), one V-tool, and one gouge. There are things I can’t do (or can’t do easily) with those few tools, so I thought I’d pick up a few other gouges. I could have ordered the tools online, but wanted some advice from more experienced carvers, and the ability to hold the tools in my hand before I shelled out money for them. I ended up with six new gouges and a few new power carving bits, all of which should help me improve my carving.
I spent Tuesday afternoon wandering around the floor, briefly watching and listening to the classes that were taking place, talking to other carvers, and generally having a good ol’ wood nerd time. I also spent a little time in the Carving Corner, whittling a little dog and chatting with other carvers. Once again I was struck by how friendly and inclusive carvers are. Every carver there, from those who are just starting out to the most accomplished, were happy to sit around and chat while whittling away on a project. And they’re happy to answer questions and spend their time demonstrating some technique or other. Whittling with this group is a relaxing and entertaining experience.
The Whittlin’ Contest was scheduled for 7:00 PM. There are three classes: Novice, Intermediate, and Open. There are a few set rules, the most important being that if you win in one of the lower classes, you have to move up. Beyond that, the person in charge of the contest (who, by tradition, is the person who won the Open class the year before) sets the other rules.
Because I had never done this before, I entered into the Novice class. There were five of us in Novice, five or six in Intermediate, and almost a dozen in the Open class. We all sat down at our respective tables and they passed out the wood. The Novices got a block of basswood, 2-1/2″ x 2-1/2″ x 3″. They told us to carve a “Civil War hat,” further clarified as “any kind of hat you would have seen during the Civil War.”
The Intermediates were given a piece that was approximately 8 inches long, and cut in to a triangle that was about 2″ on a side. I think their instructions were to carve “a military scene.” The Open contestants were given a block about 2-1/2 inches square and maybe six inches tall, and told to carve “a Civil War caricature.”
We Novices were told that we could use any tool in our toolbox. The Intermediates were limited to, I think, three tools, and those in the Open category could use only one knife. They told us that we had an hour, and started the clock.
I don’t know much about hats in general, and I know even less about the kinds of hats worn during the Civil War. I could picture the Confederate cap, but not well enough to try carving one without a reference. But I figured that I could do a cowboy hat. Certainly somebody during that time was wearing cowboy hats. The only problem was that I had to remove a whole lot of wood to realize my vision.
At one point, after I made a mistake and broke the brim of what I was working on, I considered changing to a stovepipe hat, but I ended up having enough time left over to make it look kind of like a cowboy hat.
Judging is done based on originality, technical quality (proportion, symmetry, clean cuts, etc.), and also on completeness. Somebody told me that completing the project within the time allotted was worth a lot in the judges’ eyes. I had carved a couple of stovepipe hats before, and one (failed) cowboy hat, so I was pretty sure I could finish this project in an hour.
I did finish it in an hour, and although it’s a bit of a goofy looking hat, I ended up winning first place in the Novice category. Here’s my hat along with the second and third place winners.

I think that either of the other two would have beat mine, had the carvers finished them in time. My hat is two inches tall, and the brim is two inches in diameter. Here’s a closer picture.

I was going to show the Intermediate and Open winners, as well, but the pictures were very blurry.
My prize was a plaque:

I’ll be the first to admit that my hat is no great carving. But then, I was under pressure just to finish something in the allotted time. Given advanced notice and unlimited time, I could do a much better hat.
I honestly was very surprised to win this little contest. But now I have to move up to Intermediate, and that’s going to require a lot of practice. Even the worst of the Intermediate entries was beyond my current skills.
By Jim, on April 18th, 2012 I had my bike repainted last year, and even started riding it. Then I got busy with other things (or maybe I just got lazy). The bike spent most of the last 12 months hanging in the garage overlooking the bandsaw. I’d take it out every couple of months just to assuage my own guilt, but then it’d go back on the rack and I wouldn’t think much about it for a while.
I’ve been saying for the last month that I’m going to get back on the bike, but I’ve been putting it off. This morning I got frustrated with the program I was working on, and decided to take a ride and clear my head. An hour on the bike usually does.
Every time I come back to cycling after a long absence, I unable to understand how I could possibly have stopped. That first few miles feels so good: back out on the road, enjoying the fresh air and the wind in my face, nothing heavy on my mind. It’s very liberating.
It hurts, of course. My legs aren’t used to climbing even the smallest hills. But I know that within a couple of weeks the pain will be gone and I’ll feel a lot better. I just can’t understand how I could have stopped riding again.
I took an experimental loop through a new subdivision and was on my way home when I saw a large group of riders–perhaps as many as 50–coming up on the other side of the road. There were two motorcycles in front, obviously part of the ride, and three vans following. One of the vans said, “Ride 2 Recovery” on it, and “Wounded Veterans Ahead.”
I had to go see what that was all about.
I turned around, sprinted past the vans, and caught up with the riders. I struck up a conversation with one of the riders, a former Army Ranger from Albuquerque, NM. They’re participating in the Texas Challenge: a 6-day ride from San Antonio to Arlington. The riders raise money to help support the programs that Ride 2 Recovery sponsors. I talked to this guy for a few more minutes, then rode up the line offering encouragement before turning around and heading home.
Had I been in better shape, I probably would have stayed with them all the way to Fort Hood, and then found a ride back somehow. But I figured that 50 miles was probably a bit too far for my first ride after over a year of not riding seriously.
“The Ride 2 Recovery,” the web site says, “is produced by the Fitness Challenge Foundation, (501C3) in partnership with the Military and VA Volunteer Service Office, to benefit Mental and Physical Rehabilitation Programs for our country’s wounded veterans that feature cycling as the core activity.”
Call it fate, coincidence, serendipity, whatever. The likelihood of me running into a group of riders on a Wednesday morning, out on the back roads on my first ride of the season is pretty low. But then, improbable events happen quite frequently. After all, people do win the lottery. Whatever the reason, or even if there was no reason, I sure am glad I encountered this group today. That’s some serious motivation.
By Jim, on April 13th, 2012 It’s surprising how often I hear (or see written) a programmer saying, “…and then I’ll compute a unique hash code that I can use for a key.”
The term “unique hash code” is a red flag indicating that the programmer who uttered it does not understand hash codes and is about to do something incredibly stupid. Let me provide a simple example.
In .NET, every object has a GetHashCode method that computes a 32-bit number that can serve as a key in a dictionary or hash table. Used properly, the hash code lets you create very efficient data structures for looking things up by name. But there’s no magic involved, really.
Used as intended–as the keys in a dictionary or hash table–hash codes work very well. If you try to use them for something else, it’s not going to work.
Let’s say you foolishly decide to use a hash code for a “unique key” when indexing some strings.
The number of strings is essentially infinite. The number of unique values that a 32-bit hash code can represent is a little more than four billion. So it’s a certainty that two or more strings will produce the same hash code. You might think, if you’re only storing 100,000 values, that the chance of collision (two strings hashing to the same value) is so small as not to matter. You’d be wrong.
If you’re familiar with the Birthday Paradox you know that, in any group of 25 people selected at random, the chance of two having the same birthday (month and day) are better than 50%. In a group of 60 people, it’s almost a certainty. If you don’t believe the math, you can do some empirical research of your own.
Hash codes are a lot like birthdays in this regard. A good rule of thumb is that the chance of collision (two items hashing to the same value) is 50% when the number of items hashed is equal to the square root of the number of possible values. So with a 32-bit hash code, the chance of two items hashing to the same value will be 50% when you’ve hashed 2^16, or 65,536 items. Again, if you don’t believe me just write a program that generates random strings and try it.
Another rule of thumb is that you’re almost certain to get a collision when the number of items is four times the square root. So with a 32-bit hash code, the chance of getting a collision when adding 256,000 items is almost 100%.
This is second year Computer Science stuff. Maybe even first year? And yet I hear the term “unique hash code” thrown around distressingly often by experienced programmers who should know better. It’s frightening.
If you’re interested in a bit more discussion and some sample programs that illustrate this point better, see Birthdays, Random Numbers, and Hash Keys.
By Jim, on March 29th, 2012 This piece is an unfinished experiment. I carved the black walnut dolphin last year and had it on a temporary base. Somebody gave me the mahogany dolphin cutout a few weeks ago and after I finished it I was wondering how to display them together. I was considering trying to relief carve some waves when Debra mentioned the possibility of using a piece of bark.
I just happen to have a whole lot of bark from an oak tree . . .

As I said, the piece is unfinished. I’ve sanded and finished the dolphin carvings, but the oak bark is still raw. I’ll have to put something on the bark so that it won’t flake off and deteriorate over time.
I realize that neither of the dolphin carvings is especially good. I goofed on the back of the walnut piece–making it too straight and too thin. And I didn’t round the front of the mahogany dolphin very well. That one’s dorsal fin is too small, too. That’s not my fault. The person who gave me the blank had cut it a bit short.
That said, I rather like the idea of using bark as a substitute ocean surface. What do you think?
Here’s another view, closer up.

By Jim, on March 28th, 2012 I spent most of the weekend doing yard work. Specifically, burning the remains of the fig and the wisteria that didn’t fare well over two or three years of drought. I also took down the garden fence, seeing as how we hadn’t actually cultivated a garden for a few years.

Removing the fence posts was no problem. But I set the gate posts in concrete. Removing those is going to be some work. Unless I decide to leave the gate as an artifact.
I also mowed the back yard. I ran out of time to do the front, and I won’t get to it until Sunday. That’s going to be a big job. The recent rains and abundant sunshine have made for ideal grass and weed growing conditions.
It’s surprising how much the grass grows in just a week. If I let it go two weeks, it will be high enough to scratch Charlie’s belly.

Charlie, by the way, is doing well. He was feeling his oats this afternoon, doing laps around the pool. Still a heck of a good lookin’ dog, ain’t he? The bald spots are from surgery to remove some mast cell tumors.
By Jim, on March 20th, 2012 The Hundred Birds Project has occupied most of my limited carving time the last few months. But I’d go crazy if that’s all I carved. Last week I started working on this whimsical house (gnome home) in cottonwood bark, and I finally finished it Monday night. All told I probably have six or eight hours in it.

The piece is a wall hanging, about nine inches tall on the right side, and about two and a half inches wide. Don’t know yet where I’ll hang it.
This is the second “flat back” I’ve carved. I did the other one about two years ago. I also carved a larger whimsical house in a class back in October of 2010.
I like carving the cottonwood bark. The only real problem is that I have to buy the stuff! I might have to find a good supplier, though, and stock up. These things are addictive.
By Jim, on February 20th, 2012 I thought I’d try cloud hosting for source code version control. I’ve been using version control on my local box, but figured it’d be better to have that stuff stored offsite so that I can get to it from wherever I am.
Codesion came highly recommended, and I was pleased with the ease of setting up a new trial account. At least, I was impressed until I tried to access my new repository. If I try to access it from my Subversion command line client, I get this message:
svn: E175002: Unable to connect to a repository at URL 'https://jimmischel.svn.cvsdude.com/jimsstuff'
svn: E175002: The OPTIONS request returned invalid XML in the response: XML parse error at line 1: no element found (https://jimmischel.svn.cvsdude.com/jimsstuff)
I get a similar error if I try to access it with the TortoiseSVN GUI client.
So I thought maybe I misread the terms of the free trial. I went to the Codesion site and tried to view the repository with their ViewVC browser. The result is a browser window containing this information:
An Exception Has Occurred
Python Traceback
Traceback (most recent call last):
File "/services/viewvc_template/lib/viewvc.py", line 4396, in main
request.run_viewvc()
File "/services/viewvc_template/lib/viewvc.py", line 268, in run_viewvc
self.repos.open()
File "/services/viewvc_template/lib/vclib/svn/svn_ra.py", line 204, in open
self.ctx.config)
File "/usr/local/python/lib/python2.5/site-packages/libsvn/ra.py", line 518, in svn_ra_open
return apply(_ra.svn_ra_open, args)
SubversionException: 175002 - Unable to connect to a repository at URL 'http://10.36.235.136/svn/jimmischel/jimsstuff'
175002 - The OPTIONS request returned invalid XML in the response: XML parse error at line 1: no element found (http://10.36.235.136/svn/jimmischel/jimsstuff)
Checking their online forums, it looks as though others have had similar issues in the past few weeks. Sorry, Codesion. If you can’t get a simple free trial to work, I’m not going to trust you with my source code.
There are dozens of sites that offer free or inexpensive Subversion hosting. I don’t have the time or inclination to try every one of them. Anybody have a recommendation?
And, no, I’m not interested in using GIT. Please don’t suggest it.
By Jim, on February 18th, 2012 Debra’s Valentine’s Day present from me this year was this stylized heart, carved from Purpleheart. The rough cutout was about 2-3/4 inches tall, 2-1/2 inches wide, and 1 inch thick. I cut it from a 6″ x 12″ x 1″ piece of Purpleheart that a friend gave me some time ago.

I did the cutout on the bandsaw, of course, and shaping with the Foredom power carver. After that, a lot of sanding with 100, 120, 220, 400, 600, 800, and 1,200 grit paper. Finish is Howard Feed ‘n Wax.
The heart is just the right size to fit in the hand, and it’s very pleasant to hold or to rub absently, similar to a worry stone.
By Jim, on February 7th, 2012 In The White Board Inquisition, I mentioned the FizzBuzz program as a minimum standard for identifying programmers. It’s a simple test that any programmer should be able to write in just a few minutes.
Write a program that outputs the numbers from 1 to N on the console, with these exceptions. If the number is divisible by three, then instead of outputting the number, output the string “Fizz.” If the number is divisible by five, then output “Buzz.” And if the number is divisible by three and five, output “FizzBuzz.” So the first part of your output should be:
1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,Fizz,13,14,FizzBuzz,16
Writing the numbers one per line is fine. I wrote them as comma separated values here in the interest of saving space.
If you can’t write that program, you aren’t a programmer. If you can’t write that program, you’re no good to me as a programmer and your degrees, work experience, and ability to spout buzzwords aren’t going to impress me. If you fail this simple test, I will terminate the interview early.
I am completely flabbergasted at the number of people who claim to be “senior programmers” who can’t even write that simple program.
Some people have told me that I expect too much. “After all,” they say, “we’re not trying to find real programmers, just people who can hook up some Web pages.” That’s crazy. “Hooking up Web pages,” at least in the applications I’ve seen, requires real programming. Increasingly so, in fact, what with the profusion of JavaScript. FizzBuzz tests basic programming knowledge: the use of loops, conditional statements, and simple math. I guarantee that those things are required in even the simplest of interactive Web applications.
Understand, FizzBuzz is just the first test. And don’t expect me to give exactly that problem. I might change it around a bit to see if you really understand it or if you just memorized some code for the interview. You’d be surprised at how many people can write a flawless FizzBuzz, but are totally mystified when asked to modify the program so that it counts down from 100 to 1. It’s frightening.
Years ago, I laughed at the idea of the singularity occurring within my lifetime. Reaching that milestone will require systems that are orders of magnitude more complex than anything we’ve been able to build reliably. I did, however, agree that it could happen sometime in the future. Now, I’m not so sure. Even if we get enough smart people to design such a system, there’s no way a bunch of mush-for-brains “programmers” will ever be able to implement it.
By Jim, on February 3rd, 2012 PowerShell has some nice built-in command line parameter parsing. I’ve only been wishing for something like this for … well, forever.
Imagine you have a script that accepts four parameters:
-EnvironmentName (or -e), which is mandatory
-DestinationDir (or -d), which is mandatory
-UserName (or -u), which is optional
-Password (or -p), which is optional
Usage would be:
myscript -e testing -d c:\test -u username -p password
Writing code to parse and verify those parameters is just busy work. But because we haven’t had a good alternative (at least, not on the Windows platform), we’ve been doing it for years, writing new argument parsing code for every program. Sure, there’ve been some attempts at building a generalized argument parser and validator for particular languages or platforms (like .NET), but not one of those has really caught on.
Until now. PowerShell makes quick work of parameter parsing and validation. You can describe the arguments for the script mentioned above with just a few lines of code.
# ParamTest.ps1 - Show some parameter features
# Param statement must be first non-comment, non-blank line in the script
Param(
[parameter(Mandatory=$true)]
[alias("e")]
$EnvironmentName,
[parameter(Mandatory=$true)]
[alias("d")]
$Destination,
[alias("u")]
$UserName,
[alias("p")]
$Password)
Write-Host "EnvironmentName = $EnvironmentName"
Write-Host "Destination = $Destination"
Write-Host "UserName = $UserName"
Write-Host "Password = $Password"
At a PowerShell prompt, run that script with this command:
.\ParamTest -EnvironmentName MyEnvironment -Destination c:\logs\MyEnvironment
The script will output the parameters as you entered them. The UserName and Password arguments are optional, so the output for them will be blank. If you want, you can include default values for those optional arguments.
I like that you can specify aliases for the parameters. So -e MyEnvironment is the same as -EnvironmentName MyEnvironment.
Note also that -d dest -e env will do the rational thing. That is, the order that you specify arguments doesn’t matter. Well, it does matter if you don’t name the parameters on the command line. That is, .\ParamTest MyEnvironment c:\logs\MyEnvironment will assign the value “MyEnvironment” to $EnvironmentName, and “c:\logs\MyEnvironment” to $Destination.
Unfortunately, there seems to be a bug in the positional parameters stuff. According to the documentation, if you have a parameter attribute on a parameter, then the default is that the parameter can’t be positional. If you use a parameter attribute, you’re supposed to include a Position argument if you want it to support positional processing. That is, in the above code, you should have:
Param(
[parameter(Mandatory=$true, Position=1)]
[alias("e")]
$EnvironmentName,
[parameter(Mandatory=$true, Position=2)]
Conversely, if you don’t want any positional parameters, you should be able to write:
Param(
[parameter(Mandatory=$true)]
[alias("e")]
$EnvironmentName,
[parameter(Mandatory=$true)]
[alias("d")]
$Destination,
[parameter()]
[alias("u")]
$UserName,
[parameter()]
[alias("p")]
$Password)
That doesn’t seem to work. The code above will still support positional parameters. I haven’t yet seen a good way to completely eliminate positional processing.
You can try parameter(Position=-1), but then you’ll get an exception if you try to run get-help on your script. I’ve also seen a hack of using Position=0 on all of the parameters, but that results in some unhelpful error messages if you forget to name your command line parameters.
Even with the oddities having to do with positional parameters, the Param statement is a welcome feature in any programming language.
What I’ve shown above barely scratches the surface of what you can do with Param. You can include a help message with each parameter, create parameter sets, and specify some basic argument validation, all with some simple syntax in the Param statement. If you’re writing scripts or cmdlets, you should study the Param statement.
If, like me, you’re relatively new to PowerShell, it can be difficult to find information about this stuff. A good place to start is the MSDN Windows PowerShell topic. I’ve been unable to find a PowerShell reference on MSDN. For reference material, I start at the TechNet PowerShell page. For information about Param, see about_Functions and about_Functions_Advanced, or type help about_Functions (or help about_Functions_Advanced) at a PowerShell command line.
The documentation I’ve seen lacks good examples, but a little searching and experimenting can yield good results.
With PowerShell, there’s simply no reason to write another batch file. And if you find yourself making large modifications to an existing batch file, you should think very seriously about just rewriting it to use PowerShell. It really is worth your time to learn and use it. I think you’ll find, as I have, that many of those little C# programs you’ve been writing to do various things can be replaced with simple PowerShell scripts.
By Jim, on January 31st, 2012 This is another one of those “I can’t believe I have to address this” posts.
Eventual consistency is sometimes used as an optimization in middle tier and back end processing to help balance the load on busy servers and provide a scalable architectures. In client-centered applications like large Web sites, the idea is to respond to user requests very quickly, with the understanding that for some period of time the data on the server will be inconsistent.
There are other uses of eventual consistency, but this post is about using eventual consistency as part of a client-centric application.
On the surface, implementing an eventual consistency model looks pretty easy. All the server has to do in response to a client request to modify data is queue the request and tell the client, “Okay, it’s done.” The client doesn’t really care when it the update actually happens. The server can take its own good time to update the database or whatever else needs to be done.
If only it were so simple.
Imagine a simple shopping cart like those that you see everywhere on the Web. Using a traditional (transaction-based) model, adding an item to the shopping cart sends a request to the server. The server makes the database modifications required to show that product XYZ is user ABC’s shopping cart. The server doesn’t send a response to the user application until all of the updates are done. After the server returns its response, the user can click the “View Cart” button and see everything that’s in his shopping cart.
With a simple eventual consistency model, the server’s action is somewhat different. The server queues a message that says, “Add product XYZ to the shopping cart for user ABC.” At some point in the future, a database server will see the “Add product to cart” message and process it. While that message is making its way through the queue machinery, the server returns a response to the client application that says, in effect, “The item was added to the cart,” even though there’s no guarantee that the item was actually added. Now, imagine this scenario:
- User clicks “Add to cart.”
- Server queues message “Add product XYZ to the cart for user ABC.”
- Server returns success message to client.
- User clicks “View cart.”
- Server receives request, “Return contents of user’s cart.”
- Server returns cart contents.
- Database server receives and processes “Add product” message.
Because the database server didn’t receive and process the “Add product” message before the user requested the cart contents, the user is going to see his cart without that product in it. The system showed the user an inconsistent view of the data, which breaks the cardinal rule for client applications: never astonish the user.
Any attempt at explaining this behavior to users is doomed to fail. “Oh, you clicked on your cart too fast. Just wait a minute and then refresh the page,” is not a proper response. That’s just going to confuse the user even more. Computers are supposed to make things easier for users. Imagine ordering pizza over the phone:
You: “I’d like a medium pepperoni with onions and green peppers.”
Pizza guy: “Anything else?”
You: “And a two liter soda.”
Pizza guy: “Anything else?”
You: “No. That’s all.”
Pizza guy: “So that’s a medium pepperoni with onions and green peppers. That’ll be $11.94″
You: “And my two liter soda.”
Pizza guy: “Oh, right. And your two liter soda. Your total is $14.98.”
If you want your customers to think your application is the digital equivalent of the stoned-out pizza guy, go ahead and implement a naive eventual consistency model. If you want people to take you seriously and actually use your site, take some time to read and understand what Dr. Werner Vogel, CTO and Vice President of Amazon.com has to say about eventual consistency in his article Eventually Consistent – Revisited.
Pay particular attention to the section titled Consistency–Client and Server, where he talks about variations and conflict resolution. Especially notice that at no time does he mention the possibility of a process seeing old data. That is, if a process updates a data item and subsequently reads that data item back, it will never receive an old value. Using our shopping cart example, the client knows that it added an item to the cart. The server returned an acknowledgement. If the client subsequently reads the cart, that item better be there! If the previously added item is not in the cart, your program is in error, and no amount of explaining to the user is going to change that.
The potential for the user getting an inconsistent view of the data has to be immediately obvious to any programmer who’s competent enough to write the application. That being the case, I have to conclude that the programmer somehow thinks it’s okay to confuse the user. What really astonishes me is that the people in charge–the product designers and managers–accept it when programmers say, “That’s just the way things are when you write a scalable system.” One need only point to Amazon.com for a counter example.
An eventual consistency model that presents an inconsistent view to the client is just plain broken. I have yet to see a reasonable defense for confusing the user.
It’s relatively easy to provide session consistency (see Dr. Vogel’s blog post) so that the client’s view remains consistent, and there are simple and effective conflict resolution strategies you can use on the back end to ensure that your eventually consistent data model doesn’t remain perpetually inconsistent.
Eventual consistency is just one way to extend the scalability of a large distributed Web site. One can go very far (much further than the buzzword artists will have you believe) using a traditional transaction-based system. It’s always a good idea to start with a transactional system because it’s easier to implement and prove correct, and it will serve the needs of all but the largest of sites. Eventual consistency is an optimization that’s designed to extend the capatilities of a larger, working, system. It’s quite likely that, if it comes time to extend your system with an eventual consistency model, you can add it as a layer between the client-facing front end and the server-based back end. Large parts of your existing system won’t change. That won’t be the final word on scalability, but it will let you add capacity that will handle the traffic while you implement the final solution.
Starting with an eventual consistency model is premature optimization, with all of the customary pitfalls. It’s likely that a premature implementation will optimize the wrong thing and not scale the way you intended, because what you think will be the hot spots (the areas that need to be optimized) when you start rarely turn out to be the hot spots by the time you get around to having performance problems. Writing an eventual consistency model when you’re struggling to get a handful of users for your product is wasted effort. Worse, it’s wasted effort up front that costs even more down the road when you realize that you have to throw it out and start over.
My advice for those who are considering an eventual consistency model is the same as what I give to those who think their program needs to be as fast as possible. Make your program work. Then make it scale. It takes a bit of effort to make a working system scale, true. But if you don’t have a working system to start with, you won’t have enough customers to make scaling worthwhile.
By Jim, on January 25th, 2012 If you’re looking for examples of Congressional idiocy, it’s hard to beat the story of $1 Billion That Nobody Wants. In short, there are about 1.5 billion one-dollar coins piled in bags in Federal Reserve vaults. Why? Because nobody wants them. Why is the U.S. Mint still making them? Because Congress said so.
Congress has been trying to shove dollar coins down our throats since the introduction of the Susan B. Anthony dollar in 1979. That turned out to be one of the most unpopular coins in U.S. history, and production stopped after 1981. An increase in dollar coin usage (primarily from vending machines) resulted in another 50 million or so coins being minted in 1999.
In 2000, Congress mandated the Sacagawea dollar. About 1.3 billion of them were minted in that year. Not surprisingly, the coin was highly unpopular with most people, and the number of coins minted per year dropped off sharply.
Still undeterred, Congress passed the Presidential $1 Coin Program in late 2005. This program, modeled after the State Quarter program, began in 2007 and will continue until 2016. It directs the U.S. Mint to product dollar coins with engravings of the presidents on one side. This despite warnings from the Congressional Budget Office that there would be low demand, and the Government Accountability Office warning that unused coin stockpiles and storage costs would increase.
Shockingly, demand for the coins is almost non-existent. Collectors want them. Nobody else cares.
It gets even sillier. Proponents of the Sacagawea dollar were reluncant to sign on to the Presidential coin program until some genius added a provision saying that the Sacagawea dollar must account for at one of every three dollar coins minted in any year.
A couple of quotes from the NPR article struck me as especially funny.
Members of Congress reasoned that a coin series that changed frequently and had educational appeal would make dollar coins more popular. The idea came from the successful program that put each of the 50 states on the backs of quarters.
This is a perfect example of Congressional reasoning. They failed to grasp the most important point. The State Quarter program didn’t magically make people like quarters. People already used quarters. A lot. On the other hand, 30 years of experience show us that people in general just don’t like the dollar coin. One has to think that, after a few major redesigns and a few minor redesigns, the design isn’t the problem. The American public doesn’t want a dollar coin! Stop wasting time and money trying to force one on us.
Here’s the other quote that I found especially amusing. Or frightening, I suppose.
Leslie Paige, who represents watchdog group Citizens Against Government Waste, says the government should withdraw the dollar bill from the market and force Americans to use the coins.
“I think Americans will definitely embrace the dollar coin if they’re just given the opportunity,” she says.
There is a difference, Ms. Paige, between giving me an opportunity and forcing me to use the coin. Please consult your dictionary. And by the way, the most optimistic projections of cost savings by switching from the dollar bill to the dollar coin are about $5 billion over 30 years. That works out to $166 million per year, or less than 5% of what it costs to run Congress for a single year. Just cut the staff of every Senator and Representative by one person, and we’d make up the difference.
But has Congress passed a bill to stop the insanity? Of course not. That would make too much sense. Instead, the Obama Administration has announced that minting of the coins for circulation will be suspended. They’ll still make some for collectors, but that’s about it.
I’ll grant that the amount of money we’re talking about is small. But the reasoning behind the dollar coin idiocy is exactly the same as the reasoning behind everything Congress does. They invent problems and then invent solutions that wouldn’t solve the problems, even if the problems really existed. And yet we continue to choose to pay these people and give them power over us.
We really need to wake up.
By Jim, on January 18th, 2012 In religion, politics, and other endeavors, Truth is an elusive goal. Depending on your beliefs, Truth might be found in the Bible, the Torah, Koran, the Democratic Party platform, or the lessons you learned while traipsing through the woods. Truth, in most endeavors, is highly subjective.
Truth is subjective in programming, too. If you have any doubt, just ask a dozen different programmers to tell you what is the best programming language, the best indentation style, whether domain driven design is a good idea, or whether inversion of control is just a fancy way to say, “do things in the most complicated way possible.” There are plenty of “truths” in programming.
But in a computer program, there can be only one source of Truth. That is, there can be many representations of the data that your program relies on, but only one representation can be considered the Authority. If you create different views of the data or cache some data in order to speed access, you are making a copy that at some point will differ from the Authority. It is no longer Truth.
Once you do this, you have to make a decision. Your choices are:
- Periodically invalidate the cache so that it will be updated from the Authority from time to time. This ensures that your cache will reflect the Authority with a maximum latency of some given period of time. The cache represents Truth as it existed the last time the cache was refreshed.This technique works well if your program can function well with data that is slightly out of date. We use this technique in the crawler to cache robots.txt files. If we always required the most up to date robots.txt, the crawler would have to issue two Web requests for every page it downloaded (one for robots.txt, and then one for the page). Instead, our crawler caches a site’s robots.txt file for a maximum of 24 hours. Truth, in this case, is “as it existed the last time I downloaded the robots.txt,” which will never be more than 24 hours out of date.
- Update the cache whenever the Authority changes. This sounds like a good idea, but there are drawbacks.First, the Authority has to be built with caching in mind, and must supply an API that clients can plug in to. The clients have to accept the Authority’s caching API, which might be overly restrictive.
This can also put an unacceptable performance burden on Authority updates, especially if more than one client is updating its cache. If the Authority has to call each client’s update method, then update speed is limited by the speed of all the subscribed clients. If, instead, the Authority posts updates to a message queue, then there won’t be a perceptible delay in Authority updates, but there will be a non-zero and potentially large latency in the cache updates.
There are many ways of reacting to an update message posted by the Authority. The simplest is to invalidate any cache of the affected data. That can be quite effective, but you have to be careful that your caching layer knows exactly what data it’s holding on to. That turns out to be a rather difficult task, at times.
This update strategy is usually used when you want to maintain an up-to-date view of the Authority data, but with a different organization. It works best when updates are infrequent. If you’re doing frequent updates to the view, you probably want to re-think the Authority and have it maintain a view that’s more amenable to however you’re querying it.
- Understand that your alternate view is a snapshot of Truth as it existed at some point in time, and it is never updated. This works well if you’re reporting on a snapshot, but it’s not a good general caching solution.
There are hybrid solutions that combine options 1 and 2, but in general that’s pretty rare. It seems like the height of folly to implement option 3 if you’re working with live data, but it’s distressingly easy to fall into that trap inadvertently. For example, you might build a denormalized view of some data in your database because querying the normalized view is prohibitively expensive. You initially use that denormalized view for reporting purposes, but then you foolishly decide that you can use it for other things, too. Pretty soon, large parts of your system are depending on the denormalized view, and changes to the Authority aren’t reflected, or aren’t reflected quickly enough. At that point, your system is broken because your user interface isn’t reflecting Truth.
My experience with relational databases has been that if you denormalize the data, you cannot rely on it reflecting any further changes. You can try to write your code so that it maintains the denormalized view whenever updates are made to the normalized data, but those efforts will almost certainly fail. This is especially true over time, when the original developer moves off the project and somebody new who doesn’t understand all of the denormalized structures is assigned to the project. The result is … well, it’s not pretty. I’ve never seen a case in which trying to maintain two separate views of a database worked well over the long term. Don’t try it!
Where relational databases are concerned, your best bet is to design your database so that you can update and query it efficiently. If it’s still too slow after you’re sure that your design is as good as it can be, then you throw hardware at the problem: more memory, a faster processor, faster drives, or a distributed databse.
Note that I’m not necessarily advocating a fully normalized database design. There are very good and compelling reasons to design your database to be partially denormalized. What I’m arguing against is maintaining a denormalized view in addition to a fully normalized view. I know that it’s possible with triggers and other such database machinery. It can even be done well if you fully understand the ramifications of what you’re doing and if you are meticulous in adding and maintaining your triggers. I’ve found, though, that most development teams are incapable of that level of attention to detail.
Segal’s Law states, “A man with a watch knows what time it is. A man with two watches is never sure.” The same holds true when you have more than one source of Truth in your system. You have to understand that, unless you’re querying the Authority, the data you get back will be, at best, slightly out of date. At worst, it will be so wildly out of date that it’s just plain wrong.
By Jim, on January 12th, 2012 My friend and business partner David Stafford recently posted a blog entry, .Net’s Sort Is Not Secure. Don’t Use It. Here’s a Better One, in which he shows that the .NET sort implementation (used by Array.Sort and List.Sort, and possibly others) can easily be made to exhibit pathological behavior.
How bad is it? You can construct an array of one million items that will take the .NET sort implementation more than 80 minutes to sort. The average case is something like half a second.
David’s contention is that this is a security vulnerability. Others might disagree with him, but that’s their choice. David is right. It’s not a great stretch to imagine a Web site that, as part of its work, accepts a data file from a user and sorts that data. A malicious user, knowing that the server is using .NET, could construct a data file that causes the sort to exhibit this pathological behavior, causing the site to become unresponsive. This is nothing short of a denial of service attack, made possible by the poor sorting implementation. As David shows in his post, it’s not terribly difficult to construct a worst-case array.
That fits very comfortably within the definition of a security vulnerability.
David makes two other assertions: that the sort is inflexible, and that the sort is slower than it should be, even in the absence of a malicious adversary.
The sort is somewhat flexible in that it lets you supply a comparison delegate. It does not, however, let you supply a swap delegate. That’s okay in many cases. However, if you’re sorting large structures (value types), or if you want to do an indirect sort (often referred to as a tag sort), a swap delegate is a very useful thing to have. The LINQ to Objects sorting algorithm, for example uses a tag sort internally. You can verify that by examining the source, which is available in the .NET Reference Source. Letting you pass a swap delegate would make the thing much more flexible.
David’s tests show that the .NET sort implementation is slower than it could be. In my opinion, it’s slower than it should be. David’s implementation is faster than the .NET sort in the general case, and doesn’t exhibit pathological behavior in the worst case. The worst case is so terrible, in fact, and so easy to provoke, that the .NET sort should be rewritten.
And yet, the .NET team has refused to address this issue. At best, that’s irresponsible. One can only hope that enough users log in and vote to have the issue addressed, forcing the .NET team to reconsider their decision.
David also noted that LINQ sorting is also vulnerable. What he didn’t point out is that LINQ to Objects uses a completely different algorithm than does Array.Sort. The LINQ to Objects sort is a standard naive Quicksort implementation. As you can see from his timings, the LINQ sort is 50% slower than the already tortoise-like Array.Sort in the face of an adversary.
Understand, the .NET sort will be faster than David’s Introsort in the general case if you’re sorting a primitive type (int, double, etc.) and you’re not supplying a comparison delegate. The .NET sort is faster in that case because it has special-case code to sort primitive types. If David took the time to make special-case additions to his sorting algorithm, it would outperform the .NET sort in those cases, as well.
Of course, even the special-case sorts in the .NET runtime are vulnerable in the face of an array constructed to provoke the worst case.
So take David’s advice: don’t rely on the .NET sort. Download his code and use it.
I’m considering putting together something similar to replace the LINQ to Objects sort. The general idea is to create a class called SafeOrderedEnumerable that implements IOrderedEnumerable, and uses David’s Introsort in the CreateOrderedEnumerable method. To invoke it, I’ll create extension methods SafeOrderBy and SafeOrderByDescending so that you can write, for example:
var sorted = myList.SafeOrderBy(x => x);
That should put LINQ to Objects sorting in the same ballpark as sorting an array. Not the same, of course, but close, and it will avoid the potential pathological cases.
By Jim, on January 7th, 2012 The term “technical debt“, as commonly used, refers to the eventual consequences of poor software design or development practices. The Wikipedia article and most other references consider technical debt to be a Very Bad Thing. The literature is filled with examples of development projects whose combined technical debt eventually killed or seriously hampered the company.
There is a huge amount of literature about techniques that claim to reduce or eliminate technical debt, and there are countless design patterns and development practices to go along with all that talk. Those patterns and practices are usually ways of paying up front in order to avoid having to pay more later. And to the extent that they actually meet that standard, using them to avoid technical debt is a Good Thing.
Unfortunately, those techniques intended to avoid technical debt often cause more problems than they solve, and end up costing more than it would have cost to incur the debt.
It seems every software development pundit preaches a “no technical debt” sermon with the fervor that some misguided financial advisors preach a debt-free lifestyle. And, unsurprisingly, they all have their books, articles, software packages, and training programs that will teach you how to avoid technical debt.
Yes, there’s a lot of hype and snake oil in the software development methodologies business.
Just as there are sound financial reasons to incure financial debt, there are sound business and technical reasons to incur technical debt. In fact, I think technical debt is more often a Good Thing. It takes a very strong argument to convince me not to incur many kinds of technical debt.
The comparison of technical debt to financial debt isn’t perfect. When you take out a loan at a bank or other lending institution, you agree unconditionally to repay the money you borrowed, with interest. I know of only two ways you can avoid paying: bankruptcy and death. In bankruptcy, you might have to pay back some of the debt, and if you die you might leave somebody else with the obligation. And, of course, there are the ongoing interest payments. Financial debt is never free.
Technical debt, on the other hand, often doesn’t need to be repaid, and often has no interest payments. It’s a “free loan.” Not always, but in my experience more often than not. And when it does have to be repaid, the cost is usually quite reasonable.
A good example of technical debt causing a problem is in the development of a Web site. Imagine that you have an idea for a new site. You slap something together in a few days or weeks, post it on your site, and it’s immediately a hit. Within weeks you’re getting more traffic than your poor server can handle. It’s pretty easy to expand your site to use more Web servers, but then your back end database server melts down under the load. That, too, is easily expanded, but eventually you reach a point where some critical component of your system is the bottleneck and there’s no easy way to scale it. Adding a faster server with more memory and a faster hard disk just postpones the problem.
You incurred the technical debt when you slapped together a simple Web site without taking into account the possibility of massive scaling, and now it’s time to repay that debt. And it’s painful. You also have to do it pretty quickly or all your customers will move over to your competitor who spent six months developing a copycat site. You might find yourself, as you crawl in bed at 9 A.M. after another sleepless night trying to retrofit your program, lamenting the decision to ignore the scaling problem in favor of getting something working. And you vow never to do that again.
That’s the wrong attitude to have.
To hear the “no technical debt” preachers tell it, the world is full of failures who would have succeeded had they not taken on the technical debt. And they’ll show you the successes who refused to incur technical debt, opting instead to spend the extra time required to “do it right” up front. What they won’t tell you about, because they don’t know of or choose not to mention, are the many successes who just “slap things together” and deal with the consequences successfully, and the many projects that fail despite “doing it right.” Most sites fail, not because they didn’t develop their software correctly, but because their product idea just didn’t fly. It doesn’t matter how well your code base is constructed if your business idea just doesn’t work.
The “no technical debt” preachers are wrong, plain and simple. They’ll have you believe that any technical debt will crater your project. Even those who say that you should repay technical debt as soon as possible are wrong. As with financial debt, the secret to managing technical debt is to examine each case and make an informed decision. You have to balance the likelihood of having to repay the debt against the cost of repaying it. It’s a simple (in concept, sometimes not in implementation) risk / reward calculation. What is the risk of incuring the debt, and what is the potential reward?
In the case of our hypothetical Web startup, the risk is that your server melts down before you can modify the code to be more scalable. But the likelihood of that risk is pretty darned small. First, you have to build something that people actually care about. The truth is that most Web startups turn on their servers and hear crickets. A few people will come to check it out, yawn, and move on to the next cool new thing. If that happens, you’ll be really happy that you didn’t waste a bunch of time writing your code to support massive scaling.
Even if your site starts getting traffic, it’s not like you’ll get a million dedicated users the first month. You’ll see traffic growing, and you’ll have time to refactor or rewrite your code to meet the increased demand. It might be painful–rewrites often are–but it’s unlikely that traffic will increase so quickly that you can’t keep up with it.
Some developers attempt to design for scalability to start, and in doing so end up making everything scalable. They spend a lot of time building a scalability framework so that every component can be scaled easily. Every component is split into smaller pieces, and each of those pieces is built to be scaled. That sounds like a good idea, but there are huge drawbacks to doing things that way.
The first problem is that not all components need to support massive scaling. In most software systems, there are one or two, or at most a small handful of, components that are bottlenecks. Designing those to be scalable is a Good Thing. Time spent making anything else scalable is a waste of resources. Even the time spent on those things you think will be bottlenecks is often a waste, because it’s incredibly difficult to tell where the bottlenecks will be before you have customers banging on your site. In all too many cases, designing for scalability is like attempting to optimize a program as you’re writing it–before you do a performance analysis to determine where the bottlenecks are.
Designing for scalability makes the code more complicated. Techniques like dependency injection and inversion of control are very effective ways to create more flexible systems, but they make the code more complicated by inserting levels of indirection that often are difficult to follow. Taken to their extremes, these and similar techniques create a bloated code base that is less maintainable and harder to change than the “old style” code they replace. This is especially true when a development team loses sight of the objective (make something that works) in favor of the process. When you see a system that has a nearly one-to-one mapping between interface and implementation, you know that the people who designed and wrote it lost sight of the forest because they were too busy examining the trees.
Those who preach these techniques for reducing or eliminating technical debt assume that you know what you want to build and how you want to build it, and that you have the time and resources to become fully buzzword compliant. In the case of a startup business, none of those three things is true. Startups typically have a few guys, an idea, and lots of enthusiasm. They’re going to try things, quickly building a prototype, making it available for others to look at, and then discarding it to try something else when that idea fails. Eventually, if they’re lucky, they’ll hit on something that seems to resonate, and they’ll start concentrating on that idea. That’s the nature of a startup. Those guys are living on ramen noodles and little sleep, hoping that one of their ideas strikes a nerve before the savings runs out. They don’t have time to waste worrying about things like technical debt.
Fred Brooks, in his 1975 book The Mythical Man Month, famously said:
The management question, therefore, is not whether to build a pilot system and throw it away. You will do that. […] Hence plan to throw one away; you will, anyhow.
That’s as true today as it was back then. Time spent making your first prototype scalable is wasted. You’re going to throw it away. If you’re lucky, you’ll reuse some of your underlying technology. But most of what you write in your first attempt will be gone by the time you finish the project.
As an aside, there are those who say that The Mythical Man Month is outdated and that many of its lessons are irrelevant today because we have faster, more powerful, and less expensive computers, better tools, and smarter programmers. I’ve seen studies showing that programmer productivity is five to ten times what it was 35 years ago. Whereas programmers can do more in less time today, we’re also trying to build systems that are two or more orders of magnitude larger and more complex than the systems being built back then. Brooks’ cautions are more pertinent today than they were in 1975 because teams are larger and the problems we’re trying to solve are more difficult.
Avoiding technical debt is like paying for flood insurance and building a dike around your house when you live on the top of a mountain in the desert. Sure, it’s possible that your house will flood, but it’s highly unlikely. And if the water does get that high, you have much more pressing problems that make the insurance policy and the dike irrelevant. You’ve wasted time, money, and other resources to handle an event that almost certainly won’t ever occur, and if it does occur, your solution won’t matter one bit.
So go ahead and incur that technical debt, but do so intelligently, with full knowledge of what it will cost you if it comes due. But know also that in many, perhaps most, cases, you’ll never have to pay it.
By Jim, on January 3rd, 2012 You’re probably wondering if this is really necessary. Believe me, I’m a bit surprised by it myself. But every day I see evidence that supposedly competent programmers don’t understand this fundamental point.
What am I talking about?
Let’s say you have two lists. One is a list of accounts and the other is a list of transactions that you need to apply to those accounts. Each type of record has an AccountNumber property. In essence, you have this:
class Account
{
public int AccountNumber { get; private set; }
// other properties and methods
}
class Transaction
{
public int AccountNumber { get; private set; }
// other properties and methods
}
List Accounts;
List Transactions;
The items in the Accounts and Transactions lists aren’t in any particular order. Your task is to create output that groups the accounts and transactions, so it will look like this:
Account #1
Transaction
Transaction
Account #2
Transaction
Transaction
Transaction
...etc
The naive way to do this is, for each account, search all the transactions to see if its AccountNumber field matches the account number. Something like:
foreach (var account in Accounts)
{
Console.WriteLine("Account #{0}", account.AccountNumber);
foreach (var trans in Transactions)
{
if (trans.AccountNumber == account.AccountNumber)
{
// output transaction
}
}
}
If the number of accounts and transactions is even moderately large, this is going to take a very long time. If we say that m is equal to the number of accounts and n is the number of transactions, then this will take time proportional to m * n. Imagine you have 10,000 accounts and 5,000 transactions. Your code will look at every transaction 10,000 times, meaning you end up doing 50 million comparisions.
The faster way to do this is to sort the accounts and the transactions, and then do a standard merge, which is among the oldest concepts in computing. The merge itself takes time proportional to m + n, but sorting is a little more expensive. Sorting will take m log m time for the accounts and n log n for the transactions. So the total time is (m log m) + (n log n) + m + n. Let’s do the numbers:
| Sort accounts |
m log m |
10,000 * 15 |
150,000 |
| Sort transactions |
n log n |
5,000 * 14 |
70,000 |
| Merge |
n + m |
10,000 + 5,000 |
15,000 |
| Total |
|
|
235,000 |
Now I’ll be the first to admit that these numbers aren’t perfectly comparable. That is, sorting the transactions list is more expensive than iterating over it, so the merge won’t be 200 times faster than the naive method. But it’ll probably be 100 times as fast. At least. And that’s with pretty small lists. If you’re working with 100,000 accounts and a million transactions, you’re talking maybe 22 million operations for the merge and 100 billion operations for the naive method. The merge will complete in a few minutes (if that), and the naive method will take essentially forever.
In practice you could probably merge those two large lists faster than the naive method would do the smaller lists.
All of the above is elementary computer science. Really, they teach this stuff in 100 level computer science courses. And yet every day I see people asking “how do I make this faster?” That’s bad enough. What’s worse–and what makes me fear for the future–is how many people answer with, “use multithreading!” (Or “Use the Task Parallel Library!”) It’s maddening.
If you have a quad-core machine and you get perfect parallelism, then your program will execute in one-fourth of the time it takes to execute on a single thread. But one fourth of 50 million is still 12.5 million. Even if you applied parallel processing to our simple case above, the naive method will still be two orders of magnitude slower than the single-threaded merge.
No amount of parallelism will save a bad algorithm, just as no amount assembly language optimization will make a bubble sort execute faster than quick sort in the general case.
Remember, a better algorithm gives you orders of magnitude (or even more) increases in performance. Parallel processing gives you, at best, linear increases. Spend your time on improving your algorithm. Then worry about how you might bring multiple threads to bear in order to make it faster.
By Jim, on December 31st, 2011 I laughed out loud when I saw this picture.

I was nine years old when Dad bought a trampoline. He had us check out some books from the library so we could learn the proper way to jump. I don’t know how much attention everybody else paid to those books, but I kind of glanced through them to get ideas for weird and wacky ways I could court death.
All five of us kids got pretty good on the trampoline. My older brother and sister had better form than I did, but I was the wild man. I’d try pretty much any trick I heard about, saw a picture of, or saw somebody else do. I even made up a few myself, although I learned later that they weren’t exactly original.
I do think I came up with original ways to perform unexpected dismounts. On one occasion when I was trying a new trick, I did a back flip right off the trampoline and came down directly in front of my brother, who slowed my descent enough that I landed on my feet. My recollection is that it looked almost like we planned the whole thing. Perhaps his memory of the event is better than mine. I was a bit preoccupied with my life flashing in front of my eyes as I sailed through the air to my doom.
I spent a lot of time on that trampoline from the time Dad bought it until I was 16 or 17. One summer I made a point to spend an hour every day on the thing.
Fast forward 20 years or so when Debra bought me a trampoline for my birthday and I set it up out here in the back yard. It was fun for a while–a week or so–but then the new wore off. It wasn’t nearly as much fun as when I was younger and always had friends who would come over and play on the thing with me. And for whom I could show off my latest trick. Plus, I wasn’t in nearly as good physical shape at 35 as I was when I was 16. Jumping on a trampoline is work.
We sold the trampoline a few years later, and a few years after that we were at a friend’s house. He had a trampoline for the kids, so I took it on myself to teach them a few tricks. No crazy flips or anything–Mom didn’t want me teaching her kids that, although I did have to see if I could still do that back and a half.
I was showing them how to get some real air (feet at shoulder width, pushing off gradually at the right time, using arms to control balance, etc.). I was getting some pretty good height. Then I noticed that the kids were looking under the trampoline, pointing, and giggling. And I was transported back 30 years to when we first got the trampoline and Dad was showing us how to use it. When he jumped, the mat nearly hit the ground! We all giggled at that.
Anyway, seeing the kids pointing and laughing made me start laughing with the memory. So I bounced, shifted to a sitting position, hit the trampoline with my butt … and hit the ground! Yes, the combination of my weight and the height I was getting stretched the springs far enough that I hit the ground.
I checked after that. The trampoline’s weight limit was 200 pounds. And I only weighed 180 at the time. I guess they didn’t think a 180 pound man could get enough altitude to push the mat that far.
And that’s why I laughed out loud when I saw the elephant on the trampoline.
By Jim, on December 29th, 2011 When I started working on yesterday’s blog entry about cache contention, I built an example program that used an array to illustrate the problem. That is, rather than having a struct that contains four counters, I just allocated an array. It made the code somewhat simpler, as you can see here.
const long maxCount = 500000000;
const int numThreads = 2;
const int Multiplier = 1;
static void DoIt()
{
long[] c = new long[Multiplier * numThreads];
var threads = new Thread[numThreads];
// Create the threads
for (int i = 0; i < numThreads; ++i)
{
threads[i] = new Thread((s) =>
{
int x = (int)s;
while (c[x] > 0)
{
--c[x];
}
});
}
// start threads
var sw = Stopwatch.StartNew();
for (int i = 0; i < numThreads; ++i)
{
int z = Multiplier * i;
c[z] = maxCount;
threads[i].Start(z);
}
// Wait for 500 ms and then access the counters.
// This just proves that the threads are actually updating the counters.
Thread.Sleep(500);
for (int i = 0; i < numThreads; ++i)
{
Console.WriteLine(c[Multiplier * i]);
}
// Wait for threads to stop
for (int i = 0; i < numThreads; ++i)
{
threads[i].Join();
}
sw.Stop();
Console.WriteLine();
Console.WriteLine("Elapsed time = {0:N0} ms", sw.ElapsedMilliseconds);
}
The purpose of the Multiplier in that program will become evident soon.
Run with a single thread, that code executes in about 1,700 ms on my work machine–same as the version that uses a struct. But run with two threads, the code takes a whopping 25 seconds! At first I thought that this was evidence of cache contention, so I changed the Multiplier to 8, which spreads out the counters so that they’re guaranteed to be on different cache lines. That is, the first thread will access c[0], and the second thread will access c[8].
That change did indeed improve the run time. The two thread case went from 25 seconds to about 12 seconds. Cache contention was part of the problem, but certainly not all of it. Remember, the two-thread version of my first test yesterday ran in about 2,200 ms on my system.
I ruled out array indexing overhead, figuring that if it was a problem it would show up in the single-threaded case. After ruling out everything else, I was left with two possibilities: either there’s some explicit mutual exclusion going on in the runtime, or there’s some other cache contention that I didn’t take into account.
It turns out that there is more cache contention. You just can’t see it directly because it has to do with the way that arrays are allocated.
When the runtime allocates an array, it allocates enough space for the array contents plus a little extra memory to hold metadata: the number of dimensions, the size of each dimension, etc. This is all contained in a single memory allocation. The layout of an array in memory looks like this:
---------------------------------
| metadata | array contents |
---------------------------------
^
array[0]
The array metadata is smaller than 64 bytes, so the chances of the first array element sharing the same cache line as part or all of the metadata is very high.
That’s half of the problem. The other half of the problem is that whenever code needs to access an element in the array, it has to read the metadata in order to do bounds checking and to compute the offset into the memory block. So whenever you write x = a[i] or a[i] = x, the code accesses that metadata.
If the first array element is on the same cache line as the parts of the metadata used for indexing, then every time you modify that first element, any other thread’s access to the metadata is going to incur a wait for the cache to be flushed. Modifying the first array element invalidates the cached metadata.
The reason it’s worse with arrays than with yesterday’s program is because every time the code executes --c[x], it actually makes two array accesses: one to read the current value, and one to write the modified value. Every array access makes multiple requests for the metadata, so there can be multiple stalls per iteration. That’s not true when accessing fields in a structure like we did yesterday.
The solution is to put some padding in the front of the array, as well as between the items we’re incrementing. As it stands right now, the indexes being used are 0, 8, 16, and 24. Shifting that right by eight elements would give us 8, 16, 24, and 32. That’s an easy change to make, as you can see here.
long[] c = new long[Multiplier * (numThreads+1)];
var threads = new Thread[numThreads];
// Create the threads
for (int i = 0; i < numThreads; ++i) { threads[i] = new Thread((s) =>
{
int x = (int)s;
while (c[x] > 0)
{
--c[x];
}
});
}
// start threads
var sw = Stopwatch.StartNew();
for (int i = 0; i < numThreads; ++i)
{
int z = Multiplier * (i + 1);
c[z] = maxCount;
threads[i].Start(z);
}
// Wait for 500 ms and then access the counters.
// This just proves that the threads are actually updating the counters.
Thread.Sleep(500);
for (int i = 0; i < numThreads; ++i)
{
Console.WriteLine(c[Multiplier * (i + 1)]);
}
I just showed the parts of the program that have to change. Instead of computing the index using Multiplier * i, I used Multiplier * (i + 1), the counters array is allocated with Multiplier * (numThreads + 1).
If you compile and run that program, you’ll see that the results for one, two, and three threads are almost identical. The result with four threads will be slightly higher, again because system services take a small amount of processor time away from the test program.
What I’ve been calling cache contention is more often referred to in the literature as false sharing. I’d like to thank Nicholas Butler for answering my Stack Overlow question about this, and pointing me to his article, Concurrency Hazards: False Sharing.
|
|
|