Category Archives: software development

Multithreaded elements of style in javascript

This other day I was just coding and stuff when it suddenly struck me – multithreaded programming! My general ideas about it always revolved around things like scalability, synchronization, and those philosophers who refuse to eat with their hands. What I completely missed was the human side of it – the way it helps developers express their thoughts in code with so much ease and elegance even when they’re not pursuing head-spinning performance. In fact, lots of multithreaded code out there has nothing to do with scaling up and is all about breaking down code into logical sections.

Core Javascript Multithreading

You’re probably thinking I’m way off here because everyone knows javascript is completely single-threaded. That’s right – those DOM events, AJAX, timed events – all executed by the same thread! (see John Resig’s article). The general idea is that javascript executes short-burst pieces of code and can afford to run all events in the same thread. By doing that, it avoids tricky synchronization issues and greatly simplifies the way we work with it.

AJAX and DOM events in javascript are a great example of using multithreaded paradigms (simulated multithreading that is) to simplify coding. The alternative would have been to write your own loop that does something like:

while(true){
runDOMEvents();
runScheduledEvents();
runAJAXRequests();
runEverythingElse();
}

Instead, the javascript runtime already does that for you, so all you need to do is supply the callbacks. In addition, it also runs each event with its appropriate call stack so the multithreaded illusion looks very real in firebug.

Dojo Promises

Building on the existing body of knowledge on futures and promises, Dojo defines the concept of a Deferred.You may have also seen this exact same concept in Python, or a very similar one in Java’s java.util.concurrent.Futures. Java Futures are literally running in a separate thread so getting the future value can afford to block. In Javascript otoh, no blocking is possible since there’s only one thread executing the whole shebang, so the alternative is to provide a callback to execute when the future value becomes available. This means the promised value always gets processed in a different call stack even though it’s all in the same physical thread. However, that’s not a big issue in Javascript since the concept of an execution context is extremely flexible thanks to functions like apply() and call() (or wrappers like dojo.hitch()).

You may have noticed that Java Futures already return an object of the expected type, so you can use the Future as a proxy for the concrete value. For example, we could invoke the process() method below using a String

process("abc");

or we can just as well give it a future String value:

Future<String> future = ...
process(future.get()); // blocks until String is ready

The interface therefore remains uniform whether we use a Future or a concrete value. Since this is not the case in Dojo, we have a solid workaround for it in the form of dojo.when(), which does the extra work of normalizing promises and concrete values for us.

Advertisements

A Total Communication Breakdown

This other day I was just minding my own business, you know, coding and stuff, when I suddenly felt the full wrath of a dissatisfied user. As it turned out, my last year’s project completely missed the mark for this user and he just casually dropped by to give me a piece of his mind. I’m guessing it’s a matter of time before he’s back again.

I’m not exactly troubled by the fact that there are dissatisfied users. It’s hard to build something that pleases everyone and I don’t think it’s realistic to work under such constraints. What really gets to me though is the fact that I completely failed to realize that there were such users while I was running the project. In fact, had I realized that, I would have definitely done something to make up for it – if nothing else, at least a pre-emptive PR campaign.

No, it’s not that I was slacking off. Even though I’m a developer, I typically also run a part-time product management shop out of my cubicle to verify and rectify the original requirements (trust me, I discover a lot of problems that way). In addition, by keeping people involved throughout the project, I can usually claim some pretty satisfied users.

But it still bugs the crap out of me that I didn’t detect these other users who expected something else.

Playing this back in my head, a few things come to mind. The satisfied users were:

  1. Easy to communicate with, which led to in-depth conversations that helped me understand what they want
  2. Proactive with feedback and eager to try out new features right out of the oven
  3. Equally obsessive about getting this done right

As for the dissatisfied users:

  1. Communication problems. For example, I had distributed beta builds in the hopes of getting some good criticism but didn’t get any. Case in point, the same person who came by to yell at me was given a copy of the said beta build. However, he somehow decided to hold his silence until it was too late. This turned out to be a widespread issue among dissatisfied users.
  2. Lack of mental connection. For example, I’ve had people express scepticism about Subversions’s ability to automatically merge concurrent changes. Since Subversion has been doing that really well for years (and before that we had CVS and others), I had to disregard such comments and take the person with a big grain of salt. Not to say that these people actually offered any constructive feedback on the beta build – the discussion never gained any depth. There were a number of such incidents and my course of action each time was to stick with the information from people I found reliable.

How to do better next time? First, you could say the dissatisfied users had their chance and blew it, so they fully deserved this. Well, yes, but I still can’t stand the idea of having dissatisfied users period so I’ll need something better than that.

Looking back at it, it’s a puzzle. I’m building something. I have to figure out what it is, sometimes while I’m building it. There are hidden clues everywhere, reliable and unreliable informants, some of whom withhold crucial information for irrational reasons (too shy, embarrassed, high…). The plot thickens with every conversation, every demo, every new realization. Put it together correctly and you’ll have a project that’s deliverable within specified constraints, and will have a reasonable number of satisfied users. Get it wrong and you might wind up doing it all over again in a couple of years.

