Tag Archives: performance

Maintainable Software and Premature Optimization

Software should be maintainable. Software should also be performant. Which is more important? Well, as it turns out, in order to optimize software for performance, it must be maintainable. Ease of change can easily be the most important factor in making something run well.

Premature Optimization

“In which everything is possible but nothing of interest is easy.”
– Alan J Perlis

Optimization up front often hinders evolution, because it’s designed to address a very specific concern without regard for future concerns. This is not to say that optimization is not important, it’s just something that should be done in such a way as to not hinder the ability to respond to change. Also, today’s compilers are a lot smarter than you are and can perform lots of optimizations themselves. Sometimes you simply aren’t smart enough to know where the bottlenecks occur, so it’s important to not optimize until you’ve actually proven via measurement where and why a performance issue occurs.

Programmers are really smart people, but unfortunately many programmers take pride in their ability to develop and understand complicated code. This is a danger that must be understood and avoided; particularly when it results in less maintainable code, or code in which only that single developer is capable of understanding and maintaining.

YAGNI

You Ain’t Gonna Need It. Resist the urge to optimize or implement functionality until it’s needed. This simple idea is actually the basis for much of agile software development. 90% of the functionality developed and shipped quickly is better than 100% of it shipped late or never. Why should you hold off on optimizing or implementing until it’s needed? The simple truth is that you don’t know what will be needed down the road, and so developing for it now will be a waste of time. Often times it turns out the code you prematurely wrote isn’t even needed, or your assumptions were wrong. So not only will you not need it, but even if you do, it won’t be in the right form that you are anticipating today.

 

Clarity and Explicitness

Writing code that’s clear and explicit is better than writing code that’s clever. Programmers are really expensive, so it’s to your benefit to write code that optimizes for their time, and the way to do that is to write code that communicates to people, not the machine. Write the code so that it can be understood now and in the future with little or no additional explanation needed about how it works.

Delete Code

Everyone has probably seen Andy Hertzfeld’s story of Bill Atkinson during the development of MacPaint:

In early 1982, the Lisa software team was trying to buckle down for the big push to ship the software within the next six months. Some of the managers decided that it would be a good idea to track the progress of each individual engineer in terms of the amount of code that they wrote from week to week. They devised a form that each engineer was required to submit every Friday, which included a field for the number of lines of code that were written that week.

Bill Atkinson, the author of Quickdraw and the main user interface designer, who was by far the most important Lisa implementor, thought that lines of code was a silly measure of software productivity. He thought his goal was to write as small and fast a program as possible, and that the lines of code metric only encouraged writing sloppy, bloated, broken code.

He recently was working on optimizing Quickdraw’s region calculation machinery, and had completely rewritten the region engine using a simpler, more general algorithm which, after some tweaking, made region operations almost six times faster. As a by-product, the rewrite also saved around 2,000 lines of code.

He was just putting the finishing touches on the optimization when it was time to fill out the management form for the first time. When he got to the lines of code part, he thought about it for a second, and then wrote in the number: -2000.

I’m not sure how the managers reacted to that, but I do know that after a couple more weeks, they stopped asking Bill to fill out the form, and he gladly complied.

This is a great example to follow when considering YAGNI. Not only should you resist the urge to prematurely optimize or develop, you should also aggressively remove unused or unneeded code.

Solutions?

How do you protect your code base from complexity and premature optimization?

The only real solutions here are as follows:

  1. Hire developers who understand YAGNI
  2. Hire developers who understand that a primary goal of their job is to use their code to communicate to other developers instead of the computer.
  3. Encourage a culture that understands that simplicity is better than complexity.

I’ll end with the same quote everyone slathers around the web, because even though it’s repetition is common, it’s still true.

“Premature optimization is the root of all evil.” –Donald Knuth

RavenDB: Lessons Learned: Query Includes and Projections

Note: This was originally posted over on the Development @ MSNBC blog.

By default, RavenDB will only allow 30 requests per session. This is part of RavenDB’s “Safe by default” behaviors, to prevent you from making a giant number of RavenDB HTTP requests, which would be a performance quagmire.

Let’s say you have an object graph that you are retrieving from RavenDB that contains referenced documents, and it looks like this:

stories/123
{
  "Headline": "New iPad is key to Apple's bottom line",
  "Author": "Jack Smith",
  "LastPublishedAtUtc": "2012-03-14T23:48:00.0000000+00:00", 
  "PublishStatus": "Published",
  "StoryReferences": 
  {
    "storyreference/456213": 
    {
      "Headline": "New iPhone coming soon",
      "Author": "John Doe"
    }
    "storyreference/789654": 
    {
      "Headline": "New iPad foils reviewers' attempts to find legitimate faults",
      "Author": "Jane Doe"
    }
    "storyreference/555111": 
    {
      "Headline": "Now on Netflix: Search by TV network",
      "Author": "Jack Smith"
    }
    "storyreference/942342": 
    {
      "Headline": "Apple stores to open at 8am for iPad launch",
      "Author": "John Doe"
    }
    ...
  }
}

And let’s say you are interested in getting a small subset of data about the referenced stories for display with the base story. What you DON’T want to do is something like this:

var story = session.Load("stories/123");

foreach(var storyReference in story.RelatedStories)
{
    var otherStory = session.Load(storyReference.Id);
    // ... do something with otherStory ...
}

That will result in the following HTTP traffic back to Raven:

  1. Make a request for ‘story/123′
  2. Make a request for ‘story/456213′
  3. Make a request for ‘story/789654′
  4. Make a request for ‘story/555111′
  5. Make a request for ‘story/942342′
  6. …etc…

You’ll consume unnecessary bandwidth and incur the cost of individual HTTP requests. What you really want to do is have the client make a single HTTP request. Fortunately RavenDB allows you to do that with Includes. A RavenDB include says “Hey server, go get this for me, but before you give it back to me, gather up these other things and return them with the request too so I can deal with them in a moment”.

A few weeks back we had some code that was hitting the 30 requests per session limit. At first we couldn’t understand why, since we do a pretty good job of making sure we only make 1 or 2 requests via Includes. Upon further inspection, it turned out we had misunderstood something about the RavenDB client API.

What’s the problem?

If we have an index that produces projections, in which it produces a server side anonymous entity containing flattened “StoryReferenceIds”, like this (this is a contrived example):

public class Stories_ByReferencedStories : AbstractIndexCreationTask
{
    public class Result
    {
        public string Headline { get; set; }
        public DateTimeOffset? LastPublishedAtUtc { get; set; }
        public IEnumerable StoryReferenceIds { get; set; }
    }

    public Stories_ByReferencedStories()
    {
        this.Map = stories => from story in stories
                              select new
                              {
                                  Headline = story.Headline,
                                  LastPublishedAtUtc = story.LastPublishedAtUtc,
                                  StoryReferenceIds = story.StoryReferences.Select(x => x.Id),
                              };
    }
}

… Then we had previously done something like the following on our Lucene queries against it:

session.Advanced.LuceneQuery()
  .WhereStartsWith("Headline", text)
  .OrderBy("-LastPublishedAtUtc")
  .Include("StoryReferenceIds")

However, it turns out that last Include line doesn’t do anything at all. The Include() call actually operates on the entries identified by the index, NOT the projection. In other words, the stories produced from the query are what the Include() call actually operates against.

So, with that in mind, what we actually want is something like this:

.Include("StoryReferences,Id");

The syntax with the comma may look a little funny, but what it means is “For the StoryReferenceIds entities collection, Include the document identified by the Id property from each referenced document”. So if you had a story with 45 referenced stories in it, instead of making 46 requests back to Raven, you would make only 1 request. That’s much better.

Happy coding.

Performance on-demand; Giving your ops team runtime flexibility

Note: This was originally posted over on the Development @ MSNBC blog.

Performance On Demand

Pretend you are in an operations position, in which your job is to maintain the infrastructure that routes traffic and the servers that serve requests. Wouldn’t it then be nice, if you suddenly had a surge in traffic or a drop in available server hardware (be it expected or unexpected), you could alter the performance characteristics of your web applications?

This is a problem we’ve been tackling with our new set of web apps, and we think we’ve got a pretty good solution in place.

Operations Administration Panel for Runtime Configuration

For starters, we’ve created an administration web application for our operations folks, whose primary purpose is that of runtime configuration. Operations can control various aspects of our systems from this application, including:

  • Logging levels
  • Caching TTLs
  • Database masters/slaves and replication strategies
  • Application settings
  • Network locations for editorial assets
  • Logical service bus participants
  • Etc.

When any of these settings are updated, we send a message on the service bus informing subscribers of changes in the settings they care about. Let’s analyze the one we made reference to above, which will provide ops with a way to dial in performance on demand.

Output Caching

In the administration panel, we’ve provided a settings page where the output caching TTL and data caching TTL can be set for a given application. When this setting is updated, we publish a message on the service bus, which our front end rendering ASP.NET MVC application can subscribe to.

Creating a handler in the rendering application then is pretty easy. We listen for the settings type that corresponds to caching:

    
    public class CacheSettingsUpdater : SettingsChangedHandler
    {
        protected override bool ShouldHandle(string id)
        {
            return string.Equals(
                id,
                CacheSettingsData.StorageId,
                StringComparison.OrdinalIgnoreCase);
        }

        protected override void Update(CacheSettingsData settingsData)
        {
            CacheSettings.UpdateSettings(settingsData);
        }
    }

 

As you can see, the handler can then inform a settings class by calling its “UpdateSettings” method, who keeps a reference to the latest data.

    public static class CacheSettings
    {
        private static CacheSettingsData Data = new CacheSettingsData();

        public static int OutputCacheDurationSeconds
        {
            get
            {
                return
                    Data.CurrentAppCacheParameters
                        .OutputCacheDurationSeconds;
            }
        }

        internal static void UpdateSettings(CacheSettingsData data)
        {
            Data = data;
        }
    }

 

Leveraging it with OutputCacheAttribute

Now, in ASP.NET MVC, there is an action filter for output caching: OutputCacheAttribute. This attribute can be applied at the controller level, or at the individual action level. When an action is run the first time, the framework will cache the result, such that the next request won’t require processing again, and will be delivered from cache. The cached item will be delivered from cache until the TTL/Duration expires. The effect of this is that your application won’t be processing for every request, and will be able to therefor serve more requests.

The issue with connecting up our runtime configuration class from above (CacheSettings) to the OutputCacheAttribute, is that the settings for a filter can only be specified by constants, like so:

    
    [OutputCache(Duration = 10)]
    public ActionResult Index()

 

So, we need to instead create our own action filter, which inherits from OutputCacheAttribute, so we can control where it gets its values from. I’ve simplified this for brevity to just illustrate the Duration extensibility point.

    public class ConfiguredOutputCacheAttribute : OutputCacheAttribute
    {
        public new int Duration
        {
            get { return base.Duration; }
            set
            {
                throw new NotSupportedException(
                    "Duration cannot be set directly. " +
                    "Set from runtime config.");
            }
        }

        public ConfiguredOutputCacheAttribute()
        {
            base.Duration = CacheSettings.OutputCacheDurationSeconds;
        }

        public override void OnActionExecuting(
            ActionExecutingContext filterContext)
        {
            base.Duration = CacheSettings.OutputCacheDurationSeconds;
            base.OnActionExecuting(filterContext);
        }
    }

 

As you can see, when we hit OnActionExecuting, we check the CacheSettings class for the current output cache duration, and set it on the base OutputCacheAttribute class we inherited from. The effect of this, is that during day to day traffic, operations can control the cache TTL.

Then we just apply it where we want to cache:

    [ConfiguredOutputCache]
    public ActionResult Index()

 

Well, how did we do?

Let’s see what it looks like if I simulate light traffic load. The red line indicates request execution time.

The dramatic drop off occurred when I went into the operations administration panel and changed the TTL. The spikes every 10 seconds following the drop off are when the cache duration TTL expired, forcing the page to actually process again.

There are a number of things we can do to enhance the flexibility of this system. For example, we could specify groupings in the operations administration panel that correspond to cache policies, and then simply specify on each instance of our attribute which policy we’d like to use:

    [ConfiguredOutputCache(CachePolicy = "FooCachePolicy")]
    public ActionResult Index(string streamSlug)

 

We think this feature will be particularly valuable in situations where we need more performance on demand, and look forward to extending it to have more flexibility as needed.

Happy coding!

WinForms TreeView Control Performance Issue

I finished up a windows SFTP client I was writing this week and have been testing it with data. During the testing I encountered an interesting problem with one of the windows controls; It turns out the TreeView control which contains TreeNode objects is re-initialized on each node addition. The re-initialization of the control each time causes a massive performance hit, which ultimately locks up the UI thread.

The solution was to hide the control, populate the nodes, and then show it, like so:

public FormConstructor()
{
    TreeView myTreeView = new TreeView();
    myTreeView.Fill();
}

private void Fill()
{
    myTreeView.Hide();
    myTreeView.Nodes = GetNodes();
    myTreeView.Show();
}