ChunkList<T> Class
The collection type that is designed to improve performance when handling a large and frequently updated data source.
Namespace: DevExpress.Xpf.ChunkList
Assembly: DevExpress.Xpf.Core.v20.2.dll
NuGet Packages: DevExpress.WindowsDesktop.Wpf.Core, DevExpress.Wpf.Core
Declaration
public class ChunkList<T> :
IList<T>,
ICollection<T>,
IEnumerable<T>,
IEnumerable,
IBindingList,
IList,
ICollection,
IListChanging
Type Parameters
Name | Description |
---|---|
T | The type of elements in the ChunkList collection. |
Remarks
Overview
The ChunkList collection type is designed to improve performance when handling updates of large collections.
Note
Using the ChunkList<T>
provides significant performance improvements in applications that handle a large and frequently updated data source. However, operations that iterate over the elements of the data source (e.g., sorting, filtering, summary calculation) are executed slowly in comparison. Using the ChunkList<T>
in common scenarios is not recommended.
Items within the ChunkList<T>
collection are broken up in relatively small sublists of a fixed size - chunks. Thus, each element can be accessed by its chunk index and index within a chunk. This structure provides much better performance when executing the IndexOf, Insert and Remove data operations compared to a regular list.
The IndexOf operation is called each time the PropertyChanged event fires for an object in a collection to determine the object’s position on the list. In a standard collection, it is necessary to iterate through the entire list to find the object index. In ChunkList<T>
, the object’s chunk index is already known, and you are only required to find the object’s index within a chunk.
When the Insert or Remove operations are performed in a standard collection, the collection has to shift all the items following the inserted/removed item. In ChunkList<T>
, items will only be shifted in a chunk where the item was inserted or removed, while other chunks stay intact.
The table below illustrates the difference in performance between BindingList and ChunkList<T>
.
Scenario (1,000,000 items) | BindingList Standalone | ChunkList Standalone | BindingList Bound to GridControl | ChunkList Bound to GridControl |
---|---|---|---|---|
Creation time | 1016 | 1171 | 1422 | 2016 |
Insert 10000 items | 6422 | 250 | 7765 | 469 |
Remove 10000 items | 9700 | 219 | 8400 | 438 |
Update 10000 items | 58700 | 156 | 59328 | 250 |
Full iteration | 47 | 328 | ||
Memory used (MB) | 59 | 90 | ||
Sort string property | 7485 | 8187 | ||
Sort int property | 2465 | 3313 |
Implement ChunkList
When creating a ChunkList<T>
, you need to specify the approximate size of the collection using the capacity parameter of the ChunkList<T> constructor. The chunk size is calculated as the square root of the capacity value. You can also use the constructor’s chunkSize parameter instead to explicitly set the chunk size.
There are two ways to enable the ChunkList<T>
to determine the data object’s chunk index.
Implement the IChunkListObject.ChunkObject property of the IChunkListObject interface in your data objects, so the chunk index is stored in a field at the object level.
Pros: data source is generated faster and consumes less memory.
Cons: this method requires data object modification.
See the example below.
public class DataObject : IChunkListObject { public int NumericField { get; set; } public string StringField { get; set; } public object ChunkObject { get; set; } } public class DataSource { public ChunkList<DataObject> Data { get; set; } public DataSource() { Data = new ChunkList<DataObject>(capacity: 1000000); for (int i = 0; i < 1000000; i++) { Data.Add(new DataObject()); } } }
Set the useChunksCache parameter of the ChunkList<T> constructor to true to create a hash table that stores chunk indexes for collection items.
Pros: this method does not require data object modification.
Cons: the hash table requires additional memory.
See the example below.
public class DataObject { public int NumericField { get; set; } public string StringField { get; set; } } public class DataSource { public ChunkList<DataObject> Data { get; set; } public DataSource() { Data = new ChunkList<DataObject>(capacity: 1000000, useChunksCache: true); for (int i = 0; i < 1000000; i++) { Data.Add(new DataObject()); } } }
You can also enable each chunk to listen to PropertyChanged events separately by setting the supportPropertyChanged parameter to true. In this case, there is no need to determine the chunk index to find the item position in the list, so you can disable creating a hash table by setting the useChunksCache parameter to false. However, the IndexOf operation called in runtime will not be optimized.
See the example below.
public class DataObject : INotifyPropertyChanged { private int numericField; private string stringField; public int NumericField { get { return numericField; } set { numericField = value; OnPropertyChanged("NumericField"); } } public string StringField { get { return stringField; } set { stringField = value; OnPropertyChanged("StringField"); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } public class DataSource { public ChunkList<DataObject> Data { get; set; } public DataSource() { Data = new ChunkList<DataObject>(chunkSize: 1000, supportPropertyChanged: true); for (int i = 0; i < 1000000; i++) { Data.Add(new DataObject()); } } }