Workflow Foundation performance

From my week in Redmond I still had notes on the performance session of WF. Instead of throwing them away, I thought I would share them. The session follows the technical artical ‘Performance Characteristics of Windows Workflow Foundation‘ for the larger parts. This means that the points on performance below are complementary to the article. For more background and nice graphs, read the article.

1. Persistence service

Recommendation: Consider when to persist.

Persistence happens when:

  • the WorkflowRuntime instance is stopped,
  • a custom activity marked with PersistOnClose=true closes or
  • when UnloadOnIdle=true for the persistence provider.

An instance is handed to the persistence provider, which uses the binary formatter to serialize it, that then gets passed to a GZipStream to compress the binary stream. For unloading an instance first gets persisted, then unloaded from memory. Also, persistence occurs at the end of a TransactionScope (also marked as PersistOnClose).

2. Activity Execution Context cloning

Recommendation: Write custom activities instead of cloning where high performance is required.

Issue: Workflow runtime uses AEC to maintain activity instance state and to run compensation logic.

3. Transactions in WF Activities

Recommendation: Use IPendingWork for simple workflow database transactions. Check out the WorkflowCommitWorkBatch in the SDK samples for more information. The workflow instance initial state is copied before the transaction in case of rollback. The use of System.Transaction means MSDTC occurs only if necessary.

4. Nesting compensation

Recommendation: Avoid nesting of compensating activities where performance is desired.

Issue: Because compensation retains a copy of the workflow instance state, nested compensation causes the state to multiply.

5. Workflow tracking service

Recommendation: Review your tracking profile for the required number of tracking events. Track only the events you really need.

Issue: Database operations caused by tracking affect performance.

The number of track points can be modified at runtime by editing the tracking profile. When batching is used the load is about 5% CPU usage for the SQL Server. Turning it off will make SQL Server CPU usage go up to 75%. The tracking service database can be partitioned into multiple tables. See Moustafa‘s blog. There are stored procedures you can run yourself and you can turn on automatic partitioning.

6. Workflow activity complexity

Recommendation: Optimize factors affecting state

Issue: State size affects persistence time.

Factors: Numbers of fields on the class. Properties and dependency properties being accessed. Serives being consumed. Workflow queues being used. Activity execution overhead.

7. Workflow activation cost

Recommendation: Consider startup time.

Issue: First time tree creation and validation.

Activation occurs when the workflow host calls WorkflowRuntime.CreateWorkflow. This startup time increases with the number of activities.

8. ExternalDataExchange and parameters

Recommendation: Consider serialized event data size

Issue: ExternalDataExchange and parameters are serialized through WF internal queues. Giant chunks of data will take more time to get serialized.

9. Workflow declarative rules and policy

Recommendation: Consider performance of rules

Issue: Declarative rules take longer than code conditions

Using the RuleEngine class can improve performance over the Policy activity. Rule priorities and chaining have a big effect on performance.

10. Workflow instance dynamic update

Recommendation: Consider performance

Issue: This mechanism is slow.

What it does is:

  • instance is suspended
  • clone the instance
  • edit the clone
  • validate changes (all validators are called on the new tree)
  • apply changes

This has impact on tracking, tracing and persistence.

11. Workflow dependency properties

Recommendation: Avoid when regular properties can be used.

Issue: Dependency properties are slower than regular .NET properties. There’s just a few more .NET instructions in play.

12. Workflow state machine root activity

Recommendation: avoid deeply nested states.

Issue: state transitions in and out of deeply nested states are expensive due to tree navigation and AEC cloning.

13. Workflow runtime startup cost

Recommendation: only use one WorkflowRuntime per AppDomain

Issue: Instantiating WorkflowRuntime and calling StartRuntime is expensive.

Why? Retrieves runtime config parameters. Starts default and custom services. These are significant performance configuration settings:

  • Runtime: EnablePerformanceCounters (default true) and ValidateOnCreate (defaults to true)
  • TransactionService: EnableRetries
  • SchedulerService: MaxSimultaneousWorkflows
  • PersistenceService: EnableRetries, LoadIntervalSeconds, OwnershipTimeoutSeconds
  • TrackingService: EnableRetries, IsTransactional (has nothing to do with real transactions, but will batch up tracking database writes), UseDefaultProfile (default profile will track all workflow level events and activity level events), PartitionOnCompletion
  • DisableWorkflowDebugging
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s