Cache - STARIONGROUP/COMET-SDK-Community-Edition GitHub Wiki
Caching enables storage data in memory for rapid access. When the data is accessed again, applications can get the data from the cache instead retrieving it from the original source. This improves performance and scalability. The CDP4-COMET-SDK provides a caching mechanism for the POCOs. The cache may contain the contents of the SiteDirectory
and multiple EngineeringModel
s and Iteration
s. One cache is corresponds to one data-source, e.g. the CDP4-COMET Web Services or an Exchange File.
The
cache
should be used for the development of end-user applications such as the CDP4-COMET-IME, it is not designed for server applications.
The CDP4-COMET cache is implemented using the ConcurrentDictionary. The ConcurrentDictionary
represents a thread-safe collection of key/value pairs that can be accessed by multiple threads concurrently.
ConcurrentDictionary<CacheKey, Lazy<Thing>> cache
The Key
of ConcurrentDictionary is a CacheKey that encapsulates the unique identifier of a Thing
and it's container Iteration
in case the Thing
is contained by an Iteration
, the Value
is a Lazy<Thing>
. If the Thing
is not in the containment tree of an Iteration
this Iteration
is set to null.
An
Iteration
in anEngineeringModel
is a snapshot of the state of the design at a certain point in time. When aIteration
is created all the data is copied from an existingIteration
to a newIteration
. All the unique identifiers of the objects in theIteration
are maintained. Therefore the same object (Thing) may exist in multipleIteration
s with the same unique identifier. The CDP4-COMET-SDK Cache provides the capability to store data from multipleIteration
s of the sameEngineeringModel
. To distinguish between these objects theKey
of theConcurrentDictionary
is the combination of the unique identifier of theThing
and the containerIteration
.
An operation acting on shared memory is atomic if it completes in a single step relative to other threads. Despite being thread-safe, the code executed by delegates of AddOrUpdate
and GetOrAdd
methods of the ConcurrentDictionary
is not subject to the atomicity of the operation. To solve that issue we use Lazy<T>
types as Value
of the ConcurrentDictionary
. Although in this case we are using Lazy<T>
mainly to ensure operation atomicity while working with the ConcurrentDictionary
, deferring the creation of an object until it is first used also improves performance, avoids wasteful computation, and reduces program memory requirements.
To maintain performance of the ConcurrentDictionary
it is important to limit the use of methods that acquire all locks on the ConcurrentDictionary
. The following operations in the dictionary cause it to acquire all the locks and should be avoided:
- Count, IsEmpty properties
- Keys, Values properties (which create a snapshot of the dictionary keys/values)
- CopyTo (explicit ICollection implementation)
- Clear
- ToArray
These functionality provided by these methods can be implemented using alternative strategies:
- Instead of
dictionary.Count()
usedictionary.Skip(0).Count()
- Instead of
Keys
andValues
properties use a LINQ select like this:dictionary.Select(item => item.Key)
« COMETCommon-CE POCO — Documentation overview — CDP4Common-CE Types »