When dealing with inarticulate users, remember to ask very specific questions. For example, asking “do you need a vehicle with off-road capabilities?” might give you some of the same blank stares and perhaps amusing answers like “I don’t think it’s possible for cars to operate off the asphalt”. However, ask “do you want acceleration right and brake left?” and you’ll be more successful at jogging the underpowered neurons on the other side, and maybe even have a decent conversation.

I think I’m gonna try that next time…

A Memory Leak where you least expect it

The other day I got some heap dumps that made me rub my eyes in disbelief. There’s this Map that stores a few thousand small strings (about 30 characters each, never more than 50), which in theory should never take up more than a couple of megs of RAM. However, according to MAT (Memory Analysis Tool – you know, the Eclipse plugin), this Map was taking up about 2.5GB instead!

So I went through a bunch of those Strings thinking I’d find a few that were way bigger than 50 characters and call mystery solved. However, they all seemed correct! So what’s taking up the extra 2.49GB?

Here’s a neat little snippet that demonstrates the problem:

 List<String> list = new ArrayList();
  for(int i = 0; i < Integer.MAX_VALUE; ++i)
  {
      String substr = ONE_MB_STRING.toString().substring(0,1); // get first character
      list.add(substr); // keep track of the tiny substring
      System.out.println(i); // how far will we get before it blows up?
  }

We take in a 1MB StringBuilder, convert it to a String, and grab just the first character. The one-character String is stored in the list. This simulates the conditions surrounding the huge memory leak.

So how many iterations before we run out of a 128MB heap?

Answer:

It turns out by the end of the 59th iteration, my test blows up with a big fat OOM. All the memory is eaten up by the list even though all it contains is 59 one-character String objects, provably. What???

It’s actually an interesting Java optimization that just didn’t work too well for us. Java takes advantage of String’s immutability to avoid copying bytes around when it builds substrings. The String class has an inner char[] buffer, as you might expect, along with two integers: offset and count. Needless to say, when you call substring(), you don’t get a String with a brand new buffer but rather a new String that points to the internal buffer of the source String, with only offset and count adjusted to point to the location of the substring. The behavior of the resulting String is exactly as expected, except that it drags around the original buffer with it (technically this is what you might call the Flyweight pattern). In our case, each 1-character substring  was actually pointing to the 1 MB buffer of the original String. Give it a few dozen of those and your heap becomes crammed indeed.

Solution:

The solution is really simple – construct a new String based on the substring. While substring() and split() use the flyweight pattern, the String constructor creates a new buffer based on the toString() value of the original:

list.add(new String(substr)); // keep track of the tiny substring

Update:

I was just taking a nice bubble bath while reading some Java source code when I came across this String constructor:

public String(String original) {
    int size = original.count;
    char[] originalValue = original.value;
    char[] v;
      if (originalValue.length > size) {
         // The array representing the String is bigger than the new
         // String itself.  Perhaps this constructor is being called
         // in order to trim the baggage, so make a copy of the array.
            int off = original.offset;
            v = Arrays.copyOfRange(originalValue, off, off+size);
     } else {
         // The array representing the String is the same
         // size as the String, so no point in making a copy.
        v = originalValue;
     }
    this.offset = 0;
    this.count = size;
    this.value = v;
    }

Check out those comments – looks like someone ran into this problem before…

The Agile Man-Month, Part II

You have ten developers for a five man-year project. How long will it take to complete the project?

Analogously, you sell lemonade for 10 a glass. Yes, 10. The currency is totally immaterial. Canadian dollars, Kazakhstani tenge, or sea shells – I give ten, you give lemonade.

How are these two analogous?

It is a truth universally acknowledged that a software developer is like a ninja. Each is unique, carries a distinct set of abilities, and, surely, has a different force multiplier. One’s force multiplier varies depending on the type of work. For example, some ninjas do better during mortal-style kombats. Others excel at stealth assassinations. Others still specialize in sabotage and infiltration. The total amount of damage that can be inflicted by a team of ninjas depends on the collective force multiplier of that team for that specific type of mission.

Likewise, the total amount of work attainable by a team of developers is the sum of those individual developers’ abilities for that particular type of work.

But, you will argue, the man-month number is just an estimate, and as such is perfectly acceptable. After all, how big can be the difference in force multipliers among ninjas? A ninja is a ninja, and a developer is a resource with some variation.

There are no scientific methods to quantify the difference, but, according to Fred Brooks’ The Mythical Man-Month, “good” developers are five to ten times as productive as mediocre ones. If that’s true (and many developers would agree), one man’s year can be as valuable as another’s ten! This means one developer’s five-year project can be another’s six-month stint, and such.

You have ten arbitrarily-chosen developers for a five man-year project. How long will it take to complete the project?

 

To be continued…