Notes on (extreme) Performance requirements for CAB

Object Builder, the Dependency Injection framework that provides the underlying infrastructure for all of the "CAB Magic", uses reflection.

Objects in CAB are never "newed". They are always created through a factory that inspects the metadata in a type and processes it before returning an instance. This allows CAB to wire events, inject properties, inject parameters in constructors, etc. like in the following code snippet:

[InjectionConstructor]
public Module([ServiceDependency] WorkItem rootWorkItem)
{
_rootWorkItem = rootWorkItem;
}

Object Builder is extensible, meaning that you can insert your own strategies to analyze other metadata beyond those shipped out of the box.

Examples of these extensions are shown in the SCSF Reference Implementation (see BankBranchWorkbench):

[Action(ActionNames.ShowCreditCardAccountViewAction)]
public void ShowCreditCardAccountViewAction(object caller, object target)

Action is a newly defined attribute that is added to ObjectBuilder:

builder.Strategies.AddNew<ActionStrategy>(BuilderStage.Initialization);

Another example is shown in the CAB Hands-On-Labs.

By default all this metadata analysis happens at runtime, meaning that each time an object is created through Object Builder, the type will be inspected, the strategies defined in Object Builder will be executed and the instance will be returned; and this of course provides a great deal of flexibility but also takes time. The CAB Object Builder strategies use public reflection which is significantly faster than private reflection, but there's an inevitable overhead.

In almost all cases (the vast majority from my experience so far) the performance of this implementation is enough, but there are always exceptions.

For example, when we ported CAB into the Compact Framework for mobile development, performance was a key requirement. Mobile devices normally don't have the same memory and CPU power desktops have and reflection was a big tax.

The solution was to create a tool (2 actually: CABGen and OBGen) that "compiles" the dependencies and dynamically generates an assembly with all the required relationships. Enabling these tools required minor changes in CAB & Object Builder (a code diff between the 2 versions will reveal those).

The end result is that the code runs faster because everything is resolved upfront, the price you pay is the flexibility of loading modules on the fly. However, the system works in hybrid modes too, meaning that you can mix modules that have been "CAB and OBgen'ed" with standard ones. So you still have the choice of only optimizing those that are critical for your performance requirements.

CABGen and OBGen are included in the Mobile Client Software Factory (also in source code), and although they were originally meant for the Compact Framework of CAB, nothing really prevents you to use it on the full framework, although we haven't tested it.

As I said, we haven't really tested this, but if you have a performance stretch scenario, it might be something worth looking at, and we'd love to hear what the results were.