I'm thinking over an ASP.NET application that uses ESENT for persistance.
At this point this is just my hobby project, so the requirements are very flexible. However I'd like it to work on Windows 7, Windows 2008, and 2008 R2, with .NET 3.5 and higher, and default IIS settings.
In ESENT, most operations require you to open a session object. The documentation says: "A session tracks which thread it was used on, and it will throw an error if used on multiple threads with an open transaction." The API documentation mentions the native threads, not managed threads.
I assume the open session operation is relatively expensive, that's why I don't want to open/close session for every HTTP request.
Here're my questions, finally.
How in asp.net do I initialize / deinitialize something exactly once, on every native thread that executes my C# code?
Will the code like posted below work for me?
Is there something bad I don't know in keeping the asp.net managed thread constantly pinned to the native thread with BeginThreadAffinity method? Wont my sessions leak after the IIS is under the load for a month without a single reboot?
Thanks in advance!
class MySession: IDisposable
{
[ThreadStatic]
private static MySession s_session = null;
public static MySession instance
{
get
{
return s_session ?? ( s_session = new MySession() );
}
}
private MySession()
{
Thread.BeginThreadAffinity();
// Open a new session, store the handle in non-static data member.
}
void IDisposable.Dispose()
{
// Close the session.
Thread.EndThreadAffinity();
}
}
One good approach is to create a pool of sessions and have threads grab a session from the pool and then return the session when done. A session can be used by different threads, but ESENT will complain if you migrate a session between threads while a transaction is active (it is possible to disable that behaviour though).
Several large server apps that use ESENT have taken the session pool approach and it works well for them.
our current research shows that instancing a new session in page_load and disposing it in page_unload easily yields 600 reqs/sec with wcat for a simple script that seeks on an index, and does two other seeks for each returned row.
in other words with proper tuning of esent params a session pool might not be needed.
example above is with maxsessions set to 256. adjusting minimum cache size also helps performance. on a quad core test server with 8 gb ram.
This will probably not work in this form if you really intend to leave the session open across requests.
The finalizer will run on a separate thread and closing the session will throw an error.
Most probably
JET_errSessionInUse -
session was in use on another thread, or the session was not set or reset properly in JetEndSession() during Dispose().
If you really must use ESENT, maybe you can fire up and manage a dedicated pool of threads by hand and marshal calls to/from them.
Related
I'm writing an ASP.NET MVC5 Application, I know that the actions where session["foo"] = bar are ran sequentially, now to avoid this, i want to store some informations into a MemoryCache object and not in session, but my doubt is: Is the cache managed like the session? So the actions where i put ObjectCache.Set("foo", bar, null) are ran sequentially like for session?
I know the scope difference between cache and session but for me and in this case it's not important.
Thank to everyone
I understand that you try to avoid the session lock on the page.
The cache is not lock the full page access so the answer is that the cache is not run sequentially.
There are two kind of cache, one in memory that use static dictionary to keep the data and one that save the cache on database, that use files to save the data. Both of them locks the data only for the period of read/write, while the session is lock the full access on the page from start to the end of it.
So use cache, but close the session on the page you have this issue. Also have in mind that if you use web garden then the cache on memory can have multiple different data because memory cache have its own static space on each pool.
Also the session is different for each user, the cache is the same for all users.
some more to read : ASP.NET Server does not process pages asynchronously
I think the term you are looking for is thread safety - especially around concurrent access, typically writing.
Seems that according to MSDN, System.Runtime.Caching.MemoryCache is indeed thread safe. See also: Is MemoryCache.Set() thread-safe?
I am wondering if a static class in an ASP.NET MVC app could be initialized more than once. I initially designed my app so that a static component would fetch some stuff from the database and serve as a cache, and I added a refresh method to the class which was called from the constructor. The refresh method was also made available through the administration portion of the app. At some point I noticed that the data was updated without requiring this manual trigger, which implies that the static constructor run more than once.
There are several scenarios where I could reasonably see this happen, such as an unhandled Exception causing re-initialization. But I am having trouble reproducing this, so I would like to know for sure.
The most usual scenarios would be:
a reload of the web application
touched Web.config
touched binaries
abnormal termination (out-of-memory, permission errors)
a reload of the Application Pool
a restart of IIS
a restart of w3wp.exe (at least once in 29 hours!)
The app-domain will get reloaded (recompiling the dynamic parts as necessary) and this would void any statically initialized data.
You can get around that by persisting the static data somewhere if creating it is expensive, or avoid reloading the AppDomain, the Application Pool or the IIS server.
Update: Phil Haack just published a relevant blog entry here: http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx
Bye Bye App Domain
it does a better job at explaining the above. Notable, IIS will recycle it's worker process very 29 hours at minimum and shared hosters will recycle AppDomain much more often (perhaps in 20 minutes of idle time)
So tell ASP.NET, “Hey, I’m working here!”
outlines techniques you can apply to get notified of an AppDomain take down - you could use this to get your Singleton instance behaving 'correctly'
Recommendation
I suggest you read it :)
static classes are initialized once per AppDomain.
If IIS recycles your AppDomain, everything will re-initialize.
I'm using Entity Framework 4.0 behind WCF services. My problem is that the memory used by the programm is growing a lot(start à 200Mo, and I stopped it at ~1.1Go.
How can I manage the cache? I mean, I've two datacontext, one of them is never used to read data, so can I disable the cache?
And for the other, can I specify the amount of space it cans use? Is there a way to monitor these resources? Is there a way to use less resources?
Thank you!
First of all you should not use shared contexts. Create new context for each WCF request and dispose context before you end your operation processing! If you need some data caching do it outside of EF. EF itself is not supposed to be used as cache and there is no control of this behavior.
If you host your service in IIS you can configure AppPool recycling by specifying Private Memory Limit in advanced settings of the AppPool. But it will simply kill everything running in that AppPool.
What may be happening is that each call is creating a new context. Which remains in memory untill the connection timesout and the Garbage collection removes it.
Are you not disposing of the datacontext each time you use it?
Are you closing your connections from the client?
Are you using per call session mode?
After posting this question:
How to lock on an integer in C#?
Many of the answers made me feel that I'm a 'sinner' for using lock in my web apps. I never thought this is a problem (if used wisely), what about you? Do you ever use it in your web applications?
I don't see how a web application can be written without locking, for example if you want to load some data from a database and you want to be sure that no other thread will load it (also for singletons), normally you use locking, for example:
private _locker = new object();
private YourClass[] _data;
public YourClass[] Data
{
get
{
if(_data == null)
{
lock( _locker)
{
// get your data
_data = GetYourData();
}
}
return _data;
}
}
Is there a problem with this?!
Edit:
Please note that I'm referring to a single server scenario here, for a server farm you need some distributed locking mechanism, but you don't expect every site you create to get millions of hits in a couple of weeks, do you? What if you need locking, should you create your site with that distributed locking, isn't that too much for an application which you have no idea whether it will ever need to be scaled or not? Besides computers have gotten really fast these days, one server can handle tons of traffic and this has been proven so many times, some examples are plentyoffish.com and this very site you're using right now, do some googling and I'm sure you'll come across so many others.
If you use a lock to try to control access to a remote resource (e.g. something from the database) then you'll have problems when you try to scale to more servers.
If you just want to have an AppDomain-specific lock (e.g. for a cache) then it makes perfect sense.
I disagree with your implied assertion that web applications can't be written without locking (at the web server level) though. It really depends on the application - usually database contention is handled at the database rather than the web server, precisely so that you can have multiple machines in your web tier.
For singletons it makes a certain amount of sense, but I rarely use singletons anyway...
Yes, you need to check for the data once more. Known as a double check lock. http://en.wikipedia.org/wiki/Double_checked_locking_pattern
Theoretically, a second thread could get past your first null check before your lock is created.
if(_data == null)
{
lock( _locker)
{
if (_data == null) {
// get your data
_data = GetYourData();
}
}
}
Bad idea to do this in a web app unless you really, really know what you're doing.
I would look into Upgradeable Locks http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.enterupgradeablereadlock.aspx
I don't know how you do data-access, but I've never found it needed to lock the database for one request only. I'm not sure, but I could imagine you'd try to solve certain problems with a Microsoft Access database, but thats just because it's not a good database system to use for a website (or just anything which leaves your local desktop).
Locking a local contested resource at some point within a request is fine (although rare). Locking a request and trying to hold the lock across several requests is not really going to work too well. Even if you can get it to work in a single server environment if you ever have to scale to a multi-server environment then it's just not going to work the way you expect.
The remote resource that you try to access should be in charge of the locking. As someone already pointed out, locks are process-wide, and as soon as you scale up your locks will just fail to work.
Databases also should do all the locking you need. It's one of the main requirements for a DBMS: data integrity.
I've never needed to use any synchronization mechanism on any of my webapps. Unless you're dealing with say, a raw XML file that multiple sessions are changing, I can't see the need for it. Like most people here have said - your database will take care of that for you. Updates, queries, what have you, database systems (at least ones you are likely to use with ASP.NET) take care of synchronization for you.
At the moment I am working on a project admin application in C# 3.5 on ASP.net. In order to reduce hits to the database, I'm caching a lot of information using static variables. For example, a list of users is kept in memory in a static class. The class reads in all the information from the database on startup, and will update the database whenever changes are made, but it never needs to read from the datebase.
The class pings other webservers (if they exist) with updated information at the same time as a write to the database. The pinging mechanism is a Windows service to which the cache object registers using a random available port. It is used for other things as well.
The amount of data isn't all that great. At the moment I'm using it just to cache the users (password hashes, permissions, name, email etc.) It just saves a pile of calls being made to the database.
I was wondering if there are any pitfalls to this method and/or if there are better ways to cache the data?
A pitfall: A static field is scoped per app domain, and increased load will make the server generate more app domains in the pool. This is not necessarily a problem if you only read from the statics, but you will get duplicate data in memory, and you will get a hit every time an app domain is created or recycled.
Better to use the Cache object - it's intended for things like this.
Edit: Turns out I was wrong about AppDomains (as pointed out in comments) - more instances of the Application will be generated under load, but they will all run in the same AppDomain. (But you should still use the Cache object!)
As long as you can expect that the cache will never grow to a size greater than the amount of available memory, it's fine. Also, be sure that there will only be one instance of this application per database, or the caches in the different instances of the app could "fall out of sync."
Where I work, we have a homegrown O/RM, and we do something similar to what you're doing with certain tables which are not expected to grow or change much. So, what you're doing is not unprecedented, and in fact in our system, is tried and true.
Another Pitfall you must consider is thread safety. All of your application requests are running in the same AppDomain but may come on different threads. Accessing a static variable must account for it being accessed from multiple threads. Probably a bit more overhead than you are looking for. Cache object is better for this purpose.
Hmmm... The "classic" method would be the application cache, but provided you never update the static variables, or understand the locking issues if you do, and you understand that they can disappear at anytime with an appdomain restart then I don't really see the harm in using a static.
I suggest you look into ways of having a distributed cache for your app. You can take a look at NCache or indeXus.Net
The reason I suggested that is because you rolled your own ad-hoc way of updating information that you're caching. Static variables/references are fine but they don't update/refresh (so you'll have to handle aging on your own) and you seem to have a distributed setup.