ASP.NET + thread-aware unmanaged API
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.
精彩评论