Showing posts with label memory. Show all posts
Showing posts with label memory. Show all posts

Sunday, June 22, 2008

Velocity vs MemCached vs Shared Cache

more and more people are asking me why gone have an additional distributed object caching system since even Microsoft started now a distributed / replicated caching system. I will try to answer this question in my personal point of view.

There are several reasons available, in comparison to MemCached we have a system which is written 100% in managed .net code and we started our first tries to run shared cache on Mono with a success (this version is currently not available - local development path - I will add more info about this in a different post) . Over the past few years MemCached approved itself over the biggest systems around the world and consider there is a great, active and helpful community behind it as long as people using it within Technologies like PHP, PHYTON and RUBI (and some more). Its quite clear (to me) they will use "only" MemCached and nothing else - nor Microsoft or Oracle will be able to create a solution for this communities.

At the time I started indeXus.Net Shared Cache there were nothing out there which was written 100% in .Net managed code, open source and FREE! There are several companies like Scaleout Software or Alachisoft they addressed a .Net solutions but the fact is as good they are - they cost money! In the meanwhile there are even starter kits available from various companies.

The first goal of Shared Cache was to give a solution for those who decide to use Microsoft .Net technology. The current status showed us that we able to compete in performance matters with MemCached.



Above comparison output I received from somebody else so I can't guarantee for it but on my environments results are quite similar.

What happens now since Microsoft announce it's Velocity project. I have contacted Microsoft Velocity Team with the question:

- Q:What kind of licensing will stay behind Velocity?

- A:The licencing terms have not yet been finalized. We hope to address it by CTP2.

Velocity's schedule based on the June's Tech-Ed 2008:



We hope Microsoft is going to implement the following requirements:

- No additional charge for Velocity
- 100 % managed Code
- They deploy at least pdb files
- Ability to run Velocity under MONO
- It will be at least that fast as Shared Cache and MemCached / Cacheman

I'm pretty sure most of above requirements they meet up until CTP 2 in October 2008.

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.

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:

Saturday, January 26, 2008

DUMPBIN - thats cool

get know of your assemblies with dumpbin

The Microsoft COFF Binary File Dumper (DUMPBIN.EXE) displays information about 32-bit Common Object File Format (COFF) binary files. You can use DUMPBIN to examine COFF object files, standard libraries of COFF objects, executable files, and dynamic-link libraries (DLLs).

http://support.microsoft.com/kb/177429

An interface has been developed for this nice tool: http://www.cheztabor.com/dumpbinGUI/index.htm

.Net CLR Memory Performance Monitoring

If you need to monitor you memory the usage of Perfmon is needed to start. There are also some shareware and MS CLR Profiler available but lets explain the basic's for the usage of Perfmon.

to start perfmon: start -> run: type: perfmon and the Performance SnapIn window appears.



the window starts with some default counters, usually you those are not the counters you will have to look on. Therefor you need to choose the right selection, which you do with right click -> add counters. Then you can select your requested counters as shown below:




