Obscure exception handling facts

July 28, 2009 at 08:22 PM | categories: Uncategorized | View Comments

(The second in what seems to be a day of obscure .NET facts)

While looking at some C++/CLI code in Reflector today at work, we encountered the try ... fault construct.

What's a fault block?

It's like a finally block, but it's only entered in the event of an exception.

So it's like a catch block, then?

Not exactly:

  • fault blocks don't have filters like catch blocks do
  • At the end of a fault block the exception is implicitly rethrown

Supposedly the benefit of a fault block is performance: that throw; statement at the end of a catch block has the same overhead as any other throw statement, whereas finally and fault blocks incur no runtime overhead. The stack is not unwound when a fault block is entered: fault blocks won't appear in the exception stack trace.

Where do fault blocks show up?

In the code the C++/CLI compiler emits in order to make sure that local variables have their destructors called in the event of an exception.

Read and Post Comments

Obscure IEnumerator facts

July 28, 2009 at 07:06 PM | categories: Uncategorized | View Comments

Daniel Fortunov wrote about an obscure use of duck typing in the C# spec for enumerators:

Although it is common to implement [IEnumerable and IEnumerator] when creating an enumerable class, if you were to drop the interfaces but leave the implementation, your class would still be enumerable by foreach. Voila! Duck-typing!

You can take advantage of this fact for a couple of performance tricks, as demonstrated by many of the standard collection classes in the base class library:

  • Declare your IEnumerator<T> implementation as a struct, not a class. This saves you a heap allocation when MoveNext is called.
  • Define a Enumerator<T> GetEnumerator() method on your collection class
  • Note that you're returning your own struct, not IEnumerable<T>; this avoids a boxing operation. You'll still need to explicitly implement IEnumerator<T> GetEnumerator(), for people who only have an IEnumerable<T> reference to your collection. These performance tricks don't apply when you're making calls through this interface.

When somebody uses foreach over your collection, the compiler sees a series of MoveNext calls and accesses to the Current property, and it emits code to call these efficiently on your struct.

What's more, the code in your struct's methods is a candidate for inlining by the JIT compiler. The segment of the MoveNext method of System.Collections.Generic.List<T>+Enumerator that can throw an exception is split into its own method, apparently for this reason.

I don't claim any kind of definite performance benefits from using these techniques, but it does look like the language designers put some thought into making it possible to use foreach without incurring any overhead compared to some less elegant method.

Read and Post Comments

dollop, a Python Lisp interpreter

June 15, 2009 at 09:00 AM | categories: Uncategorized | View Comments

Via Hacker News, Hans Nowak's proof of concept:

The proof-of-concept implementation that uses this concept is called dollop and is available at github. (Requires Python 3.0.) The name is because it's only a "dollop of Lisp" (or rather, Scheme); it only supports a few special forms (begin, define, if, lambda), and a few functions for example programs (+, -, *, =, list). It cuts corners in other ways as well, as my goal was to get a working proof-of-concept out, not to write a complete Scheme interpreter.

Hans explains how he avoids stack overflow, due to tail recursion, by replacing the machine call stack with an explicit stack data structure in his interpreter. A tail call replaces the token at the end of this stack, instead of pushing a new one.

This is a technique you can apply in an interpreter based around an eval-apply cycle: with a full compiler, the principle is the same, but you have to detect tail calls in advance and generate the correct bytecode -- say, a .NET tail.call instruction or an x86 jmp opcode.

Read and Post Comments

Vague class names: "Manager" and "Helper"

June 06, 2009 at 06:48 PM | categories: Uncategorized | View Comments

From journal.stuffwithstuff.com:

Do not use "Manager" or "Helper" or other null words in a type name.

If you need to add "Manager" of "Helper" to a type name, the type is either poorly named or poorly designed. Likely the latter.

I always agreed with this: names like ConnectionManager and XmlHelper are too vague to be useful. But I never came up with a retort as pithy as this one of Robert Nystrom's:

Types should manage and help themselves.
Read and Post Comments

Moving a Perforce project to GitHub

June 02, 2009 at 08:41 PM | categories: Uncategorized | View Comments

I keep all of my home projects in a local Perforce instance. I wanted to put my Lisp compiler code onto GitHub; since I'm not paying for a Perforce licence, I'm limited to a single user.

The GitHub user account and repository setup process was pretty straightforward, until it came to adding files. I haven't been able to find a single set of instructions for this, but I pieced it together thanks to Stack Overflow:

  1. You will need the git-p4 Python script from here: http://repo.or.cz/w/git.git?a=tree;f=contrib/fast-import;hb=HEAD
  2. From the some empty directory -- not the one that contains the Perforce project -- run the following command to import the entire Perforce version history:
    python git-p4 clone --destination=. //depot/path/to/project/...@all
  3. You now have a brand new local git repository that contains a clone of the project from Perforce. You need to push it to GitHub:
    git remote add origin git@github.com:username/repository.git
    git push origin master
  4. To push subsequent Perforce changes to GitHub:
    git-p4 sync
    git push origin master

Edit: I almost forgot to include the URL of the compiler source

Edit 2: Turns out you mustn't run git commands from a Perforce local directory: as always, Perforce doesn't like it if something else (in this case git) interferes with its local files.

Read and Post Comments

« Previous Page -- Next Page »