Saturday, September 8, 2007

K2.net Process Sizing and Performance Best Practices

This is the third of a series of best practices I considered when starting a new workflow. Note that manye of these Best Practices are K2.net 2003 specific. They will be re-evaluated with the new BlackPearl release.

1) Process Sizing Considerations
1.1) Use the K2.net Estimator When Designing a Process
K2.net has some spreadsheets that will help you understand how much database storage will be required for process instances. Specifically things that must be considered are:
  • What are the number of process and activity level fields, the data types and size?
  • If audit trails are used for data fields and how many times can the data be updated?
  • How many destination users will be assigned for each activity?

1.2) Understand Process and Activity Level Fields
From a general programming position process level fields should be though of as global fields defined at a top of a class while activity level fields are local fields to a method. Process and Activity level fields are not limited to just using primitive data types. Custom objects can be used if they are serialized into a data field. Important Note: Activity level fields can have multiple instances if many slots have been created. A unique activity instance will always be created for an activity slot. This will result in the data value being created and stored for each individual activity instance. Use activity data fields when you need to pass data between activities and events or when each destination user requires their own unique value. This will have to be balanced with having too many process level fields that could be similar to one another.

1.3) Number of Destination Users
“A high number of destination users for activities with client events can cause severe performance issues on the K2.net Server. This comes into play when a large number of users access the Worklist simultaneously (or calls from the K2.netROM API to user worklists) and a high volume of data has to be returned to the K2.net Server from the database. In conjunction with the "Data on Demand" it can be alleviated. With the arrival of K2.net 2003 Service Pack 3 (SP3), there is now an alternative way to handle this. SP3 introduced the option to create a single activity instance for an activity when a Destination Queue is used as the activity destination. The new feature creates a single Activity Instance for the Destination Queue. K2.net Server will create only one activity instance which is visible to all users within the Destination Queue. When one of the users opens the item it will no longer be visible in the other user's tasks lists but will have been assigned to the user who opened it. The implications however are that only one slot is available. The advantage is that only one activity instance is created in the database significantly reducing database overhead as well.” [1]

1.4) Keep Audit Trail
For data fields checking the keep audit trail checkbox will save every value every time the data field changes. If the data field is big (like xml) this will fill up the K2 database every quickly.

1.5) Data on Demand is Lazy Loading
“Data on Demand is a feature which minimizes the load placed on server resources when a large volume of data from the K2.net database is requested by the K2.net server and worklist. By default, when a process instance is loaded by the K2.net server all the data fields are loaded, regardless of whether they are needed at that time or not. This creates a resource drain as not all the data fields are required at the same time to perform a step within the process. However, since all the data has been loaded, the system must manage the data contained within memory even though only a small portion of the data may be affected at that time. To make use of the "Data on Demand" feature, it must be enabled on a field-by-field basis from within K2.net Studio. When "Data on Demand" is active, only the fields required at that time will be returned by the server when the request for data is sent through to the server. In other words, the data must be "demanded" as an explicit call for it to be loaded into server memory and passed to the client application. “ [1]

2) Externalize Large Data Requests for Open Worklist Items
When using the K2.net ROM be careful to not make unfiltered requests for worklist items to the K2.net server as this can be resource intensive. For the OpenWorklist method create a WorklistCritera object with a filter.

“For large volume scenarios where process/activity data fields need to be utilized to filter or sort a worklist, it is recommended that the specific data fields required in the search be stored in a database table external to K2.net, in addition to the native K2.net data field storage. The external table should contain a field for the K2.net "Process Instance ID" if querying process datafields or a "Process Instance ID" and an "Event Instance ID" if tracking activity level data. A query can then be constructed that joins the external table data with the internal K2.net _Worklist table, or more appropriately a read- only view on the _Worklist table (see below for a sample view). Please note the read-only view of the worklist table is the recommended interface to querying the K2.net Worklist. This query should then become the basis for the custom worklist application, ensuring that the fields necessary to process a worklist item in an application (generally the platform, serial number and URL for the event which is stored in the "Data" field), are accessible.” [1]

3) Server Events in Multi-Destination Activities
Be careful to not place a server event into an activity that has multiple slots for destination users unless the code in the event must be executed for each destination user. This can become a bottleneck by flooding external applications with hundreds of simultaneous calls or it could even introduce errors like insert duplicate records into a database.

4) Use Destination Queues for AD Groups
When Active Directory (AD) Groups are used as destination users for activities, destination queues should be used. K2.net will poll active directory to check for changes in the group membership. This will allow K2.net to remove a destination user whom has been removed from the group creating more security around who can access the K2.net process instance. As well if a user is added a new activity instance for this destination user will be created. The rate in which K2.net will poll active directory is configurable. [1]

5) Understand Exception Handling
Exceptions will be raised in the following order from within K2.net: [1]

  • Code Level Try-Catch Block
  • Event Exceptions Code Block
  • Activity Exceptions Code Block
  • Process Exceptions Code Block

Exceptions that are handled in a try/catch block will not be logged to the K2.net database. It is recommended that the error may need to be handled locally but a custom error can be thrown which will continue up the stack and be caught at the Process Level. At that location it can be determined if the error should be result in stopping the process instance or continue letting it move along. This is a good location to do global logging of exceptions.

Reference - K2.net 2003 Process Design best practices - http://kb.K2.networkflow.com/articles/kb000161.aspx

No comments: