Have you patented this comparison technique? :P

From: [email protected] [mailto:[email protected]] On 
Behalf Of Greg Harris
Sent: Thursday, 20 May 2010 1:22 PM
To: ozDotNet
Subject: Re: How To do something every so often

Hi Everyone,
I think that this shows that we all have too much time on our hands!
Our modern machines are so fast that this is an irrelevant question for all but 
the most compute intensive applications.
The standard well known design pattern is to use the modulus (%) function.
if ( (i % lTestPoint) == 0 )
  Console.Write( "x" );

As about 80% of development cost is in maintenance, then keep it simple unless 
you really really need to change it for a good reason.  So DON'T CHANGE THIS!
I wrote a quick program to test this and got the result that it does not really 
matter which technique you use when you compare it to doing a little bit of 
real work inside the loop.
In some more detail...
The program had a tight loop going from zero to 268,435,456 (0x10000000) and 
outputting an "x" every 16,777,215 (0xffffff) times through the loop.
Tests results were:

*         Using modulus (%) function, time = 3.20 seconds (the slowest)

*         Using separate counter with equals (==) test, time = 1.81 seconds

*         Using separate counter with greater than equals (>=) test, time = 
1.79 seconds

*         Using Boolean logic on the base counter, time = 1.64 seconds (the 
fastest test)

*         Not test at all, time = 1.01 seconds

*         Doing some real work and not doing the test at all, time = 9.93 second
This shows what I would expect:

*         Not doing the test is the fastest.

*         A Boolean logic test is the fastest way of actually doing the test.

*         A separate counter is a little slower, but effectively the same time.

*         It does not matter if you test for equal (==) or greater than or 
equal (>=) (the difference is in the third decimal place)

*         Yes modulus function (%) is the slowest

*         But all irrelevant compared to doing some real simple work in the loop
The modulus function (%) took 1.55 seconds more than the Boolean logic over 
268,435,456 iterations, it has taken me about an hour to write this test 
program and email, the modulus function could have been run more than 300 
Billion times in this time!
Test program output

lEndPoint:  268435456
lTestPoint: 16777215
Start Test 1: using Mod (%)
xxxxxxxxxxxxxxxxx
Done 00:00:03.1981829

Start Test 2: using a separate counter test is ==
xxxxxxxxxxxxxxxx
Done 00:00:01.8081034

Start Test 3: using a separate counter test is >=
xxxxxxxxxxxxxxxx
Done 00:00:01.7921025

Start Test 4: using boolean logic on the base counter
xxxxxxxxxxxxxxxx
Done 00:00:01.6380937

Start Test 5: No test at all

Done 00:00:01.0070576

Start Test 6: No test at all, but doing some real work

Done 00:00:09.9345682
Test program

    static void Main(string[] args)
    {
      DateTime lStartTime ;
      DateTime lEndTime   ;
      TimeSpan lDelta     ;
      long     lCounter   ;
      long     lEndPoint  = 0x10000000; // 268,435,456
      long     lTestPoint = 0xffffff  ; //  16,777,215
      double   lSum       = 0         ; // sum of the square roots (the work 
test#6 only)

      Console.WriteLine( "lEndPoint:  " + lEndPoint .ToString() );
      Console.WriteLine( "lTestPoint: " + lTestPoint.ToString() );

      Console.WriteLine( "Start Test 1: using Mod (%)" );
      lStartTime = DateTime.Now;
      for ( long i = 0; i<=lEndPoint; i++ )
      {
        if ( (i % lTestPoint) == 0 )
          Console.Write( "x" );
      }
      Console.WriteLine();
      lEndTime = DateTime.Now;
      lDelta   = lEndTime - lStartTime;
      Console.WriteLine( "Done " + lDelta.ToString() );
      Console.WriteLine();

      Console.WriteLine( "Start Test 2: using a separate counter test is ==" );
      lCounter = 0;
      lStartTime = DateTime.Now;
      for ( long i = 0; i<=lEndPoint; i++ )
      {
        lCounter++;
        if ( lCounter == lTestPoint )
        {
          Console.Write( "x" );
          lCounter = 0;
        }
      }
      Console.WriteLine();
      lEndTime = DateTime.Now;
      lDelta   = lEndTime - lStartTime;
      Console.WriteLine( "Done " + lDelta.ToString() );
      Console.WriteLine();

      Console.WriteLine( "Start Test 3: using a separate counter test is >=" );
      lCounter = 0;
      lStartTime = DateTime.Now;
      for ( long i = 0; i<=lEndPoint; i++ )
      {
        lCounter++;
        if ( lCounter >= lTestPoint )
        {
          Console.Write( "x" );
          lCounter = 0;
        }
      }
      Console.WriteLine();
      lEndTime = DateTime.Now;
      lDelta   = lEndTime - lStartTime;
      Console.WriteLine( "Done " + lDelta.ToString() );
      Console.WriteLine();

      Console.WriteLine( "Start Test 4: using boolean logic on the base 
counter" );
      lStartTime = DateTime.Now;
      for ( long i = 0; i<=lEndPoint; i++ )
      {
        if ( (i & lTestPoint) == lTestPoint )
        {
          Console.Write( "x" );
        }
      }
      Console.WriteLine();
      lEndTime = DateTime.Now;
      lDelta   = lEndTime - lStartTime;
      Console.WriteLine( "Done " + lDelta.ToString() );
      Console.WriteLine();

      Console.WriteLine( "Start Test 5: No test at all" );
      lStartTime = DateTime.Now;
      for ( long i = 0; i<=lEndPoint; i++ )
      {
        // Do nothing
      }
      Console.WriteLine();
      lEndTime = DateTime.Now;
      lDelta   = lEndTime - lStartTime;
      Console.WriteLine( "Done " + lDelta.ToString() );
      Console.WriteLine();

      Console.WriteLine( "Start Test 6: No test at all, but doing some real 
work" );
      lStartTime = DateTime.Now;
      for ( long i = 0; i<=lEndPoint; i++ )
      {
        lSum += System.Math.Sqrt((double)i);
      }
      Console.WriteLine();
      lEndTime = DateTime.Now;
      lDelta   = lEndTime - lStartTime;
      Console.WriteLine( "Done " + lDelta.ToString() );
      Console.WriteLine();

      Console.ReadLine();
    }


Reply via email to