Lets describe the different counters we have:

  • # Bytes in all Heaps: This counter is the sum of four other counters; Gen 0 Heap Size; Gen 1 Heap Size; Gen 2 Heap Size and the Large Object Heap Size. This counter indicates the current memory allocated in bytes on the GC Heaps.
  • # GC Handles: This counter displays the current number of GC Handles in use. GCHandles are handles to resources external to the CLR and the managed environment. Handles occupy small amounts of memory in the GCHeap but potentially expensive unmanaged resources.
  • # Gen 0 Collections: This counter displays the number of times the generation 0 objects (youngest; most recently allocated) are garbage collected (Gen 0 GC) since the start of the application. Gen 0 GC occurs when the available memory in generation 0 is not sufficient to satisfy an allocation request. This counter is incremented at the end of a Gen 0 GC. Higher generation GCs include all lower generation GCs. This counter is explicitly incremented when a higher generation (Gen 1 or Gen 2) GC occurs. _Global_ counter value is not accurate and should be ignored. This counter displays the last observed value.
  • # Gen 1 Collections: This counter displays the number of times the generation 1 objects are garbage collected since the start of the application. The counter is incremented at the end of a Gen 1 GC. Higher generation GCs include all lower generation GCs. This counter is explicitly incremented when a higher generation (Gen 2) GC occurs. _Global_ counter value is not accurate and should be ignored. This counter displays the last observed value.
  • # Gen 2 Collections: This counter displays the number of times the generation 2 objects (older) are garbage collected since the start of the application. The counter is incremented at the end of a Gen 2 GC (also called full GC). _Global_ counter value is not accurate and should be ignored. This counter displays the last observed value.
  • # Induced GC: This counter displays the peak number of times a garbage collection was performed because of an explicit call to GC.Collect. Its a good practice to let the GC tune the frequency of its collections.
  • # of Pinned Objects: This counter displays the number of pinned objects encountered in the last GC. This counter tracks the pinned objects only in the heaps that were garbage collected e.g. a Gen 0 GC would cause enumeration of pinned objects in the generation 0 heap only. A pinned object is one that the Garbage Collector cannot move in memory.
  • # of Sink Blocks in use: This counter displays the current number of sync blocks in use. Sync blocks are per-object data structures allocated for storing synchronization information. Sync blocks hold weak references to managed objects and need to be scanned by the Garbage Collector. Sync blocks are not limited to storing synchronization information and can also store COM interop metadata. This counter was designed to indicate performance problems with heavy use of synchronization primitives.
  • # Total committed Bytes: This counter displays the amount of virtual memory (in bytes) currently committed by the Garbage Collector. (Committed memory is the physical memory for which space has been reserved on the disk paging file).
  • # Total reserved Bytes: This counter displays the amount of virtual memory (in bytes) currently reserved by the Garbage Collector. (Reserved memory is the virtual memory space reserved for the application but no disk or main memory pages have been used.)
  • % Time in GC: % Time in GC is the percentage of elapsed time that was spent in performing a garbage collection (GC) since the last GC cycle. This counter is usually an indicator of the work done by the Garbage Collector on behalf of the application to collect and compact memory. This counter is updated only at the end of every GC and the counter value reflects the last observed value; its not an average.
  • Allocated Bytes/sec: This counter displays the rate of bytes per second allocated on the GC Heap. This counter is updated at the end of every GC; not at each allocation. This counter is not an average over time; it displays the difference between the values observed in the last two samples divided by the duration of the sample interval.
  • Finalization Survivors: This counter displays the number of garbage collected objects that survive a collection because they are waiting to be finalized. If these objects hold references to other objects then those objects also survive but are not counted by this counter; the "Promoted Finalization-Memory from Gen 0" and "Promoted Finalization-Memory from Gen 1" counters represent all the memory that survived due to finalization. This counter is not a cumulative counter; its updated at the end of every GC with count of the survivors during that particular GC only. This counter was designed to indicate the extra overhead that the application might incur because of finalization.
  • Gen 0 Heap Size: This counter displays the maximum bytes that can be allocated in generation 0 (Gen 0): its does not indicate the current number of bytes allocated in Gen 0. A Gen 0 GC is triggered when the allocations since the last GC exceed this size. The Gen 0 size is tuned by the Garbage Collector and can change during the execution of the application. At the end of a Gen 0 collection the size of the Gen 0 heap is infact 0 bytes; this counter displays the size (in bytes) of allocations that would trigger the next Gen 0 GC. This counter is updated at the end of a GC; its not updated on every allocation.
  • Gen 0 Promted Bytes/Sec: This counter displays the bytes per second that are promoted from generation 0 (youngest) to generation 1; objects that are promoted just because they are waiting to be finalized are not included in this counter. Memory is promoted when it survives a garbage collection. This counter was designed as an indicator of relatively long-lived objects being created per sec. This counter displays the difference between the values observed in the last two samples divided by the duration of the sample interval.
  • Gen 1 heap size: This counter displays the current number of bytes in generation 1 (Gen 1); this counter does not display the maximum size of Gen 1. Objects are not directly allocated in this generation; they are promoted from previous Gen 0 GCs. This counter is updated at the end of a GC; its not updated on every allocation.
  • Gen 1 Promted Bytes/Sec: This counter displays the bytes per second that are promoted from generation 1 to generation 2 (oldest); objects that are promoted just because they are waiting to be finalized are not included in this counter. Memory is promoted when it survives a garbage collection. Nothing is promoted from generation 2 since it is the oldest. This counter was designed as an indicator of very long-lived objects being created per sec. This counter displays the difference between the values observed in the last two samples divided by the duration of the sample interval.
  • Gen 2 heap size: This counter displays the current number of bytes in generation 2 (Gen 2). Objects are not directly allocated in this generation; they are promoted from Gen 1 during previous Gen 1 GCs. This counter is updated at the end of a GC; its not updated on every allocation.
  • Large Object Heap Size: This counter displays the current size of the Large Object Heap in bytes. Objects greater than 20 KBytes are treated as large objects by the Garbage Collector and are directly allocated in a special heap; they are not promoted through the generations. This counter is updated at the end of a GC; its not updated on every allocation.
  • Process ID: This counter displays the process ID of the CLR process instance being monitored.
  • Promted Finalization-Memory from Gen 0: This counter displays the bytes of memory that are promoted from generation 0 to generation 1 just because they are waiting to be finalized. This counter displays the value observed at the end of the last GC; its not a cumulative counter.
  • Promted Memory from Gen 0: This counter displays the bytes of memory that survive garbage collection (GC) and are promoted from generation 0 to generation 1; objects that are promoted just because they are waiting to be finalized are not included in this counter. This counter displays the value observed at the end of the last GC; its not a cumulative counter.
  • Promted Memory from Gen 1: This counter displays the bytes of memory that survive garbage collection (GC) and are promoted from generation 1 to generation 2; objects that are promoted just because they are waiting to be finalized are not included in this counter. This counter displays the value observed at the end of the last GC; its not a cumulative counter. This counter is reset to 0 if the last GC was a Gen 0 GC only.

