[.net programming language only]

Performance programming for WebSphere eXtreme Scale Client for .NET

[Version 8.6.0.4 and later]You must consider the effects that the .NET APIs have on the performance of your .NET application. The management of the data grid, map objects, and threads also influences application performance.

IGridMapPessimisticAutoTx API versus IGridMapPessimisticTx API

When you are using only Get or GetAll methods to retrieve data from the grid, the IGridMapPessimisticAutoTx.Get and IGridMapPessimisticAutoTx.GetAll methods are faster than the counterpart IGridMapPessimisticTx methods. This performance increase is because the shared lock is automatically freed during the IGridMapPessimisticAutoTx API Get and GetAll method calls. In contrast, the shared lock that is set by the IGridMapPessimisticTx API Get and GetAll methods is not freed until the Commit method call, resulting in another client/server request and response.
IGridMapPessimisticAutoTx<object,object> autoTxMap = 
	grid.GetGridMapPessimisticAutoTx<object,object>("Map");
IGridMapPessimisticTx<object,object> manualTxMap = 
	grid.GetGridMapPessimisticTx<object,object>("Map");                

// 1 remote grid access        
object autoVal = autoTxMap.Get(key);

// 2 remote grid accesses
manualTxMap.Transaction.Begin();
object manualVal = manualTxMap.Get(key); // first remote grid access to get and lock item
manualTxMap.Transaction.Commit();    	     // second remote grid access to release the shared lock
For more information about locking behavior, see Configuring and implementing locking in .NET applications.

Batch APIs

WebSphere eXtreme Scale Client for .NET provides a matching batch API for each API that operates on a single data grid item.  Some of these batch APIs result in a single request that is sent to the data grid. However, a few other batch APIs exist that result in multiple requests to be sent to the data grid.  Limit the use of these convenience APIs when you are optimizing the .NET application for performance. The following WebSphere eXtreme Scale Client for .NET batch APIs result in one data grid request no matter how many items are in the batch list:
  • IGridMapPessimisticAutoTx.GetAll, IGridMapPessimisticTx.GetAll
  • IGridMapPessimisticAutoTx.InvalidateAll, IGridMapPessimisticTx.InvalidateAll
  • IGridMapPessimisticAutoTx.PutAll, IGridMapPessimisticTx.PutAll
  • IGridMapPessimisticAutoTx.RemoveAll, IGridMapPessimisticTx.RemoveAll
  • IGridMapPessimisticTx.LockAll
  • IGridMapPessimisticTx.GetAndLockAll
The following WebSphere eXtreme Scale Client for .NET batch APIs are convenience APIs that result in data grid requests, where one API is listed for each item in the batch list:
  • IGridMapPessimisticAutoTx.ContainsKeyAll, IGridMapPessimisticTx.ContainsKeyAll
  • IGridMapPessimisticAutoTx.AddAll, IGridMapPessimisticTx.AddAll
  • IGridMapPessimisticAutoTx.ReplaceAll, IGridMapPessimisticTx.ReplaceAll
  • IGridMapPessimisticAutoTx.TouchAll, IGridMapPessimisticTx.TouchAll

Pooling data grid and map objects

.NET application processor and memory usage increase when you instantiate IGrid, IGridMapPessimisticAutoTx, and IGridMapPessimisticTx objects.  Where possible, maintain the minimum number of these instances.  Grid objects are thread safe. A single instance can be shared across all threads in the process.  Map objects, such as IGridMapPessimisticAutoTx and IGridMapPessimisticTx objects, are not thread safe, so each concurrent thread requires a separate map object instance.  If your .NET application accesses the data grid from many different threads, maintain a thread-accessible pool of map object instances. This pool prevents the constant recreation of map instances.  The following code sample shows a map instance pool implementation:

using System;
using System.Collections.Concurrent;
using System.Threading;
using IBM.WebSphere.Caching; 
using IBM.WebSphere.Caching.Map;  
namespace NetClientPooledMapExample 
{     
	class Program     
	{         
		private static ConcurrentQueue<IGridMapPessimisticAutoTx<string, string>> autoTxMapQ = 
			new ConcurrentQueue<IGridMapPessimisticAutoTx<string, string>>();         
		private static IGridManager gm = null;         
		private static ICatalogDomainInfo cdi = null;         
		private static IClientConnectionContext ctx = null;         
		private static IGrid g = null;          
		static void Main(string[] args)         
		{             
			int numThreads = 50;    // Number of concurrent threads accessing the same map              
			try             
			{                 
				gm = GridManagerFactory.GetGridManager();
				cdi = gm.CatalogDomainManager.CreateCatalogDomainInfo("localhost:2809");                 
				ctx = gm.Connect(cdi);
				g = gm.GetGrid(ctx, "Grid");                  
				Thread[] tArray = new Thread[numThreads];                 
				for (int i = 0; i < numThreads; i++)                 
				{                     
					tArray[i] = new Thread(PopulateGrid);                     
					tArray[i].Start();                 
				}                  
				for (int i = 0; i < numThreads; i++)                 
				{                     
					tArray[i].Join();                 
				}             
			}             
			catch (Exception e)          
			{                 
				Console.WriteLine("Encountered exception during grid access: {0}", e);             
			}             
			finally             
			{                 
				if (gm != null &amp;&amp; ctx != null)                 
				{                     
					gm.Disconnect(ctx);                 
				}             
			}         
		}          
		private static void PopulateGrid()         
		{             
			IGridMapPessimisticAutoTx<string, string> gridMapAuto = null;             
			string key = "Key_" + Thread.CurrentThread.ManagedThreadId;             
			string value = "Val_" + Thread.CurrentThread.ManagedThreadId;              
			try             
			{                 
				// Pull an available map off the queue                 
				gridMapAuto = GetAutoTxMap(g, "Map1");                  
				// Do some work with the map                 
				gridMapAuto.Put(key, value);                  
				Console.WriteLine("Thread {0} wrote key {1} with value {2}", 
					Thread.CurrentThread.ManagedThreadId, key, value);             
			}             
			catch (Exception e)             
			{                 
				Console.WriteLine("Encountered exception during map access: {0}", e);             
			}             
			finally             
			{                 
				// Release the map to the queue when done                
				ReleaseAutoTxMap(gridMapAuto);             
			}         
		}          
		private static IGridMapPessimisticAutoTx<string, string> GetAutoTxMap(IGrid grid, string mapName)         
		{             
			IGridMapPessimisticAutoTx<string, string> retmap = null;              
			if (!autoTxMapQ.TryDequeue(out retmap))             
			{                 
				// Create a new map if the queue is out of available maps                 
				retmap = grid.GetGridMapPessimisticAutoTx<string, string>(mapName);             
			}              
			return retmap;         
		}          
		private static void ReleaseAutoTxMap(IGridMapPessimisticAutoTx<string, string> map)         
		{             
			autoTxMapQ.Enqueue(map);         
		}      
	} 
} 

.NET ThreadPool management

WebSphere eXtreme Scale Client for .NET uses the .NET ThreadPool to obtain threads for reading responses from the data grid.  When the number of active ThreadPool threads exceeds the minimum level for the ThreadPool, the ThreadPool allocates new threads at a much slower rate. .NET 3.5 allocates two threads per second, which can significantly impact the performance of your .NET application. The .NET ThreadPool is shared across all threads that are in the same application domain. If a WebSphere eXtreme Scale Client for .NET application consumes many threads from the .NET ThreadPool, the WebSphere eXtreme Scale Client for .NET might not be able to quickly obtain a ThreadPool thread to process incoming data from the data grid. These threads might include asynchronous tasks, timers, or explicit work queueing.
Ensure your WebSphere eXtreme Scale Client for .NET application configures the .NET ThreadPool to avoid having the number of active thread pool threads exceed the ThreadPool minimum levels.  The ThreadPool provides the following APIs for monitoring the ThreadPool configuration and active number of thread pool threads.