Thursday, February 28, 2008

indeXus.Net Shared Cache - 11 reasons why you should consider to use it!

indeXus.Net Shared Cache is high performance distributed and replication cache system build for .Net cache and enterprise application running in server farms.

indeXus.Net Shared Cache provides distributed replicated cache to minimize the load factor on deeper layers. It consists the usage of two or more servers in a farm. It's replicated all data within the cluster. The big plus is simple, you have all your cache nodes on all different servers. In case one of your servers get restarted, it will receive all items automatically from its parent. indeXus.Net Shared Cache uses 100% managed code which is written .Net C#.

Why you should consider to use indeXus.Net Shared Cache? There is no more efficient way to increase the scalable performance of applications then the use caching to unload deeper layers and you able to scale linear.

  1. We provide a wider range of caching - distributed and replicated caching. The experience we have done so far showed us that a lot of projects have a huge need of data integrity.
  2. We provide several cleanup models to purge the cache:
    a. Cache Item Priority
    b. LRU – Least Recent Used Item
    c. LFU – Least Frequently Used Item
    d. Time based
    e. BLF – Biggest Latency First
    f. LLF – Lowest Latency First
    g. Hybrid – Creating an index based on various item attributes such as: time in cache, Amount of requests, Size, Cache Life Time and some more.
  3. Configurable maximum cache size and the load factor when the system starts to purge cached items.
  4. With the upcoming release we gone provide Key Cache Dependency (it can be that in future we will also support SQL and File Dependency)
  5. With the upcoming release we gone provide bulk operations
  6. We use a binary format which has an overload payload of 36 bytes per Message.
  7. Simple server and client configuration with custom provider sections
  8. We use internally a custom thread pool which is configurable.
  9. We provide a small management console with some basic information about cache nodes.
  10. We provide detailed statistic information for client and server:
    a. Client Side:
    i. Amount of objects which are added / received / removed
    ii. Network usage
    iii. Successful and failed actions
    iv. Item Hit Rate
    b. Server Side per Node (all servers are aggregated)
    i. Amount of items available
    ii. Size of all items
    iii. A list with the top 20 keys based on hits
  11. Last but not least: it’s absolutely free and open source!

Friday, February 22, 2008

consider to use local variables in some cases

who said performance == performance?

If you visited this blog already you now that indeXus.Net Shared Cache Server part is developed now as an asynchronous server and not a thread per client model. One of the very central server methods is to receive data. For this we have the following one:
private void ReadCallback(IAsyncResult ar)