GC.Collect - how it really works - .net Garbage Collection

The GC (Garbage Collection) in .Net is a Win32 process within HEAP which is initially created by the OS (Operation System) based on CLR request. This request add 2 segments of 16 MB each (16kb committed). One of them is allocated for the Gen0, Gen1 & Gen2 and the second segment is used for LOH (Large Object Heap). Objects greater than 20 KBytes are treated as large objects by the Garbage Collector and are directly allocated in a special heap

While we start to create small objects the first segment starts to grow. If we suppose that we keep all instantiated objects without ever releasing any instance until the segment gets full, the CLR ask OS for another segment of 16MB (16kb committed) and continues to allocate object space from that new segment which has been received by the operating system.

If we free up memory, lets suppose all allocated 32 MB, CLR leaves you still with a HEAP size of 32 MB even that nothing is committed. The GC still held all free space and will not return it to the OS until we use a memory pressure.

With the memory pressure the operating system sending a signal to the CLR to trim the working set and the CLR will return additional segments to OS.

The conclusion of it is simple, there is plenty of free memory and the operating system does not claim anything from running processes.

Friday, January 25, 2008

Performance average comparsion between State Server and indeXus.Net Shared Cache

Performance Environment and preconditions:
Client: MS Windows XP Prof, Intel Pentium D, 2.8GHz, 3.24 GB RAM
Server: MS Windows Server 2003, Enterprise Edition SP2, Intel Pentium D, 2.8GHz, 3.24 GB RAM
Iterations: 1000

Object Size: ~1kb
Debug Mode: True

Session State on same server:
In-Process: 225 requests / second
Out-Of-Process: 165 requests / second

Session State on remote server:
Out-Of-Process, 55 requests/second (-68%)

indeXus.Net Shared Cache same server:
add: 3s 128ms -> 319.6 req/sec
get: 3s 096ms -> 322.3 req/sec
remove: 2s 868ms -> 348.6 req/sec

indeXus.Net Shared Cache remote server:
add: 3s 425ms -> 291.9 req/sec
get: 3s 620ms -> 276.2 req/sec
remove: 3s 556ms -> 297.9 req/sec



original page:
http://www.codeplex.com/SharedCache/Wiki/View.aspx?title=Speed%20Test%20Results

additional comparsions will be added soon, also with sql server

Wednesday, December 26, 2007

indeXus.Net Shared Cache V1 is available

I finally have released the first version of indeXus.Net Shared Cache which is available at: http://www.sharedcache.com/.

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.

indeXus.Net SharedCache runs as a distributed windows service on every web and / or application server farm to cache data objects in memory out of process. Your stored objects can be accessed from any of your servers in your farm. It would be great if you help me to make it public through usage and blog entries. The release notes are available at the following location: https://www.codeplex.com/Release/ProjectReleases.aspx?ProjectName=SharedCache&ReleaseId=9424

for any queries about sharedcache please use the following email:
sharedcache [AT] indeXus [DOT] Net

Saturday, December 22, 2007

a simple und strightforward way to sort generic List

Sorting in general with generic list is quite easy if the developer knows how to do the sorting. With simple anonymous methods, as well the little known Comparsion delegate.

In one of my previous posts (caching cleanup strategy) I described a specific problem I have to solve for SharedCache, the .Net caching solution for distributed cache: http://www.sharedcache.com/ / http://www.codeplex.com/SharedCache

The following example here is just partly, the full code will be available within a few day's on CodePlex - upon my next hugh checkin .... people i'm a bit afraid to check it in sometimes it has so many new features ;-) - that i say as a person which preferres the way of: make small steps your reach your target faster!!!!

