Is MemoryCache scope session or application wide? - asp.net

I'm using MemoryCache in ASP.NET and it is working well. I have an object that is cached for an hour to prevent fresh pulls of data from the repository.
I can see the caching working in debug, but also once deployed to the server, after the 1st call is made and the object is cached subsequent calls are about 1/5 of the time.
However I'm noticing that each new client call (still inside that 1 hour window - in fact just a minute or 2 later) seems to have the 1st call to my service (that is doing the caching) taking almost as long as the original call before the data was cached.
This made me start to wonder - is MemoryCache session specific, and each new client making the call is storing it's own cache, or is something else going on to cause the 1st call to take so long even after I know the data has been cached?

From MSDN:
The main differences between the Cache and MemoryCache classes are
that the MemoryCache class has been changed to make it usable by .NET
Framework applications that are not ASP.NET applications. For example,
the MemoryCache class has no dependencies on the System.Web assembly.
Another difference is that you can create multiple instances of the
MemoryCache class for use in the same application and in the same
AppDomain instance.
Reading that and doing some investigation in reflected code it is obvious that MemoryCache is just a simple class. You can use MemoryCache.Default property to (re)use same instance or you can construct as many instances as you want (though recommended is as few as possible).
So basically the answer lies in your code.
If you use MemoryCache.Default then your cache lives as long as your application pool lives. (Just to remind you that default application pool idle time-out is 20 minutes which is less than 1 hour.)
If you create it using new MemoryCache(string, NameValueCollection) then the above mentioned considerations apply plus the context you create your instance in, that is if you create your instance inside controller (which I hope is not the case) then your cache lives for one request
It's a pity I can't find any references, but ... MemoryCache does not guarantee to hold data according to a cache policy you specify. In particular if machine you're running your app on gets stressed on memory your cache might be discarded.
If you still have no luck figuring out what's the reason for early cache item invalidation you could take advantage of RemoveCallback and investigate what is the reason of item invalidation.

Reviewing this a year later I found out some more information on my original post about the cache 'dropping' randomly. The MSDN states the following for the configurable cache properties CacheMemoryLimitMegabytes and PhysicalMemoryLimitPercentage:
The default value is 0, which means that the MemoryCache class's
autosize heuristics are used by default.
Doing some decompiling and investigation, there are predetermined scenarios deep in the CacheMemoryMonitor.cs class that define the memory thresholds. Here is a sampling of the comments in that class on the AutoPrivateBytesLimit property:
// Auto-generate the private bytes limit:
// - On 64bit, the auto value is MIN(60% physical_ram, 1 TB)
// - On x86, for 2GB, the auto value is MIN(60% physical_ram, 800 MB)
// - On x86, for 3GB, the auto value is MIN(60% physical_ram, 1800 MB)
//
// - If it's not a hosted environment (e.g. console app), the 60% in the above
// formulas will become 100% because in un-hosted environment we don't launch
// other processes such as compiler, etc.
It's not necessarily that the specific values are important as much as realizing to why cache is often used: to store large objects that we don't want to fetch over and over. If these large objects are being stored in the cache and the hosting environments memory threshold based on these internal calculations are exceeded, you may have the item removed from cache automatically. This could certainly explain my OP because I was storing a very large collection in memory on a hosted server with probably 2GB of memory running multiple apps in IIS.
There is an explicit override to setting these values. You can via configuration (or when setting up the MemoryCache instance) set the CacheMemoryLimitMegabytes and PhysicalMemoryLimitPercentage values. Here is modified sample from the following MSDN link where I set the physicalMemoryPercentage to 95 (%):
<configuration>
<system.runtime.caching>
<memoryCache>
<namedCaches>
<add name="default"
physicalMemoryLimitPercentage="95" />
</namedCaches>
</memoryCache>
</system.runtime.caching>
</configuration>

Related

When to use HttpApplicationState rather than Web.Caching.Cache?

