Tuning Contracts for Performance

I have a service contract with a few operations that take large inputs and do a lot of processing. If I configure the service quotas with small values to prevent too many of the expensive operations from happening at once, then the overall throughput is very bad. If I configure the service quotas with large values, then the expensive operations could be called many times and the server will run out of resources.

I've left the question off of this one because I'm not actually going to talk about this problem. Instead, the description was a good excuse to talk about the design of service contracts.

Long-time programmers will recognize the discussion on chatty versus chunky interface design. Chatty interfaces break operations up into small units of work. It takes a lot of chatty method calls to get something done, but because everything is nicely componentized, it's possible to reassemble the pieces in ways that the original designer didn't think of. Chunky interfaces map large, user-scale operations to a single method call. It only takes a few chunky method calls to get something done, but the operations chosen for the interface are really all you can do.

In the non-distributed application world, it often doesn't matter whether your interfaces are chatty or chunky. There were some exceptions. For example, operating system calls have a kernel-mode transition cost so it's beneficial to get a lot of work done with a single call. Every iteration between kernel and user mode results in paying the transition cost. For distributed applications, there is a similar large transition cost called the network. Each trip back to the network introduces a lot of latency relative to the typical computational costs of an operation. COM programming really threw the distinction in your face because it was suddenly a lot harder to predict whether a given method call would incur an expensive transition. You had to program defensively and use lots of chunky interfaces to avoid unpredictable costs at runtime.

Typically, calls between application tiers have to be done through chunky interfaces. Calls within an application tier can afford to be chattier. HTTP applications in particular tend to be extremely chunky. Often, requesting a resource will return every single piece of information about that resource and you don't have to make any trips to the server again. This trend has swung back around recently but mostly because the resources are too large to transmit at once (maps of the world, my mail box).

Back to the original topic, the situation sounds a lot like an interface that has mixed together chatty and chunky operations. It has operations with greatly differing granularity. Such interfaces usually end up with the worst of both worlds in terms of performance and usability. The performance characteristics of the interface are going to be bad unless the client and service are located nearby. However, the interface isn't giving you the flexibility you'd have for a typical local service. This scenario would be a good candidate to look at whether someone has thrown multiple service contracts behind one interface without thinking about the overall design.

Next time: Channels Illustrated

Comments

  • Anonymous
    February 23, 2007
    Let's shift gears for a bit and talk about transport channels now as opposed to protocol channels. Everything