Tuesday, June 6, 2006

BizTalk 2006: Parallel Shape and Threads

Another question I never before had the time to test has to do with the Parallel Shape. The product documentation states that this shape should be used to handle specific message exchange patterns, namely where several messages are expected, but the order is not previously specified (like in a parallel convoy).

It is generally assumed, however, that the execution is multi-threaded. The excellent post by Scott Colestock about "parallel actions, exceptions, and timeouts..." also seems to assume this, while exploring what happens in parallel shapes, when he describes a work-around to the compile-time validation that doesn't allow the use of a .Net object instance in more than one un-synchronized branch of the parallel shape.

To test this situation, I did the most simple test possible: I created a simple 3 branch parallel, with the following contents in each of the branches:

- An expression shape writing "start" followed by the ThreadId (Thread.CurrentThread.ManagedThreadId) to the Debug
- A delay shape
- An expression shape writing "end" followed by the ThreadId to the Debug

What I found out when I tested it, was that all the branches print out the same thread id. Plus, they are executed left to right.

Apparently, there is a scheduler that executes one shape (segment?) at a time, but all in the same thread. It is more or less obvious that BizTalk can't just spawn more threads at will (and there is a BizTalk MaxWorkerThreads registry setting which defaults to 25), and distributing work for the existing threads would probably be too slow.

I did some additional tests, out of curiosity. I created a parallel shape with 6 branches, each containing 3 expression shapes just printing out information do debug, as shown in the following image:

The result was that the branches where fully executed left to right, and the output in the debug out was:

1 - 11 - 21 - 2 - 12 - 22 -3 - 13 - 23 - etc.

Each of the branches ("tasks") seems to be scheduled together.
After this, I added delay shapes to the branches, as follows:

In this case, the scheduler did something different. Apparently, it schedules all the Expressions in a sequence together, but the Delays are placed at the end. This is the (deterministic) output:

1 - 2 - 3 - 4 - 14 - 5 - 15 - 6 - 16 - 11 - 21 - 12 - 22 - 13 - 23 - 24 - 25 - 26

A lot of things could be happening here. Maybe it is related to MessageBox operations, or maybe it's by shape.
I used Lutz' Reflector to take a quick look at BizTalk's DLL's, and found classes named RunSchedule and SegmentScheduler, which seem to handle some of this behaviour, but I don't really think it's a good idea to count on this, as it might change in future versions.

So, takeaways:

- the parallel shape is not multi-threaded, although it looks like it, and should be used only to handle specific messaging patterns;

- the execution order of the branches is done left-to-right. I don't recommend you base your orchestration design on this information, but it might be useful in some scenarios.


No comments:

Post a Comment