{
// some code int read = handler.EndReceive(ar);
if (read > 0)
{
Monitor.Enter(state);
for (int i = 0; i <>
{
state.DataBuffer.Add(state.Buffer[i]);
}
Monitor.Exit(state);
// .
// .
// .
// .
// some more code
}

The above loop is developed straightforward, take the received buffer and concatenate it to the actual List until you received all needed data from the client. Well done - works great - but its slow like hell !!!!

Lets do some re-factoring and save up to 2.5 sec. which is actually for the tested use case 27,2% of end-to-end time:
adding 1000 objects with approx. 100kb toke 10,251 sec. in average (100 runs) - after this change we ended up with 7,456 sec for the same case in average for also 100 runs.

private void ReadCallback(IAsyncResult ar)
{
// some code
int read = handler.EndReceive(ar);
if (read > 0)
{
Monitor.Enter(state);
// save 2.5 seconds while i copy data to local variables and i do not access the property
byte[] localBuffer = new byte[state.DataBuffer.Count];
localBuffer = state.Buffer;
List localList = new List();
localList.AddRange(state.DataBuffer);
// copy all buffer data into DataBuffer which is list and contains all data until we get the whole message.
for (int i = 0; i < read; i++)
{
localList.Add(localBuffer[i]);
}
state.DataBuffer = localList;
Monitor.Exit(state);
// .
// .
// .
// .
// some more code
}

My conclusion is simple, keep attention were do you access object properties. I'm pretty sure that in 99% of all use cases it would not matter but here, its an amazing result for today's session.

Tuesday, February 12, 2008

indeXus.Net Shared Cache pre-release 2.0.0.140 is available

indeXus.Net SharedCache is a high-performance, distributed caching system. Although application-neutral, it's commonly used to speed up dynamic Web applications by alleviating database load.

This release includes many new features and enhancements like server connection pooling, more efficient network usage, and much smaller protocol overload. We could increase performance in almost every test-case.

Most of the new developments have been based on community feedback; enhancements which have been requested over the last few weeks have all been logged and incorporated in the new release.

The use of 100% managed code provides performance and ensuring optimal reliability in the most demanding environments. The full Visual Studio.Net solution is available for download.

Latest release is available and ready to download at the following link:
https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=SharedCache&ReleaseId=10166

Shared Cache is an open source project hosted on http://www.codeplex.com/SharedCache and it’s licensed under “GNU Library General Public License (LGPL)”

ADO.Net - Performance Matters

Today I found 2 very intersting blog postings for ADO.Net and Linq:

http://blogs.msdn.com/adonet/archive/2008/02/11/exploring-the-performance-of-the-ado-net-entity-framework-part-1.aspx

http://blogs.msdn.com/adonet/archive/2008/02/11/exploring-the-performance-of-the-ado-net-entity-framework-part-2.aspx

Monday, February 11, 2008

Shared Cache - compare results between version 1.0.2.134 and 2.0.0.140 and upper

As already mention in some previous posts in my Blog I have re-written the whole client / server logic which runs under the hood. Checkout the following post for more information: http://netrsc.blogspot.com/2008/02/threaded-asynchronous-tcp-server-with.html

The client application which is delivered with indeXus.Net Shared Cache contains some Speed test options were I'm able to compare between them now. All in all i have to mention the server is getting quite faster then it was before and for sure more robust. Never thought such a async approach would make that much difference. All in all there are some key changes:
  • Server is running as async TCP Server with a custom Threadpool
  • Network traffic decreased dramatically between, especially upon server echos
  • We take now full advantage of object pooling, so each action from the client in the test application gone use only 1 single "new Socket()" instead of several thousands.
People who have not seen the menu here is a stripdown of the different options.

Speed Tests [200 / 300 range]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
200 - Add 10 objects with the size approx. of 1kb.
210 - Add 100 objects with the size approx. of 1kb.
220 - Add 1000 objects with the size approx. of 1kb.
230 - Add 10000 objects with the size approx. of 1kb.
240 - Add 10 objects with the size approx. of 100kb.
250 - Add 100 objects with the size approx. of 100kb.
260 - Add 1000 objects with the size approx. of 100kb.
270 - Add 10000 objects with the size approx. of 100kb.
280 - Add 10 objects with the size approx. of 1MB.
290 - Add 100 objects with the size approx. of 1MB.
300 - Add 1000 objects with the size approx. of 1MB.
310 - Add 1500 objects with the size approx. of 1MB.
Just different options which makes it easy to compare with different approaches.
Below we see a table were in almoast every case we could increase the performance. Why we have the 3 marked Get operations which are slower I haven't figured out yet but I promiss I will do so. In generall we can say we have a performance increasment and system & network resource decreasment. With the upcoming version I have implemented some performance counters which will make life easier to compare results between installations.

As we can see we have for the case 100 client calls with 1 kb only better results then before.

As bigger the message (payload) which has to be transferred to the server, as better the results are getting. I was wondering if I have done a calculation mistake but I re-run the whole test 3 times.
It would be very intersting if people would post theire results to compare.

Sunday, February 10, 2008

Threaded Asynchronous Tcp Server with a blocking Client

I don't know now how many prototypes I have written in the past few weeks to verify which approach would fit best to scale and be most performance for indeXus.Net Shared Cache. To write a Client / Server Architecture which mostly will be N:M connectivity was not that easy as I thought in beginning.

Honestly I believe I have study every single C# sample I found on the common search engines and arrived to the point where I started to adapt the samples. Unfortunately 99% of founded samples are showing how to pass a string from the client to the server beside one blog which has written down a lot of theory and some very nice diagrams without to come up with code. I only can recommend you to read this blog up and down before you write even one single line of code: http://www.coversant.net/Coversant/Blogs/tabid/88/EntryID/10/Default.aspx. There are some very smart people around they have done great work.

After a while of research, I get to koders.com where I found a strip-down version of their product.

Another very useful page with a lot of sample code around .net is Mike Woodrings's .net Sample Page which contains a bunch of great examples for different domains.

I think I have tried any way to use Sockets now:


  • Blocked Sockets
  • Unblocked Sockets
  • Poll Sockets
  • Select

Every prototype I have done so far had his advantages and disadvantages. In the end of this post I will provide 2 downloads:

  • prototype with poll sockets on client and server
  • protptype with block sockets on client side and async server handling
Once I get comfortable with all the different Issues which come across the write the server part I decided to use Asad Aziz - Asynchronous Server Socket using C# Sample as my base for the server. Its very easy written but my knowledge on this issue was limited until I started to work on it quite intensive and I think I learned every day at least 10 new things :-)

Lets dive into different key parts of the client and the server. An additional issue I would like to mention here is that the whole code is 100% managed.

We gone start first with the server. As already mention the server is working Asynchronous which means we have to handle with IAsyncResult. Upon Server start we begin run the server within a different thread and the client cleanup will be handled by a TimerCallback to purge disconnected clients in case they not removed before upon disconnection.

ThreadStart serverListener = new ThreadStart(this.StartListening);
serverThread[0] = new Thread(serverListener);
serverThread[0].IsBackground = true;
serverThread[0].Start();
TimerCallback timerDelegate = new TimerCallback(this.CheckSockets);
this.lostTimer = new Timer(timerDelegate, null, SharedCacheTcpServer.timerTimeout, SharedCacheTcpServer.timeoutMinutes);

Since we have started now the serverListener we Bind the server IPEndPoint to the requested ip and port and start to listen for connections from clients. Once a connection is received it only will be destroyed in one of the following 2 cases:

  1. The Socket has not been used for a certain amount of time
  2. Client Socket get disconnected.

With this we avoid to much Server resources. As started we will use a ManualResetEvent to accept only one by one client. I have commented this part for testing purposes and the server started to throw memory exceptions. So keep it simple in the meaning, only start a new BeginAccept once you finished to move the client into AccecptCallback.

private void AccecptCallback(IAsyncResult ar)
{
// signal main thread to continue
this.allDone.Set();
Socket clientListener = ar.AsyncState as Socket;
if (clientListener != null)
{
Socket handler = clientListener.EndAccept(ar);
Console.WriteLine(@"Connected by client: {0}", handler.RemoteEndPoint);
StateObject state = new StateObject();
state.WorkSocket = handler;
state.AliveTimeStamp = DateTime.Now;

... and some more code ..

once you have done all setup for you StateObject (this is the object which contains all different data between the calls) we able to call BeginReceive. SharedCache Protocol between client and server keep simple: [messageLength][message] so if we are not able to get the whole message at once we have to call several times BeginReceive until we have received everything from the client and we able to run the custom stuff on the server.

Once we done with our reading we can start to process received package and process with it. To keep server resources (amount of threads) under control I decided to use Mike's Threadpool.


I think the 2 most important parts are within this message is to know that we need to read the header which indicates to message length and if we need to read more data for this message or do we can proceed it arrived data.

// check for header
if (state.ReadHeader) { .....


// check for message length -> TODO: how to check longer values as int count in list????
if (state.DataBuffer.ToArray().LongLength == state.MessageLength) { ...


as you can see there is even one open point since I use in my state object a List. I had some discussions with people on asp.net forums but I believe i can life right now with this
int.MaxValue as maximal message length ;-)


the next key position in above code print screen is that we use at this place again handler.BeginReceive() since we want to client connection keep opened as long as possible. Some previous tests had shown me while i open and close 1000 Sockets the time reduction to use always the same is more then 50%. Before we can post the request into ThreadPool we need to remove the Range of our message size [8 bytes] that's why we do: state.DataBuffer.RemoveRange(0,8); once we have posted it to the threadpool to pool handles the message sending the Echo to the waiting client.
HandleClientMessage is the place which is called after you get the free Thread from the ThreadPool - here you can manage your Server side stuff and once you done you can send it back to the Client. If you work within Winform environment a more event driven design would be correct but for sharedcache this would not be correct since the client is waiting for the server response.



in the above example we do nothing else then to set an Attribute of the object IndexusMessage to Successful.
The response from the server needs to be prepared, then also the client waits for the same struct [message length][message data]. Therefore we call UtilByte.CreateMessageHeader(with the msg.GetBytes() which returns a byte array) and we combine both values to 1 single byte array. since this is done we can free up resources and set the actual messageLength on the state so we know how much data we need to send to the client which is not less important.



Within the Send() method we start the async call: socket.BeginSend() or if we do not have anything to send back (this case does not happen here) we reset all state data and start to receive again without to destroy the state and the socket which is included in the state. The
same idea happens within the SendCallback() we call BeginSend() as long we have data to send and once we sent everything to the client we reset the state and start to receive again with socket.BeginReceive().

These are all important parts on the server side, I will wrap up the client in a different post within the next few days.

The 2 best code-solution I have found on the web are the following 2 links:

http://www.codeproject.com/KB/IP/Generic_TCP_IP_server.aspx
http://www.codeproject.com/KB/IP/AsyncSocketServerandClien.aspx

Both of them could not handle the case I needed so I hope people can use the Prototypes in this or another way. It would be great if you let me know if you are using them. So here are the downloads:


I really would like to say "thank you very much" to all contributors of the following articles and coding samples:

Monday, February 04, 2008

IPAddress.Parse("127.0.0.1") vs. Dns.GetHostEntry("127.0.0.1")

Did you ever come to the point where you had to get several times an System.Net.IPEndPoint? The constructor takes an IPAddress and a specific Port which you select... Now guess what... if you handle with known IPAddresses within your Network you should not use Dns.GetHostEntry just because its very very very slow, as long you know the IP Address ;-). In almoast every online example I have seen so far online I always have seen usage of Dns.GetHostEntry.... people thats so wrong in my point of view and after my measurment - correct me if I'm wrong but I love to measure :-) !

Once you deal with other issues maybe there is no other way but since a while I grab the WWW around tcp and udp socket issues and one of this issues is to give a solution with object pooling while a unexpected load arrives on a web-server and it needs to open more then the expected amount of sockets to its server. So here we can have e.g. instead of the normal 20 open connections fast 120 - 150 additional sockets. This additional instances are there for a certain time amount and afterwards they get closed again but even then. If you need to be fast, then every millisecond counts since we are talking about scalability.

In general I gone compare about the following code lines:

IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 48888);

and

IPEndPoint ep = new IPEndPoint(Dns.GetHostEntry("127.0.0.1").AddressList[0], 48888);

I have done a small test to measure if this two options are really have such a hugh difference:

Run no. 1 with: 127.0.0.1

IP-Address Parse average: 6 milliseconds
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8

DNS GetHostEntry average: 125 milliseconds
56, 57, 66, 67, 68, 70, 70, 71, 71, 72, 78, 78, 79, 80, 81, 81, 82, 82, 83, 85, 86, 87, 88, 88, 91, 95, 96, 96, 97, 97, 98, 99, 99, 101, 102, 103, 104, 106, 110, 111, 113, 114, 116, 117, 118, 119, 122, 127, 128, 129, 130, 130, 131, 133, 143, 144, 144, 145, 145, 146, 146, 147, 148, 148, 149, 150, 155, 155, 156, 157, 158, 158, 159, 159, 160, 161, 161, 162, 162, 163, 164, 165, 166, 167, 169, 169, 170, 171, 172, 173, 173, 174, 175, 175, 176, 177, 177, 178, 178, 179,


Run no. 2 with: 192.168.xxx.21

IP-Address Parse average: 11 milliseconds
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12
DNS GetHostEntry average: 168 milliseconds
95, 99, 100, 101, 105, 106, 106, 109, 110, 112, 121, 121, 122, 123, 124, 125, 126, 132, 133, 134, 136, 137, 139, 141, 141, 143, 144, 146, 148, 153, 153, 155, 155, 156, 157, 157, 160, 163, 163, 164, 165, 166, 168, 168, 169, 170, 170, 173, 177, 177, 178, 179, 180, 180, 181, 181, 182, 182, 183, 184, 184, 185, 186, 186, 187, 187, 188, 191, 192, 193, 193, 194, 195, 195, 196, 197, 197, 198, 199, 200, 201, 202, 203, 203, 204, 205, 206, 206, 207, 207, 208, 208, 209, 210, 211, 211, 215, 217, 218, 218,

incredible how much the difference is.

The formatted code is available over here: http://www.ronischuetz.com/code/IpParseVsDnsGetHostEntry.html
and the c# version you can get from here:
http://www.ronischuetz.com/code/IpParseVsDnsGetHostEntry.cs.txt

Friday, February 01, 2008

.net C# code helper serie

I have no clue how many times you are writing the same code but I will start to use the blog for several helper classes I'm using all the time again and again and again.


This series starts with the System Information Helper class. This class helps to provide System Information for Windows Environments. The parts of the class are the following onces:

  • Get .net framework information
  • Get Operating System
  • Get the name of the system machine
  • Get the current executing location
  • Get config files in executing location
  • Get the current user

The code can be dowloaded from the following location: http://www.ronischuetz.com/code/SysInfo.cs.txt or just have a look at the formatted version: http://www.ronischuetz.com/code/sysinfo.cs.html.

If you send me some additional parts I will extend the post.

Shared Cache - .Net Caching made easy

All information about Shared Cache is available here: http://www.sharedcache.com/. Its free and easy to use, we provide all sources at codeplex.

Facebook Badge