I have a key/value pairs mapped by hash (ID) in Dictionary<string, Dictionary<string, string>> called id2key_value. You can think of this as a way to represent database-like table with rows.
I added some helper functions to ease the use of some basic datatypes by doing a cast, like
public int GetInt(string id, string key)
{
int value = 0;
bool success = int.TryParse(map[id][key], out value);
if (success)
return value;
else
throw new InvalidOperationException(
"Trying to obtain a non-integer value with GetInt().");
}
Well, I thought I was being clever when I came up with an idea of a “cast-cache”, which basically holds already parsed objects, so I could skip the parsing of the string for int, bool, DateTime, etc., and simply cast them to appropriate datatype from the cache. Like,
public int GetInt(string id, string key)
{
if (cast_cache.ContainsKey(id) && cast_cache[id].ContainsKey(key))
return (int) cast_cache[id][key];
int value = 0;
bool success = int.TryParse(map[id][key], out value);
if (success)
{
this.AddToCache(id, key, value);
return value;
}
else
throw new InvalidOperationException(
"Trying to obtain a non-integer value with GetInt().");
}
The “cast-cache” is simply Dictionary<string, Dictionary<string, object>>.
So, I did some performance testing with 10000 ints added to the map. Then I did one million random retrieves, with and without “cast-caching”.
It took 495(ms) without caching and 490(ms) with caching. I also ran a test with DateTime, there the difference was more significant, but less than I expect (~750(ms) non-cached vs ~500(ms) cached).
Not (obviously) understanding the principle of a cast, how costly this operation is and why the performance is so close to the one that “deserializes” from string?
Casting is much faster that most people seem to think since you are not touching the object itself (you are simply changing the reference that points to that object).
One of the main reasons that you ought to avoid casting is that when you cast you are eschewing type-safety and introducing potential execution-time errors into your application. I would rarely consider casting to be a performance concern.
As a side note I would make sure that you test both reference types and value types in your cache to make sure that you are not incurring a performance penalty due to the boxing and unboxing of any value types.
The performance penalty of boxing comes from the fact that casting a value type to an object does involve more than changing a reference as the value type must be copied to the heap. Also the use of a boxed value type will unbox the reference type and subsequently copy those values from the heap to the stack again.