When using the HttpRuntime.Cache in an ASP.NET application, any item retrieved from the cache that is then updated will result in the cached object being updated too (by reference). Subsequent reads from the cache will get the updated value, which may not be desirable.
There are multiple posts on this subject, for example:
Read HttpRuntime.Cache item as read-only
And the suggested solution is to create a deep-copy clone using binary serialization.
The problem with binary serialization is that it's slow (incredibly slow), and I can't afford any potential performance bottlenecks. I have looked at deep-copying using reflection and whilst this appears to be better performing, it's not trivial to implement with our complex DTOs. Anyone interested in this may want to have a look at the following brief article:
Fast Deep Cloning
Does anyone have any experience of caching solutions such as AppFrabric / NCache etc and know whether they would solve this problem directly?
Thanks in advance
Griff
Products like NCache and AppFabric also perform serialization before storing the object in an out-of-process caching service. So you'd still take that serialization hit, plus you'd get slowed down even further by going out-of-process (or maybe even over the network) to access the serialized object in the caching service.
Implementing ICloneable on your classes to perform hand-tuned deep copies will avoid reflection and will outperform binary serialization, but this may not be practical if your DTOs are very complex.
Updated to provide specifics:
AppFabric usese the NetDataContractSerializer for serialization (as described here). The NetDataContractSerializer can be a little faster than the BinaryFormatter, but its performance is usually in the same ballpark: http://blogs.msdn.com/b/youssefm/archive/2009/07/10/comparing-the-performance-of-net-serializers.aspx
NCache rolled their own serializer, called "Compact Serialization". You need to either implement their ICompactSerializable interface on your DTO classes and read/write all members by hand, or else let their client libraries examine your class and then emit its own serialization code at runtime to do that work for you (it's a one-time hit when your app starts up, where they have to reflect over your class and emit their own MSIL). I don't have data on their performance, but it's safe to assume that it's faster than serializers that perform reflection (BinaryFormatter/DataContractSerializer) and probably somewhere in the same performance realm as protobuf, MessagePack, and other serializers that avoid excessive reflection. More detail is here.
(I work for a company (ScaleOut Software) that's in the same space as NCache, so I should probably know more about how they do things. ScaleOut lets you plug in whatever serializer you want--we usually recommend Protobuf-net or MessagePack, since they're generally considered to be the reigning champions for .NET serialization performance--definitely take a close look at those two if you decide to use a serializer to make your deep copies.)
Most cache frameworks rely on serialization.
You should consider invalidating the cache each time you change an object.
For example:
object Get(string key)
{
if (!Cache.Contains(key))
{
Cache[key] = GetDataFromDatabase(key);
}
return Cache[key];
}
void Invalidate(string key)
{
Cache.Remove(key);
}
So you can do:
var myDto = Get(id);
myDto.SomeProperty = "changed";
myDto.Save();
Invalidate(id);
Related
I've been looking for a type that is analogous to the MemoryStream class, but uses a Memory<T> as storage medium instead of byte
The reason for this, is I want to create in-memory streams, whose data might come from either managed, or unmanaged source, and avoid the performance cost that comes with copying said data.
Does anyone know a type that derives from System.Stream and is applicable in this scenario?
I've looked around the open issues on the corefx github, and it seems that such a type would be indeed be nice to have, and they have an open issue about it. However as things stand, such a thing is not yet available.
For my global variables and data I find myself in a dilema as to whether to use HttpApplicationState or Static variables - What's the best approach?
This document states that one should use static variables over httpapplicationstate:
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312607
However, one thing I like about HttpApplicationState (and System.Web.Caching.Cache), is that one can easily enumerate the entries and select which items to remove (I've created a global CacheManager.axd for this purpose), whereas I don't believe there's an easy way with Static variables (and even then it's not clear what to do to "re-initialise" them), without recycling the app pool.
Any suggestions on a neat general-purpose way to handle and manage global objects?
Thanks, Mark.
Your instincts are correct. Use System.Web.Caching. The built-in cache management takes care of all the heavy lifting with respect to memory allocation and expiring stale or low priority objects.
Make sure to use a naming convention, for your cache keys, that makes sense down the road. If you start relying heavily on caching, you'll need to be able to target/filter different cache keys by name.
As a general practice, it's good to try to avoid global state in web applications when possible. ASP.NET is a multithreaded environment where multiple requests can get serviced in parallel. Unless your global state is immutable (readonly), you will have to deal with the challenges managing shared mutable state.
If your shared state is immutable, and you don't need to enumerate it, then I see no problem with static variables.
If your shared state is volatile/mutable, then you probably want to create an abstraction on top of whichever underlyig mechanism you choose to store the data to ensure that access and modification of that shared state is consistent and complies with the expectations of the code that consumes it. I would probably use the system cache in such a design as well, just to be able to leverage the expiration and dependency features built in to the caching service (if necessary).
New to .net and was wondering if there is a performance gain to keeping an instance of, for example a DAL object in scope?
Coming from the Coldfusion world I would instanciate a component and store it in the application scope so that every time my code needed to use that component it would not have to be instanciated over and over again effecting performance.
Is there any benefit to doing this in ASP.Net apps?
Unless you are actually experiencing a performance problem, than you need not worry yourself with optimizations like this.
Solve the business problems first, and use good design. As long as you have a decent abstraction layer for your data access code, then you can always implement a caching solution later down the road if it becomes a problem.
Remember that any caching solution increases complexity dramatically.
NO. In the multi-tier world of .asp this would be considered a case of "premature optimization". Once a sites suite of stubs, scripts and programs has scaled up and been running for a few months then you can look at logs and traces to see what might be cached, spawned or rewritten to improve performance. And as the infamous Jeff Atwood says "Most code optimizations for web servers will benifit from money being spent on new and improved hardware rather than tweaking code for hours and hours"
Yes indeed you can and probably should. Oftentimes the storage for this is in the Session; you store data that you want for the user.
If it's a global thing, you may load it in the Application_Start event and place it somewhere, possibly the HttpCache.
And just a note, some people use "Premature Optimisation" to avoid optimising at all; this is nonsense. It is reasonable to cache in this case.
It is very important to do the cost benefit analysis before caching any object, one must consider all the factors like
Performance advantage
Frequency of use
Hardware
Scalability
Maintainability
Time available for delivery (one of the most important factor)
Finally, it is always useful to cache object which are very costly to create or you are using very frequently i.e. Tables's Data (From DB) or xml data
Does the class you are considering this for have state? If not, (and DAL classes often do not have state, or do not need state), then you should make it's methods static, and then you don't need to instantiate it at all. If the only state it holds is a connection string, you can also make that property field a static property field, and avoid the requirement of instantiating it that way.
Otherwise, take a look at the design pattern called Flyweight
Are there any clever layers out there to sit on top of the System.Web.Caching.Cache class to handle simple scenarios to fetch items using generics.
I'd like to maybe provide a delegate function to retrieve an item, and be able to fetch an item with a strongly typed GetItem and a delegate function to retrieve an item if it isnt found.
For instance
CleverCache<K, T>
T GetItem(K)
RegisterDelegate(FetchItemDelegate<K,T>)
I'd also like a nice way to handle a cache that only ever handles a single object.
The ASP.NET Cache object just seems really primitive. It just seems like a hashtable with a timeout. They may as well just call it HashtableWithTimeout for all I care. I want some better astraction. Is this the kind of thing that the caching application block will do for me?
Yes I know this is fairly simple code, i just dont have time for any wheel reinventing right now.
You may want to look into some more sophisticated cache providers that can wrap the ASP.NET cache, such as the Enterprise Library's caching block. It provides a much more robust and rich caching story for object lifecycle, invalidation, retrieval, etc.
The ASP.NET cache deserves more credit than you give it - it's actually a very powerful base. Alone, it doesn't do anything complex as you have pointed out, but it is well-designed and robust enough to support some pretty cool stuff.
You may want to look into SharedCache and Microsoft Velocity as improvements to the basic caching available in ASP.NET. I don't know how extensively strong typing is designed into either - but from the samples and documentation I've seen it's better than the ASP.NET Cache.
I have recently inherited an ASP.Net app using Linq2SQL. Currently, it has its DataContext objects declared as static in every page, and I create them the first time I find they are null (singleton, sort of).
I need comments if this is good or bad. In situations when I only need to read from the DB and in situations where i need to write as well.
How about having just one DataContext instance for the entire application?
One DataContext per application would perform badly, I'm afraid. The DataContext isn't thread safe, for starters, so even using one as a static member of a page is a bad idea. As asgerhallas mentioned it is ideal to use the context for a unit of work - typically a single request. Anything else and you'll start to find all of your data is in memory and you won't be seeing updates without an explicit refresh. Here are a couple posts that talk to those two subjects: Identity Maps and Units of Work
I use to have one DataContext per request, but it depends on the scenarios you're facing.
I think the point with L2S was to use it with the unit of work pattern, where you have a context per ... well unit of work. But it doesn't work well in larger applications as it's pretty hard to reattach entities to a new context later.
Rick Strahl has a real good introduction to the topic here:
http://www.west-wind.com/weblog/posts/246222.aspx
One thing I can say I have had problems with in the past, is to have one context to both read and write scenarios. The change tracking done in the datacontext is quite an overhead when you are just reading, which is what most webapps tends to do most of the time. You can make the datacontext readonly and it will speed up things quite a bit - but then you'll need another context for writing.