The new LegacyOptimized data processed engine was introduced in version 17.1. In this version, only common data processing operations were supported and it was necessary to enable the engine manually by setting the PivotGrid.OptionsData.DataProcessingEngine property to LegacyOptimized. In newer control versions, more features were supported and overall performance was improved further as described in the T505508: PivotGrid performance improvements from version 17.1 to version 19.1 (client data processing mode) article. Starting with version 18.1 the LegacyOptimized data processing engine is enabled by default. However, if PivotGrid uses a functionality, which is not supported by the LegacyOptimized mode, the data engine automatically switches back to the Legacy mode.
This article describes differences between Legacy and LegacyOptimized data processing engines, and issues that you may face if the LegacyOptimized engine is enabled in your project after an upgrade.
The Legacy data processing engine is not the best choice for processing big amounts of data. Previously, we suggested selecting the Server Mode or using an OLAP data source for a data source with more than 100000 data rows. The LegacyOptimized engine demonstrates much better performance. Thus if you display data from a large data source, the LegacyOptimized data engine may be a preferable solution. However, take note of the following differences:
1. Data Sorting and Grouping
The Legacy engine aggregates data after sorting is performed at the data source level. The LegacyOptimized engine sorts the aggregated data. A different workflow means that the CustomFieldSort event occurs in different situations. The legacy engine raises the CustomFieldSort event more often to compare different data rows. The LegacyOptimized engine raises the event to compare the resulting data groups.
However, you can still use the ListSourceRowIndex property and the GetListSourceColumnValue function. They return data from the first data row included in the processed group. This functionality is suitable for most field sorting scenarios. If it is not sufficient, feel free to contact us, and we will do our best to find a solution.
The Pivot Grid also calls the CustomGroupInterval event for each data source row in the Legacy engine. In the LegacyOptimized engine, it calls this event only for unique field values.
2. The LegacyOptimized engine has strict requirements for custom types
To display custom types in the grid, you need to provide them with a common group and sort functionality. That is, implement the IComparable interface and override a custom object’s Equals and GetHashCode methods. Otherwise, the grid cannot group and sort custom objects. The Legacy engine has the same requirement for custom objects. However, if a custom object does not meet the group and sort requirement, the Legacy engine still tries to process a value (e.g. by converting to string). Since conversion may cause incorrect results and requires much more resources, the LegacyOptimized engine does not attempt to process a custom object that does not meet the group and sort requirement.
3. Multithread data processing
The LegacyOptimized engine supports multithread data processing. It affects only internal control behavior and should not affect your application logic in any way. Make sure that your custom types have thread-safe implementations of the IConvertible and IComparable interfaces, the Equals and GetHashCode methods.
4. The default summary values specified by the SummaryType property are calculated using the original data type
The Legacy engine converts all values to the Decimal type and subsequently calculates summary values. This operation is time-consuming. Thus in the LegacyOptimized engine, summary values are calculated using the original type. Decimal operations produce higher precision, so you may wish to enable decimal conversion in LegacyOptimized mode by setting the OptimizeSummaryTypeCalculation property to false.
5. Calculated Fields are processed for fields with incorrect FieldName values
The Legacy engine checks calculated fields’ FieldName and UnboundFieldName property values before processing. If both names match the name of any data source column, the field is bound and data is not calculated, but rather loaded from the data source instead. The LegacyOptimized engine does not verify field names and calculates all fields with any UnboundType property value except for UnboundColumnType.Bound.
6. It may be inefficient to use the CustomSummary event:
The CustomSummary event with the LegacyOptimized data processing engine may hinder the overall performance. The LegacyOptimized engine processes typed data while the CustomSummary event inherits an API from the old Legacy engine where untyped data is used. As a result, the use of this event requires multiple boxing/unboxing operations that always affect the performance.
To avoid this problem, we suggest using Unbound Fields with UnboundExpression to provide custom values instead of the CustomSummary event. Please check this solution and feel free to contact us if you face difficulties when rewriting your code to use unbound expressions. We will be happy to help you.
7. The IEnumerable.GetEnumerator method is used to read data source data
The Legacy engine reads all data using the IList.Item[Int32] property. The new LegacyOptimized engine uses the IList.Item[Int32] property to get values from specific data source rows and read data from the entire data source using the IEnumerable.GetEnumerator method for better performance.
8. UnboundExpreessions are compiled before processing
The Legacy engine processes UnboundExpressions separately for each data source row. This is a rather long operation and the LegacyOptimized engine compiles the UnboundExpression once before data processing. This approach demonstrates better performance, however it has strict requirements for types of provided data. For example, the Legacy engine can dynamically parse a String value to get DateTime or numbers. In the Legacy engine, you need to use ToDateTime, ToInt, ToDouble, and ToDecimal functions to parse string values.