Pithy Perf Patterns

Maoni Stephens, Perf PM on the CLR team sent me some key “patterns”... You will see I have not expanded on any of them, I am sure we can talk Rico into blogging on any of these at length if we ask nicely....

  1. avoid finalizers; use the Dispose pattern.
  2. avoid the urge of writing your own memory allocator (which is a common thing to do in native world)
  3. avoid having the object pattern of lots of midlife-ed objects
  4. use chunky instead of chatty interfaces in interop, and avoid marshaling complex types if you can
  5. use the ThreadPool instead of managing your own threads
  6. use caches to avoid doing the same things again and again (of course this applies to native world as well but we've seen so many cases where people do this - like fusion parsing the same manifest again and again and etc)
  7. don't throw exceptions when you don't have to - throwing exceptions is expensive in managed world
  8. know the hidden cost (examples include using foreach; when boxing happens; when reflection is involved)
  9. don't use XML without thinking! (again, also applies to native - DOM is slow too but I guess the managed xml classes are so easy to use and we've seen so many cases where people abuse using xml).
  10. And this important thing applies to all: "pay for play" - only do things when you need to.

UPDATE: Maoni pointed out to me that I left off her most important rule... "With perf there are rarely absolutely rules so we need to tell people why they want (or not want) to do these so they can decide for themselves"  It is a good rule indeed. 

Also, notice you can always find good perf info on Rico's blog.

Comments (20)

  1. Brad Wilson says:

    I think I’d like an expansion on #9. It’s hard for me to know whether Microsoft thinks I’m thinking or not. 🙂

    We use XML for configuration files. Why? Because the XML parser is written. Writing parsers for text files is a lame way to spend your day.

  2. Rico Mariani says:

    It’s funny how things work out. I suspect the email that Maoni sent Brad was distilled from the slides she and I made for a talk we gave together a few weeks ago which was in turn distilled from recent entries on my blog so I’ve already actually commented on most of those.

    See http://weblogs.asp.net/ricom/

    Now the particulars of XML and the XML DOM is that I often find folks picking up the (sledgehammer of an) XML parser to parse, at great expense, a comparatively small amount of data. Often precisely because it is so easy to do just that.

    This isn’t always the wrong thing to do of course; We each have to make choices as to where to invest our time, both processing time and development time. But, and this is especially true for simple configuration data, there are comparatively few benefits to using XML and the cost could be higher than you want to bear. So that advice makes our greatest hits list because it’s a common pitfall. And not The Pit of Success.

    So #9 simply boils down to make an informed decision. Doing anything by reflex is a recipe for Big Trubble.

  3. David Levine says:

    >1. avoid finalizers; use the Dispose pattern

    I’d expand this a bit. If an object implements the Dispose interface then it should also implement a Finalizer as a backstop, and then I would treat it as at least a warning (log it), and possibly an error (throw exception), if the finalizer ever ran. The idea is that the Dispose is a contract that the object requires the client to honor.

    The goal is to catch violations during the debug phase before it ever ships to customers.

  4. Brad Abrams says:

    Thanks David — I generally agree with your post, but I might not go as far as you suggest. The Dispose pattern is mostly a perf optimization… That is for correctness the finalizer running is not a bad thing so I would not throw and exception from the finalizer. The Finalizer is a great backup plan.

    We know from experince with COM that developers have trouble explicily freeing instances, I don’t want to go back to that world.. We should continue to take advantage of the GC here.

  5. David Levine says:

    Thanks Brad. Most of the subtle/weird problems we’ve run are at the intersection of .net and COM, and it’s caused us to adopt a paranoid style with releasing resources, hence the rule I suggested. I completely agree that using the GC to free resources is far superior then relying on developer hygiene. But…

    Currently we really can’t go very far in .net before we have to interact with the underlying system objects (files, windows, networks, COM, threads, etc.) with open/use/close semantics. If all resources were managed we probably wouldn’t need Dipose/Finalizers at all – try-finally blocks would handle most cleanup requirements. Until we reach that happy day we still need to use discipline. In our case we plan to surround the throw statements with #if DEBUG so that shipping code wont blow chow.

  6. josh says:

    but isn’t the performance optimization of the suggested use of the dispose pattern over the use of finalizers that your objects don’t have to be promoted in the GC so that at some time in the future the finalizer thread can come around and finalize them?

    by putting in a "backup" finalizer it seems that you completly negate that optimization…

  7. David Levine says:

    The Dispose method calls GC.SuppressFinalize(this) so that the finalizer only gets called if the Dispose method is never invoked, so we still get our perf improvement if the object is used correctly.

  8. Claude Ballew says:

    I would have before a recent project completely agreed with you on ThreadPools instead of managing your own threads. In the Framework 1.0.3705 ( I have not tried the same with 1.1 or higher ) some interesting things happened inside of a Windows Service I had written.

    The threads were in a thread pool using the Threading timer. The first thing I noticed was my first thread created was always favored. The other threads did receive clock cycles, but not as consistently as the first thread did.

    The other thing that happened to me was a mis behaving DataProvider written by a non-Microsoft vendor who shall remain nameless 🙂 threw an unknown exception. This in itself was not a problem, but my next call into that provider went to never, never land. Again no problem except that at that point all my other threads stopped receiving clock cycles, no ticks ever fired again on any of the threads, but my primary thread and the service were still live.

    I had much code devoted to handling awry thread, but that code never got hit because my app was unaware of the issue.

    Now I have my own threads, spawned by me and a health thread to make sure all my threads are behaving and communicating in a timely matter and no more issues. I still believe in threadpools and I will probably try again in 1.1 to see if the same behavior is exhibited, but for my production code, I’ll keep my approach until threadpools win me back.

  9. eriksalt says:

    I would like to see some more information on the threadpool requirement. Is the performance recomendation only because the threads are ‘pooled’, or is this a case like memory management where rolling your own tends to make things up? I have heard allot of talk refering to the threadpool as having performance limitations, and have seen developers in the field rolling their own threadpools. I think a more thorough treatment of this topic would enlighten many people.

  10. Louis Parks says:

    I must say it’s a bit odd to hear someone suggest that using XML for a relatively small amount of data is not recommended. Visual Studio defaults all app config files to an XML format, all web app config files to an XML format, the VS project files to an XML format, etc. Often, these XML files hold very little data. Perhaps someone can clarify this for me?

  11. Codezen says:

    Regarding Louis Parks comment…..

    It makes lot of sense to have config info in the XML file like app.config. The config file contains parameters that define the way an application would behave. E.g. a windows service that polls a resource at a configurable interval. If you need to to quicken up the polling, just change the config key, restart the service and thats it……..now ain’t that easy.

    As far as perf is concerned….it is not that perf intensive. When an app domain loads, the config params are loaded in an in-memory collection by a section handler (parsing is done for that config section during this process) e.g. the keys in the appSettings section are handled by NameValueFileSectionHandler. So when you access these values, they are fetched from the in-memory collection…….no parsing here…so no perf issue.

    Using the XML for data storage should be considered judiciously. Nothing like a good ol’ RDBMS to store/manipulate/read the data. As far as data transmission is concerned XML can be a good idea e.g. if there is a case of transmission of data between two heterogeneous systems.

    All and all Maoni’s pt. 9 hits the nail on the head.

Skip to main content