/// <summary> /// Creates sessions concurrently and stores a random binary blob in each session. This /// method then waits for all the sessions to expire and verifies that each session has in /// fact been removed from the provider and the provider's memory cache. It also takes a /// snapshot of the memory usage pre session creation, post session creation and post /// session expiration. This method will fail is any session still exists in the provider /// or there was excessive memory usage. /// </summary> /// <param name="provider">The MongoDB provider to use for the test.</param> /// <param name="numberOfSessions">The number of sessions to create concurrently.</param> /// <param name="sessionSizeInMegabytes">The number of MB of buffer to create and store in each session.</param> private void CreateConcurrentSessionObjects(MongoDBSessionStateProvider provider, int numberOfSessions, byte sessionSizeInMegabytes) { var sessions = new System.Collections.Generic.SynchronizedCollection<string>(); double initialWorkingSet, postSessionCreationWorkingSet, postSessionExpirationWorkingSet; var currentProcess = System.Diagnostics.Process.GetCurrentProcess(); initialWorkingSet = (currentProcess.WorkingSet64 / 1024.0 / 1000.0); int sessionSize = (sessionSizeInMegabytes * 1024 * 1024); var result = Parallel.For(0, numberOfSessions, idx => { System.Threading.Thread.Sleep(50); // Give a little wiggle room HttpRequest request = null; HttpResponse response = null; HttpContext context = GetContext(out request, out response); string sessionId = _SessionIdManager.CreateSessionID(context); sessions.Add(sessionId); byte[] dummyData = new byte[sessionSize]; (new Random()).NextBytes(dummyData); var dataStore = provider.CreateNewStoreData(context, (_TimeoutInSeconds / 60)); dataStore.Items["Data"] = dummyData; provider.SetAndReleaseItemExclusive(context, sessionId, dataStore, null, true); TestContext.WriteLine("Created session {0} with dummy data", sessionId); }); while (!result.IsCompleted) { System.Threading.Thread.Sleep(1000); } GC.Collect(); currentProcess.Refresh(); postSessionCreationWorkingSet = (currentProcess.WorkingSet64 / 1024.0 / 1000.0); var counter = _TimeoutInSeconds + 60; TestContext.WriteLine("Waiting {0} seconds for session expiration...", counter); while (counter > 0) { System.Threading.Thread.Sleep(1000); counter--; } TestContext.WriteLine("Checking Sessions in store and cache..."); var sessionIds = sessions.ToArray(); result = Parallel.ForEach<string>(sessionIds, sessionId => { HttpRequest request = null; HttpResponse response = null; HttpContext context = GetContext(out request, out response); bool locked; TimeSpan lockAge; object lockId; System.Web.SessionState.SessionStateActions actions; var storeData = provider.GetItem(context, sessionId, out locked, out lockAge, out lockId, out actions); Assert.IsNull(storeData); // Now check the cache! ISessionStateData sessionStateData; bool existsInCache = CheckSessionExistsInCache(provider, sessionId, out sessionStateData); if (existsInCache || sessionStateData != null) { TestContext.WriteLine("Session {0} still exists in cache!", sessionId); } else { sessions.Remove(sessionId); } }); while (!result.IsCompleted) { System.Threading.Thread.Sleep(1000); } GC.Collect(); GC.WaitForPendingFinalizers(); currentProcess.Refresh(); postSessionExpirationWorkingSet = (currentProcess.WorkingSet64 / 1024.0 / 1000.0); TestContext.WriteLine("Memory Usage: Initial = {0}MB, PostSessionCreation = {1}MB, PostSessionExpiration = {2}MB", initialWorkingSet, postSessionCreationWorkingSet, postSessionExpirationWorkingSet); TestContext.WriteLine("After expiration, session count = {0}", sessions.Count); currentProcess.Dispose(); double memoryDifference = postSessionExpirationWorkingSet - initialWorkingSet; TestContext.WriteLine("Memory Difference -> {0}MB", memoryDifference); bool isMemoryExhausted = (memoryDifference > 20); // This should be based on the buffer size and number of sessions if (sessions.Count != 0) { Assert.Fail("{0} Sessions still exist in memory. The memory has grown from {1}MB to {2}MB", sessions.Count, initialWorkingSet, postSessionExpirationWorkingSet); } if (isMemoryExhausted) { Assert.Fail("Excessive Memory Consumption. Memory has grown by {0}MB", memoryDifference); } }
/// <summary> /// Creates sessions concurrently and stores a random binary blob in each session. This /// method then waits for all the sessions to expire and verifies that each session has in /// fact been removed from the provider and the provider's memory cache. It also takes a /// snapshot of the memory usage pre session creation, post session creation and post /// session expiration. This method will fail is any session still exists in the provider /// or there was excessive memory usage. /// </summary> /// <param name="provider">The MongoDB provider to use for the test.</param> /// <param name="numberOfSessions">The number of sessions to create concurrently.</param> /// <param name="sessionSizeInMegabytes">The number of MB of buffer to create and store in each session.</param> private void CreateConcurrentSessionObjects(MongoDBSessionStateProvider provider, int numberOfSessions, byte sessionSizeInMegabytes) { var sessions = new System.Collections.Generic.SynchronizedCollection <string>(); double initialWorkingSet, postSessionCreationWorkingSet, postSessionExpirationWorkingSet; var currentProcess = System.Diagnostics.Process.GetCurrentProcess(); initialWorkingSet = (currentProcess.WorkingSet64 / 1024.0 / 1000.0); int sessionSize = (sessionSizeInMegabytes * 1024 * 1024); var result = Parallel.For(0, numberOfSessions, idx => { System.Threading.Thread.Sleep(50); // Give a little wiggle room HttpRequest request = null; HttpResponse response = null; HttpContext context = GetContext(out request, out response); string sessionId = _SessionIdManager.CreateSessionID(context); sessions.Add(sessionId); byte[] dummyData = new byte[sessionSize]; (new Random()).NextBytes(dummyData); var dataStore = provider.CreateNewStoreData(context, (_TimeoutInSeconds / 60)); dataStore.Items["Data"] = dummyData; provider.SetAndReleaseItemExclusive(context, sessionId, dataStore, null, true); TestContext.WriteLine("Created session {0} with dummy data", sessionId); }); while (!result.IsCompleted) { System.Threading.Thread.Sleep(1000); } GC.Collect(); currentProcess.Refresh(); postSessionCreationWorkingSet = (currentProcess.WorkingSet64 / 1024.0 / 1000.0); var counter = _TimeoutInSeconds + 60; TestContext.WriteLine("Waiting {0} seconds for session expiration...", counter); while (counter > 0) { System.Threading.Thread.Sleep(1000); counter--; } TestContext.WriteLine("Checking Sessions in store and cache..."); var sessionIds = sessions.ToArray(); result = Parallel.ForEach <string>(sessionIds, sessionId => { HttpRequest request = null; HttpResponse response = null; HttpContext context = GetContext(out request, out response); bool locked; TimeSpan lockAge; object lockId; System.Web.SessionState.SessionStateActions actions; var storeData = provider.GetItem(context, sessionId, out locked, out lockAge, out lockId, out actions); Assert.IsNull(storeData); // Now check the cache! ISessionStateData sessionStateData; bool existsInCache = CheckSessionExistsInCache(provider, sessionId, out sessionStateData); if (existsInCache || sessionStateData != null) { TestContext.WriteLine("Session {0} still exists in cache!", sessionId); } else { sessions.Remove(sessionId); } }); while (!result.IsCompleted) { System.Threading.Thread.Sleep(1000); } GC.Collect(); GC.WaitForPendingFinalizers(); currentProcess.Refresh(); postSessionExpirationWorkingSet = (currentProcess.WorkingSet64 / 1024.0 / 1000.0); TestContext.WriteLine("Memory Usage: Initial = {0}MB, PostSessionCreation = {1}MB, PostSessionExpiration = {2}MB", initialWorkingSet, postSessionCreationWorkingSet, postSessionExpirationWorkingSet); TestContext.WriteLine("After expiration, session count = {0}", sessions.Count); currentProcess.Dispose(); double memoryDifference = postSessionExpirationWorkingSet - initialWorkingSet; TestContext.WriteLine("Memory Difference -> {0}MB", memoryDifference); bool isMemoryExhausted = (memoryDifference > 20); // This should be based on the buffer size and number of sessions if (sessions.Count != 0) { Assert.Fail("{0} Sessions still exist in memory. The memory has grown from {1}MB to {2}MB", sessions.Count, initialWorkingSet, postSessionExpirationWorkingSet); } if (isMemoryExhausted) { Assert.Fail("Excessive Memory Consumption. Memory has grown by {0}MB", memoryDifference); } }