a simple sample class (a full formatted working class sample from my project):

   1:      public class Cleanup : IComparable<Cleanup>
   2:      {
   3:          string yourProperty = string.Empty;
   4:          public enum SortingOrder
   5:          {
   6:              /// <summary>
   7:              /// ascending sorting order
   8:              /// </summary>
   9:              Asc,
  10:              /// <summary>
  11:              /// descending sorting order
  12:              /// </summary>
  13:              Desc
  14:          }
  15:          public int CompareTo(Cleanup other)
  16:          {
  17:              return this.yourProperty.CompareTo(other.yourProperty);
  18:          }
  19:          public static Comparison<Cleanup> CacheItemPriority =
  20:              delegate(Cleanup cu1, Cleanup cu2)
  21:              {
  22:                  if (Cleanup.Sorting == SortingOrder.Asc)
  23:                  {
  24:                      return cu1.yourProperty.CompareTo(cu2.yourProperty);
  25:                  }
  26:                  else
  27:                  {
  28:                      return cu2.yourProperty.CompareTo(cu1.yourProperty);
  29:                  }
  30:              };
  31:      }
Once you have defined your class, you are able to sort it like need, with Ascending and Descending sortings
the sample you find also formatted at here: http://www.ronischuetz.com/code/cachecleanup.html
   1:      public class CacheCleanup
   2:      {
   3:          public CacheCleanup()
   4:          { 
   5:              List<Cleanup> coll = new List<Cleanup>();
   6:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.Normal, new TimeSpan(0, 1, 7), 1, new DateTime(2007, 12, 28, 14, 12, 12), 21232, 90));
   7:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.AboveNormal, new TimeSpan(0, 15, 7), 2, new DateTime(2007, 12, 28, 14, 12, 14), 22232, 190));
   8:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.BelowNormal, new TimeSpan(0, 18, 7), 3, new DateTime(2007, 12, 28, 14, 12, 40), 23232, 88));
   9:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.High, new TimeSpan(0, 8, 7), 4, new DateTime(2007, 12, 28, 14, 12, 16), 21552, 22));
  10:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.Low, new TimeSpan(0, 9, 7), 5, new DateTime(2007, 12, 28, 14, 12, 17), 21252, 1));
  11:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.NotRemovable, new TimeSpan(0, 22, 7), 6, new DateTime(2007, 12, 28, 14, 12, 19), 212332, 5));
  12:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.AboveNormal, new TimeSpan(0, 41, 7), 7, new DateTime(2007, 12, 28, 14, 12, 22), 211232, 55));
  13:              coll.Add(new Cleanup(IndexusMessage.CacheItemPriority.BelowNormal, new TimeSpan(0, 58, 7), 8, new DateTime(2007, 12, 28, 14, 12, 21), 22532, 25));
  14:   
  15:              Console.WriteLine(@"Without Sorting");
  16:              foreach (Cleanup c in coll)
  17:              {
  18:                  Console.WriteLine(c.ToString());
  19:              }
  20:   
  21:              Cleanup.Sorting = Cleanup.SortingOrder.Asc;
  22:              coll.Sort(Cleanup.CacheItemPriority);
  23:              Console.WriteLine(@"Normal Sorting");
  24:              foreach (Cleanup c in coll)
  25:              {
  26:                  Console.WriteLine(c.ToString());
  27:              }
  28:   
  29:              Cleanup.Sorting = Cleanup.SortingOrder.Desc;
  30:              coll.Sort(Cleanup.CacheItemPriority);
  31:              Console.WriteLine(@"Reverse Sorting");
  32:              foreach (Cleanup c in coll)
  33:              {
  34:                  Console.WriteLine(c.ToString());
  35:              }
  36:          }
  37:      }

it's couldn't be easier :-)

Thursday, December 20, 2007

caching cleanup strategy

As many of the blog readers know, I develop in my spare time a .net caching component which is available under: http://www.sharedcache.com or http://www.codeplex.com/sharedcache. This component aims to be a high-performance, distributed memory object caching system, generic in nature, but intended to speeding up dynamic web and / or win applications by alleviating database load.

now since some different websites are using the cache (thanks for all your feedback's and inputs) the issue comes up to selectively purges items to free system memory.

Here are some options which I would love to hear your feedback's about them and about what you would need for your personal usage:

  • CacheItemPriority: A new option will be created where objects which are added to the cache receives a priority attribute.
  • LRU: Least Recent Used: The objects with the oldest requests will be deleted- LFU: Least Frequently Used: Means the object's witch are used less will be deleted from the cache / if all objects are used in same frequency the objects will be used in a randomized order
  • Pitkow/Recker: Like LRU, but if they used on same day they will not be deleted
  • Timebased: The objects with the smallest time left in the cache will be deleted, in case all objects are used with max time, they will be deleted randomized
  • SIZE: Delete always biggest objects until it received the size of FillFactor
  • Lowest-Latency-First: Delete smallest objects until configured FillFactor reached. in the app settings the customer will be able to define his cleaning strategy type as a key.
  • Hybrid: Makes a combination between several parameters: TimeTaken, Amount of Requests, Size, Cache Life Timeeach parameter receives a number between 1 - n and those with the highest / lowest numbers will be deleted until configured FillFactory reached.

I would love to receive your feedback's and inputs about it.

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