Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Optimize cache with multiple keys in c# - remove duplication of objects

I have a project in Asp.Net Core. This project has a ICacheService as below:

public interface ICacheService
{
    T Get<T>(string key);
    T Get<T>(string key, Func<T> getdata);
    Task<T> Get<T>(string key, Func<Task<T>> getdata); 
    void AddOrUpdate(string key, object value);
} 

The implementation is simply based on ConcurrentDictionary<string, object>, so its not that complicated, just storing and retrieving data from this dictionary. At one of my services I have a method as below:

public async Task<List<LanguageInfoModel>> GetLanguagesAsync(string frontendId, string languageId, string accessId) 
{
    async Task<List<LanguageInfoModel>> GetLanguageInfoModel()
    {
        var data = await _commonServiceProxy.GetLanguages(frontendId, languageId, accessId);
        return data;
    }

    _scheduler.ScheduleAsync($"{CacheKeys.Jobs.LanguagesJob}_{frontendId}_{languageId}_{accessId}", async () =>
    {
        _cacheService.AddOrUpdate($"{CacheKeys.Languages}_{frontendId}_{languageId}_{accessId}", await GetLanguageInfoModel());
        return JobStatus.Success;
    }, TimeSpan.FromMinutes(5.0));

    return await _cacheService.Get($"{CacheKeys.Languages}_{frontendId}_{languageId}_{accessId}", async () => await GetLanguageInfoModel());
}

The problem is that I have three params in this method that I use as a cache key. This works fine but the problem is that the combination of three params is pretty high so there will be so many duplication of objects in cache. I was thinking to create a cache without duplication like below:

To have a cache with a list as a key where I can store more than one key for one object. So when I get new elements I will check for each of them if it is in the cache, if it is in the cache I will only add a key in the key list otherwise insert a new element in the cache. The problem here is that testing if an object is in the cache is a big problem. I think it will consume a lot of resources and would need some serialization into a specific form to make the comparison possible which will make again the comparison consuming a lot of resources. The cache might look something like this CustomDictionary<List<string>, object>

Does anybody know a good approach of solving this issue to not duplicate objects in the cache ?

EDIT 1:

My main concern is when I retrieve List<MyModel> from my webservices because they might have 80% of the objects with the same data which will drastically increase the size in memory. But this would be relevant for simple cases as well. Lest suppose I have something like this:

MyClass o1 = new MyObject();
_cache.Set("key1", o1);
_cashe.Set("key2", o1);

In this case when trying to add the same object twice I would like to not duplicate it but to have key2 somehow pointing to the same object as key1. If this achieved it will be problem to invalidate them but I expect to have something like this:

_cache.Invalidate("key2");

This will check if there is another key pointing to same object. If so, it will only remove the key otherwise destroy the object itself.

like image 789
Rajmond Burgaj Avatar asked Jul 12 '18 14:07

Rajmond Burgaj


People also ask

How do you optimize for a cache?

Bottom line, the key to optimizing for a cache (well, other than knowing the system quite well) is to keep all of the things you need performance for in the cache at the same time, organizing that data such that it is possible to have it all in the cache at once.

How to cache keys from the same object in Java?

The keys from the same Object, you can use object.hashCode (), so you don't need to specific keys one by one @Override @Cacheable (key="#bar.hashCode ()") public int foo (Bar bar) { ....

How can I make a memory cache useless?

You need to be acutely aware of all the memory transactions going on that are hitting that cache (some systems have independent instruction and data caches making the task easier). You can easily make a cache useless by not carefully managing your memory.

Is it possible to understand and optimize code transformations for caches?

The rules for code transformations are specified with a very rigorous mathematical model, so that it is something both computer scientists can understand and computers can execute. The following is a link posted by Larry OBrien in one of his answers. Show activity on this post. It is quite possible to understand and optimize for caches.


1 Answers

Maybe we could reformulate this problem to two separate issues ...

  1. executing the call for each combination and
  2. storing n times the identical result, wasting tons of memory

For 1 I don't have any idea how we could prevent it, as we do not know prior to execution if we will fetch a duplicate in this setup. We would need more information that is based on when these values vary, which may or may not be possible.

For 2 one solution would be to override hashcode so it is based on the actual returned values. A good solution would be generic and walk through the object tree (which probably can be expensive). Would like to know if there are any pre-made solutions for this actually.

like image 122
FrankyBoy Avatar answered Sep 21 '22 17:09

FrankyBoy