This is a mirror of official site: http://jasper-net.blogspot.com/

Buffer.BlockCopy not as fast as you think

| Tuesday, February 15, 2011
I recently wrote a quick test to prove something, that ended up being wrong…

Of course this is the way of science. You form a hypothesis, then you test. The results should prove or disprove your theory.

The Hypothesis

Ok, my theory was that Buffer.BlockCopy() would outperform our current Array.Copy routines on the page level.

When we are loading records off a page, we have to extract some parts of the buffer to build up a row buffer. A typical 8Kb page may have 100 or more records packed into it, and grabbing them out can take quite a bit of time. Each row data is a compressed byte array that may include information that points to extended row data as well.

This is one of the differences between this same app written in C++ and C#. In C++, you would just take a pointer to the original buffer and pass that to the row routines, you wouldn't need a copy of the data. But we don't have pointers in C#, so a copy is made to get out just the part of the buffer needed by that row.

Since we want the fastest way possible to read this block of data into the row, we were looking at alternative ways to do it.

The Experiment

I wrote a program that randomly grabs a length from an 8Kb block that contains 150 records. The length of the row was randomized (but the seed reset to the same value for both tests to ensure the same random numbers were used with both methods). The results were surprising.

class Program
{
   public static int pagesize = 8192;
   public static int MaxLoops = 100000;

   static void Main( string[] args )
   {
       Stopwatch watch = new Stopwatch();

       // Force a GC Collect so we start clean
       GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
       System.Threading.Thread.Sleep(2000);
       watch.Start();
       DoTest(true);
       watch.Stop();
       Console.WriteLine("Buffer.BlockCopy took {0} ticks", watch.ElapsedTicks);

       watch.Reset();
       GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
       System.Threading.Thread.Sleep(2000);

Read more: Codeproject

Posted via email from Jasper-net

0 comments: