Thursday 17 October 2019

Don't be afraid of the in-memory Cache

For a very long time, I had this doubt in my mind if "in-memory" cache is a justified solution if the number of items to be cached are quite high. I guess I had my own reasons for this; primarily because I had never tried to put so much data in such process level cache.

Of course, if it was 2005, we might still be using 32 bit hardware and memory constraints were equally important as optimized processing logic. But now that memory is cheap, we can be assured that it is ok to trade-off memory for better performance.

So, i ran an experiment.

            var memoryCache = MemoryCache.Default;
            Console.WriteLine(memoryCache.Count());
            Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64);
            Stopwatch sw = new Stopwatch();
            sw.Start();
            for (int i = 0; i < 1000 * 1000; i++)
            {
                memoryCache.Add("key" + i.ToString(), new Tuple("key" + i.ToString(), true), new CacheItemPolicy() { AbsoluteExpiration = DateTime.UtcNow.AddDays(1) });
            }
            sw.Stop();
            Console.WriteLine($"Time taken to write 1M values to cache {sw.ElapsedMilliseconds}");

            Console.WriteLine(memoryCache.Count());
            Console.WriteLine(Process.GetCurrentProcess().PrivateMemorySize64);

            memoryCache = MemoryCache.Default;
            Console.WriteLine(memoryCache.Count());
            sw.Restart();
            for (int i = 0; i < 1000 * 1000; i++)
            {
                var val = memoryCache.Get("key" + i.ToString()) as Tuple;
                if (val == null)
                {
                    Console.WriteLine("Found null");
                }
            }
            sw.Stop();

            Console.WriteLine($"Time taken to read 1M values to cache {sw.ElapsedMilliseconds}");

I wanted to check the impact on memory usage and if it there is any apparent issue with keeping 1M records in "in-memory" cache.

Well, there were no apparent issues.
0
19460096
Time taken to write 1M values to cache 4167
1000000
757383168
1000000
Time taken to read 1M values to cache 676

As you can see, there is not much delay in writing or reading so many records. The memory usage does definitely jump by a factor of 10 but i guess we planned to use more memory anyways.

Tuesday 8 October 2019

Azure Storage Blob : Policies

It has been a feature that was missing from Azure Storage Blob capabilities - adding policies for performing actions after certain conditions e.g. deleting a blob item after 1 month. 

There are typical use cases for it. I can give you one example.

Let's imagine an API that needs to asynchronously process messages it receives. An standard approach will be to put the message in a blob storage and leave a message in the queue with the address of blob item so that you can process the item later on.

Application's queue processor service can read the message, downloads the blob item and process the request. However, it might need to add a "maintenance" code to delete the blob item so that you don't store the unnecessary message. This is a code you could have avoided if platform had a feature for it :).

PS: if the message is smaller than 64kb than you can directly put it in a queue too, but we digress.


Well, Microsoft Azure Storage has added support for policies for handling typical actions (like the one i mentioned) for Azure Blob. Link

Quite nifty feature.

I can define a rule like below to delete items after 1 month.

{ "rules": [ { "name": "deleteTemporaryData", "enabled": true, "type": "Lifecycle", "definition": { "filters": { "blobTypes": [ "blockBlob" ], "prefixMatch": [ "queueinputblob/messages" ] }, "actions": { "baseBlob": { "delete": { "daysAfterModificationGreaterThan": 30 } } } } } ] }