When i need to cache something in my application, i used to choose Web.Caching.Cache. But i ran into some legacy code that using HttpApplicationState instead.
Since Web.Caching.Cache is more powerful and flexible (seems MUCH more), is there a situation that better to use HttpApplicationState??
I will be very appreciate if you can show me some examples :-)
Both HttpApplicationState and Web.Caching.Cache can be used to store information that can be globally accessible throughout an ASP.Net application. However, they have very different uses.
HttpApplicationState is used to store application data that typically does not change. It is typically populated in Application_Start in Global.asax, when the application is starting. I personally have not used it much, but I believe it is typically used to store small pieces of application configuration that are global to all users of an application and which either do not change or change very infrequently. Something put into Application state will remain there indefinitely, until the app recycles. But when it recycles and restarts again, Application_Start will execute again and re-populate it.
It is important to note that HttpApplicationState is a singleton and is not thread safe. So when you make changes to it, you must lock and unlock the Application object via calls to Application.Lock() and Application.UnLock(). Read more
There are actually three different ways you can cache ASP.Net content: Page level, partial page, and data. I am going to talk about data caching, since I think that is most relevant to your question. The ASP.Net cache is used to store large quantities of application data that would be expensive to retrieve from a data store for every request. The key differences between HttpApplicationState and Cache are 1) Cache data is designed to expire and be purged from memory by a variety of triggers or conditions (time, other cache dependencies, etc), whereas HttpApplicationState will be there forever until the app recycles, and 2) Cache data can be purged from memory if a server is experiencing severe memory pressure, and you thus can never count on it being there and must always test to see if it is present, whereas HttpApplicationState will always be there.
Caching is used to store data closer to the application that does not need to be pulled from a database on every request. Caching is designed to store very large quantities of data, and an intelligent caching architecture can have an enormous positive impact on performance.

Is Caching in C# the right approach for me?

I've tried to read up on Caching in ASP.NET and still have a few questions.
When using a Sql Cache Dependency ... I know that you can specify which tables will be monitored but if a change happens to any one of those tables does it reset the entire cache? I understand that I don't want to cache tables that will have frequent changes but we could end up with a good handful of cached tables and even if each table only gets a few updates a day, that could turn into 50ish resets of the cache daily (8 hour window).
I would be creating and maintaining this cache via a GAC DLL. A large number of different applications would be accessing that GAC at any one time. Does each application maintain its own copy of the cache or is it just stored in one global location (or possibly per app pool)?
Is there a physical location on the server where I can see how much space the Cache is currently consuming? This would be extremely pertinent if each application maintains its own Cache as that could end up taking large amounts of disk space.
Is there some way to physically force the cache to rebuild itself? I could see my boss assuming that the cache was at fault for a particular issue and I'd need to be able to rule that out at the rootest level. No "changing a record and saying that SHOULD rebuild the cache" but rather "doing [Action X] and KNOWING that whatever was in the cache is now gone"
Thanks in advance for your answers and time.
SqlCacheDependency only monitors tables in the old-style SQL 2000 approach, which relies on triggers and polling. The SQL 2005+ method monitors changes at the row level, and uses Service Broker. At the level of the Cache object, changes will invalidate just the Cache entries associated with the given SqlCacheDependency (not the entire cache).
Each application has a separate copy of the Cache. If you have many apps sharing the same data, you might consider creating a separate "caching server," and have your apps get their data from there, using WCF -- basically add another tier to your app.
You can look at a couple of cache-related performance counters, but if your concern is disk space, then there's nothing to worry about, since the ASP.NET cache is stored entirely in RAM. In addition, if RAM gets too full, one feature of the cache is that it will let go of old/infrequently referenced objects to make room for new objects.
The easiest way to force the cache to be dropped is to simply recycle your application or AppPool (which happens once a day or so by default anyway). If you want something more targeted, you would need to write some code to forcibly remove certain items from the cache, either using Cache.Remove() or using linked dependencies.
from top of my head:
Only that table's content will be invalidated.
Each web application has it's own cache.
Cache is stored in memory. and see this question How to determine total size of ASP.Net cache? regarding cache size
http://bit.ly/vsqNDl this may help

value of ASP.NET variables for different users

I'm using VS2010,C# to develop my ASP.NET web app, sometimes I need to declare public or even public static variable at start of my codebehind files, so that I can access them globally in the file and also they preserve their value between postbacks, everything works fine on my local server (as I'm the only person who runs the code). But I don't know exactly what happens when this page (and therefor its codebehind) are run by several web site visitors at the same time, I want my program to run the same for all users, but I think in this way something will cause problems, I can remember from my previous ASP.NET experience that using variable (public or public static) in codebehind can cause misunderstanding for different users of web site, for instance:
user A runs program, (public static int) my_int that had the value of -1 at startup has taken value of 100, and at this time user B runs the same page, so my_int is 100 and it will cause problems, also suppose that user A leaves the page while my_int has value of 100, then user B will visit the page my_int would be initially 100 (while that should be -1) so I think unexpected behaviors would occur
is it right? will this happen at all? if so, how can I prevent it? should I use session instead of variables? how can I have a better understanding about the whole situation
thanks friends
A simple rule - you need to choose storage as per the scope of data being stored. And for any mutable (read/write) shared state, you have worry about concurrent access (thread safety). For example, if a variable is a static then it would available through-out application (correctly speaking app-domain) but it also means you have ensure thread-safety while reading/writing the variable. Here are few tips
For per request scope, use local variables. No need for thread-safety (as only request thread would access it).
For per page scope (over repeated post-backs), use view-state. No need for thread-safety (as only request thread would access it).
For per user scope, use session state. A good thing about session state is that you don't have to worry about thread-safety (ASP.NET take care of that).
For application wide scope (strictly speaking app-domain wide scope), use application state or static variables. Application State offers lock/unlock API for thread-safety while for static variables, you have put your own locking mechanism. Static variables are good bet for application wide read-only data i.e. you initialize them at the start of application and then use the information whenever needed w/o locking because there are no writes.
For any scope larger than this, use database (or any other persistent data store). For database, transactions are used to ensure consistency.

ASP.NET Data Cache - preserve contents after app domain restart

I am using ASP.NET's data caching API. For example:
HttpRuntime.Cache.Insert(my_data, my_key);
Is there any way to configure cache so its contents are preserved when the App Domain recycles?
I load many object into cache, but there is a substantial delay re-loading these every time the app domain restarts. Assume for this question that I can't prevent the appdomain restart due to a server configuration.
Is there any way to configure cache so
its contents are preserved when the
App Domain recycles?
No. The Cache object holds references in RAM. Period.
Alternatives:
Out-of-process Session state (although that's per-user)
Distributed cache
Use SQL Server as a cache (where it keeps data in memory, rather than on disk)
Write the objects to disk at the web tier
I generally prefer #3 myself, although there are scenarios where the others are appropriate.
Recycling the appdomain dumps the cache. If you want to get around this you'd need to use a distributed cache. Here's an example.
For your most expensive data you can cache the objects with a distributed cache such as Memcached or velocity. Depending on the size of the object and the length of runtime you could also serialize it to disk or to your database provided that the access speed to these resources is less than the time to create the object.
Now since the in-proc cache is super fast compared to any other solution since it just holds a reference to the memory object you will want to use it where possible. You can keep a copy of your cached object on disk until it is lost and then re-create it from that and place it in memory. Where this is tricky is when you have to expire the data so only use the cache/disk/sql combo where you won't need to expire/invalidate the data otherwise you will need to ensure that you clear both. This will also get around not being able to implement distributed caching on a shared server for example.

How do I prevent static member variables from being accessed by more than one request at a time in IIS?

I’m having some trouble with understanding how IIS is handling static variables on its threads. My understanding has always been that if IIS has 4 worker processes that it can handle 4 requests simultaneously and that it would be the same as having 4 separate threads running the website. Any static variables would persist in each individual thread. The reason I’m a bit confused is that I have a scope that I’ve made which manages connections and caching transactions. When I’m testing the app I don’t notice any issues but after I’ve compiled it and hit it at the same time from two different locations I seem to get a sort of conflict. Now if these worker processes are separate why would this be? Can more than one request be processed on a single worker thread at the same time? This is tremendously important as there are unique ID’s that are held in these static members to handle escalation of the objects that manage these functions and it appears that they are trying to access the same object.
I'm running this on Vista's IIS server on an x64 machine.
EDIT
For values that need to persist through the thread on a single request, I put these values into Web.HttpContext.Current.Items which seems to do the trick.
<ThreadStatic()> can be used but it may not be available during the entirity of the request process. In one module that I have, is only used on a variable to indicate if that thread has already loaded the settings for the cahcing server. If true then the tread (not asp.net) is ready to fetch data from the caching server.
First concept to change: if you're using ASP.NET, they are ASP.NET threads, not IIS threads.
Second, this is a .NET issue. static variables are shared throughout the AppDomain in .NET. Since you'll have one AppDomain per IIS application (more or less), that means your static variables will be shared across all worker threads in the application.
There will be a lot more than four threads, and they'll all be sharing the same variables, which means you'll either need to do locking, or you'll need to not use static variables.
Whatever your understanding has always been, I suggest you go back and figure out where you got that understanding from; then update it, because it doesn't have much to do with ASP.NET.
EDIT: The subject has changed, so I'll change the answer a little.
You have to interlock access to these variables. Alternatively, you should consider reevaluating your design. Your design apparently assumed some different model for access to statics. This assumption has turned out not to be correct. It's possible that this assumption may have cascaded throughout your design. You should reevaluate your design in the light of reality.
Each worker process runs in its own AppDomain, so each WP will have its own instance of a static variable.
In the answer here it suggests the AppDomain is shared across WPs which is incorrect.
You should be using the .NET connection pooling though and you should investigate the using(IDisposable){} method of scoping your connections.

Resources