WF4 Performance

I have been playing around with the idea of modeling business rules as a set of small workflows (Flowcharts in WF4).  In the application, this would result in small workflows being called a large number of times.  I decided to investigate the performance overhead of invoking a workflow in WF4, the workflow technology in .NET 4.  Since I am using Visual Studio 2010 Ultimate Beta 2, this also seemed like a good opportunity to evaluate the performance profiler included in this edition of VS 2010.

For this test, I implemented a simple application that performs a calculation 10,000 times, then outputs that value to the console.  As a reference, I first implemented this in simple C# code as follows:

Code1

To determine the performance, I used the Instrumentation Profiler.  The simple C# code took approximately 800 milliseconds to execute.  Most of the time was spent writing to the console.

Profile1

 

Next, I implemented the calculation functionality in a simple flowchart workflow.  My flowchart has a single InArgument y, and an OutArgument x.

Workflow

In the Main method for my application, I modified the loop to call the simple workflow to perform the calculation.

Code2

The performance from this implementation seems a little disappointing at first.  We went from a total execution time of less than 1 second to approximately over 36 seconds.

Profile2

But if we really think about what’s happening here, this performance isn’t that bad.  We know that it takes about 1 second to perform the calculations and output the results.  That means that the remaining 35 seconds was spent on “workflow” related processing.  In that 35 seconds, we were able to create and execute 10,000 workflows.  Clearly this is not fast enough to accomplish what I was originally trying to do.

After digging through the profiler, I noticed that the application seemed to be spending a large percentage of the time initializing the workflow.  This led me to investigate if we could just create the workflow object one time and reuse it whenever we invoke that workflow.  It turns out that we can, and the results are dramatic.

 

The code is as follows:

Code4

Notice that I am now passing the input to the workflow using a Dictionary<string,object>.  I’m not sure why, but when I tried setting the input using workflow.y = i, the workflow would always use the first value that was assigned to y.  In this case, my output was always 0 because the workflow was always using y=0.  Passing the workflow inputs as a Dictionary seems to work around this problem.

Using this method of invoking the workflow, the total execution time was just over 1.15 seconds.

Profile4

Now this looks much better.  By caching the instance of the workflow object, we are able to significantly reduce the overhead of executing a workflow.  In this case, we spent just over 1/2 the time calling Console.WriteLine().  That means we were able to execute 10,000 workflows in the remaining .65 seconds.  Considering the flexibility this can provide in an application, I would consider this overhead to be minimal.  In most real-world applications, the difference in performance will not be noticeable to the end user.

When running the application in release mode with no profiler attached, it took 14.48 seconds to execute the workflow 1,000,000 times.  That works out to 69,039 workflows per second!

I found the performance profiler in VS 2010 to be useful.  While it is much better than no profiler at all, I was a little disappointed.  There are much better profilers on the market today.

Print | posted on Monday, October 26, 2009 2:46 AM

Feedback

# re: WF4 Performance

left by James Bradt at 11/18/2009 11:21 PM Gravatar
Interesting post.

I dived into WF when WF3 first came out and was under-impressed with what it really provided. I will need to take another look at WF4.

One question that I have. In setting up your code to use the same instance of the workflow, aren't you really creating just a glorified function call, or is the simple example not expressing the benefits WF4 offers.

Not complaining, just trying to grok what WF4 brings to the table.

James

# re: WF4 Performance

left by David Paquette at 11/25/2009 3:25 PM Gravatar
Thanks for the feedback James.

In a sense, the small workflow in my example is really no different than a simple function call. I was just trying to assess the overhead of executing workflows, so I wanted to keep the workflows small to isolate the overhead of the workflow runtime.

Where this becomes useful is that you can load workflow definitions at runtime from a XAML file. The idea I am exploring is to use the workflows to implement business rules (in this case formulas, or some logic to select different formulas based on some criteria) that are different for each client. Since it is very easy to host the workflow designer in a WPF application, we can have a team of client implementation specialists that customizes the client business rules without needing to come back to the development team to make changes. We can store the workflows in a file or in the database, and hopefully eliminate the need to create different versions of compiled assemblies for each client. This could also be accomplished using a scripting language of some sort, but I like the idea of using workflows (in particular the Flowchart Workflow) because it makes it really easy to review the customizations with the client. After all, everyone can understand a flow chart.

There are some big differences in this respect between WF3 and WF4:
-Flow chart workflows (much more natural than State Machine or Sequential workflows)
-It's now REALLY easy to host the workflow designer in a WPF application (this was difficult in WF3)
-Performance... The overhead of executing a workflow in WF3 limited executions to approximately 10,500 per second. A similar test with WF4 on my computer resulted in 208,000 workflow executions per second.
-Ease of use. The complexities of the runtime are better abstracted in WF4 than they were in WF3.

# re: WF4 Performance

left by Bhaskar Sharma at 4/20/2010 6:13 PM Gravatar
Hi David,

I got attracted to this blog by reading to your comment"Performance... The overhead of executing a workflow in WF3 limited executions to approximately 10,500 per second. A similar test with WF4 on my computer resulted in 208,000 workflow executions per second".

My problem is as follows:-

I am creating one workflow instance for each of my order in an order management system.

Need to know as what is a decent limits of workflow instances which can be created on a server.While suggesting, also share your server configuration. I am thinking of about 90000 workflow instances hosted as a service in IIS.

These workflow instances will work and die out with persistance only incase of system failure.

--------------------------------------------------------
Do you have performance figures on how many instances of workflow can be created at a time when the workflow is hosted as a service in IIS using AppFabric.

Also if you could share data about how much time it is going to take for a workflow based on wf4 to exceute which has one policy activity with externalised 10000 rules.

Please share whatever performance data you have along with configuration of the server for which the data is relevant.

Cheers

Bhaskar

# re: WF4 Performance

left by Mike Hanrahan at 9/16/2011 10:36 AM Gravatar
Just a note on James' comment above. The code is not really "just" invoking a method, as the effect of the code is to cache the activity definition (not the instance). So therefore that loop could be run in multiple threads and it would be safe. A more detailed explaination of this is given here:

http://blogs.msdn.com/b/endpoint/archive/2011/02/12/wf4-performance-tip-cache-activities.aspx
Post A Comment
Title:
Name:
Email:
Comment:
Verification: