davidjrh / dnn.rediscachingprovider

This caching provider allows to use a Redis cache server or cluster within DNN Platform (formerly DotNetNuke)
MIT License
23 stars 16 forks source link

Serializing with JSON #38

Open msant7 opened 3 years ago

msant7 commented 3 years ago

Hi, I was wondering if anyone had any thoughts about serializing with JSON instead of BinaryFormatter. I implemented the following as a test on my local dev and it seems to work well: https://patrickdesjardins.com/blog/serializing-complex-object-for-redis

PROS

Here is an example of a cached item...

get dma9_DNN_SkinDefaults_SkinInfo "{\r\n \"$id\": \"1\",\r\n \"$type\": \"DotNetNuke.UI.Skins.SkinDefaults, DotNetNuke\",\r\n \"AdminDefaultName\": \"Admin.ascx\",\r\n \"DefaultName\": \"Inner.ascx\",\r\n \"Folder\": \"/Xcillion/\"\r\n}"

Just curious if anyone has any thoughts on this or have tried this with DNN. Thanks

davidjrh commented 3 years ago

Sounds really interesting to me. When I built this module some time back, I tried with different serializers like DataContract, XmlSerializer (there is still code about it https://github.com/davidjrh/dnn.rediscachingprovider/blob/c938a92a1cbd637f92e6ada482466fa69482a7fc/RedisCachingProvider/Shared.cs#L66 that is not currently in use), etc. After lot of tests, the I got the best performance with binary uncompressed. Note that there is already an option to compress/decompress in place.

At that time, I didn't try with any JSON serialization, and after reviewing this post (https://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/), I'm thinking that having the option to use JSON or even other serializers would be an interesting experiment. Seems that just with JSON the performance would be better than binary.

Do you have measured the performance with lot of objects (small and large) so we can do some type of comparison?

On the other hand, the binary serializer can even serialize/deserialize private properties, not sure if that's possible with the other ones.

msant7 commented 3 years ago

Just to give an update on this. Everything was looking good, I was getting really good results on size and time, but then I hit a roadblock. I get the following exception: Exception of type 'DotNetNuke.Collections.Internal.ReadLockRequiredException' was thrown.

at DotNetNuke.Collections.Internal.SharedDictionary2.EnsureReadAccess() at DotNetNuke.Collections.Internal.SharedDictionary2.IEnumerable_GetEnumerator() at Newtonsoft.Json.Utilities.DictionaryWrapper`2.System.Collections.IDictionary.GetEnumerator() at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer) at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Formatting formatting, JsonSerializerSettings settings) at DotNetNuke.Providers.RedisCachingProvider.Shared.SerializeJSON(Object source) in C:\dnnsites\ot9\Providers\CachingProviders\RedisCachingProvider\RedisCachingProvider\Shared.cs:line 110 at DotNetNuke.Providers.RedisCachingProvider.RedisCachingProvider.Insert(String key, Object value, DNNCacheDependency dependency, DateTime absoluteExpiration, TimeSpan slidingExpiration, CacheItemPriority priority, CacheItemRemovedCallback onRemoveCallback) in C:\dnnsites\ot9\Providers\CachingProviders\RedisCachingProvider\RedisCachingProvider\RedisCachingProvider.cs:line 205

This occurs when TabInfo is serialized. What is specifically causing it is the following member variables: image

In order for those elements to be accessed, it needs to be accessed as follows, or you can't read the element. image

Not sure if anyone has any ideas.... Thanks

mtrutledge commented 2 years ago

Was any progress on this ever made?

mtrutledge commented 2 years ago

I am going to take a slightly different approach here. If the JSON serialization fails for some reason I am going to fall back to Binary serialization. Then check for base64encoded strings during deserialization.