Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory management / caching for costly objects in C#

Assume that I have the following object

public class MyClass
{
    public ReadOnlyDictionary<T, V> Dict
    {
        get
        {
            return createDictionary();
        }
    }
}

Assume that ReadOnlyDictionary is a read-only wrapper around Dictionary<T, V>.

The createDictionary method takes significant time to complete and returned dictionary is relatively large.

Obviously, I want to implement some sort of caching so I could reuse result of createDictionary but also I do not want to abuse garbage collector and use to much memory.

I thought of using WeakReference for the dictionary but not sure if this is best approach.

What would you recommend? How to properly handle result of a costly method that might be called multiple times?

UPDATE:

I am interested in an advice for a C# 2.0 library (single DLL, non-visual). The library might be used in a desktop of a web application.

UPDATE 2:

The question is relevant for read-only objects as well. I changed value of the property from Dictionary to ReadOnlyDictionary.

UPDATE 3:

The T is relatively simple type (string, for example). The V is a custom class. You might assume that an instance of V is costly to create. The dictionary might contain from 0 to couple of thousands elements.

The code assumed to be accessed from a single thread or from multiple threads with an external synchronization mechanism.

I am fine if the dictionary is GC-ed when no one uses it. I am trying to find a balance between time (I want to somehow cache the result of createDictionary) and memory expenses (I do not want to keep memory occupied longer than necessary).

like image 654
Bobrovsky Avatar asked Jun 10 '12 19:06

Bobrovsky


People also ask

When should you use cache memory?

Accelerating online database applications is the most common use case for in-memory caching. For example, a high-traffic website storing content in a database will significantly benefit from the in-memory cache.

Why cache is faster than database?

A cache's primary purpose is to increase data retrieval performance by reducing the need to access the underlying slower storage layer. Trading off capacity for speed, a cache typically stores a subset of data transiently, in contrast to databases whose data is usually complete and durable.

What is caching in C?

Caching is a separate memory, yes, and it has it's own addresses, but when the CPU caches memory lines from RAM, it keeps a record of what RAM-addresses the memory was on, and keeps a map between RAM-address and cache-address. From the point of view of your program, the address is the same.


1 Answers

WeakReference is not a good solution for a cache since you object won´t survive the next GC if nobody else is referencing your dictionary. You can make a simple cache by storing the created value in a member variable and reuse it if it is not null.

This is not thread safe and you would end up in some situations creating the dictionary several times if you have heavy concurent access to it. You can use the double checked lock pattern to guard against this with minimal perf impact.

To help you further you would need to specify if concurrent access is an issue for you and how much memory your dictionary does consume and how it is created. If e.g. the dictionary is the result of an expensive query it might help to simply serialize the dictionary to disc and reuse it until you need to recreate it (this depends on your specific needs).

Caching is another word for memory leak if you have no clear policy when your object should be removed from the cache. Since you are trying WeakReference I assume you do not know when exactly a good time would be to clear the cache.

Another option is to compress the dictionary into a less memory hungry structure. How many keys does your dictionary has and what are the values?

like image 118
Alois Kraus Avatar answered Oct 19 '22 07:10

Alois Kraus