dba key graphic

Preamble


 Print this Page


Below is a series of recorded conversations, links and code samples presented by a number of members from the Database Advisors List.

Most of the comments and sample code were provided by Gustav Brock, Shamil Salakhetdinov and Stuart McLachlan; Jim DeMarco, Fred Hooper and Marty Connelly also contributed.

The communications centered on the performance levels that could be obtained through various methods code optimization using languages like MS Visual basic, Fortran, PowerBasic, FreeBasic, C#, VB.Net and C++

All comments are actual conversation so editing has been kept to a minimum, so as not to change the authors’ comments.

The following composite was assembled and installed on the DBA site by Jim Lawrence and the grammar, spelling and composition checked By Susan Harkins

 

 

Array Performance

 

Gustav Brock started the conversation with the following question:

 

Hi all

 

I have some routines that manipulate data in and between some arrays.

The arrays are not large but they are recalculated about 3 mio times which runs on my machine to 90 seconds.

 

I was wondering if there would be any significant speed increase by moving these routines to a DLL. I have no experience in writing such libraries but guess I could find as the routines are uncomplicated.

Variables are Long mostly, only one Single.

 

It would take me some time to program these, of course, and if the speed increase only could be expected to be, say, 30%, it would hardly be worth it.

 

Does anyone (Drew, Stuart?) have experience about what to expect?

 

/gustav

 

 

Response from Jim DeMarco

 

Gustav,

 

I'd expect some speed increase from compiled code but how much is hard to say.  It's doubtful that it would cut the time in half but it's certainly a possibility.

 

Are your routines in class modules?  If not and you can write them into a class or classes I'd be glad to compile them for you so you could test.

 

Jim DeMarco

 

 

Response form Stuart McLachlan

 

For something like that I'd definitely build a real DLL in PowerBasic. PB has built in array manipulation functions which are highly optimized and the speed gains compared to doing this sort of thing in VB/VBA would be dramatic.

 

Create a VB "DLL" is likely to have little effect on speed, it could even slow it down because of the calling overhead.

 

I'm leaving town in a couple of minutes for the weekend, but email me off list with your current array procedures and I'll take a look at building a simple DLL for you when I get back.

 

Still, if anyone with PowerBasic or other compiler could make similar tests and publish the results,

 

Stuart

 

 

Commented from Stuart McLachlan

 

The DLL was programmed and compiled in FreeBASIC and the FBIde which I earlier posted links for.

 

Setting lngLoopMax to 10^6 returns these running times for the two functions:

 

 

  ArrayTimeLocal: 34 seconds

  ArrayTimeDLL: 2.2 seconds (measured with 10^7 loops)

 

 

Thus this simple tool gives a speed improvement of 15.5 to 1 ... not bad!

 

 

Response from Gustav Brook:

 

Hi Stuart

 

Thanks! This is a bit surprising; I had expected it to run faster.

 

/gustav

 

 

Further response from Stuart McLachlan:

 

On my machine with the same code compiled to DLL in PowerBasic:

 

 

ArrayTimeLocal: 27 (10^6)

ArrayTimeDLL: 2.7 (actually 27 secs for 10^7)

 


An improvement of 10:1 .

 

Looks like for this set of operations FreeBASIC does a better job than PowerBASIC.

 

 

Response from Marty Connelly:

 

Just one hint for VBA code speed on this line since everything is being done by integers

 

 If alngTmp(lngItem, 1) / 10 = 100 Then

 

On a run of 50 seconds

If I use integer division with the "\" operator, I save around 1 second

 

 If alngTmp(lngItem, 1) \ 10 = 100 Then

 

If I use multiplication instead of division, I save 5-6 seconds It does a type conversion to a long, but I have never seen a full documented description of this from MS so I don't trust it, so I would use CLng which would add overhead.

 

 If alngTmp(lngItem, 1) * 0.1 = 100 Then

 

Some optimizing compilers have options that might change division by a constant to multiplication of it's inverse.

 

 

Response from Fred Hooper:

 

Hi Gustav,

 

His son, who now works with him, *likes* to program in Assembler (otherwise, he seems normal).

They used it to replace the millions-of-times-called routines in a ray tracer, which replaces the vector screen display if enough time elapses to finish the computations. The product is for kitchen design and, like the others but better, shows what the kitchen will look like. It's interesting to watch the screen change, it's as though the display changed to a picture.

 

Fred

 

 

Response from Gustav Brock:

 

Hi Fred

 

Sounds interesting and in line with the comments from Mr. PowerBasic (Stuart).

 

By the way, how did your brother-in-law write the Assembler version? With a tool of some sort or directly? Are you saying he obtained a 50:1 improvement in total compared to VB? I could probably handle PowerBasic without much trouble, but Assembler is far away.

 

/gustav

 

 

And further comment to Fred's message by Gustav Brock:

 

Hi Fred

 

That son deserves respect!

It is years ago I gave away my original plastic box with Microsoft Assembler to some local computer nerds collecting rarities.

 

But how can you handle Assembler today?

I located these links which may be of interest to some of you:

 

About HLA, High Level Assembly (contradicting?):

  http://www.linuxjournal.com/article/8408

 

Main page of HLA which is free:

  http://webster.cs.ucr.edu/AsmTools/HLA/index.html

 

Writing DLLs with HLA:

  http://webster.cs.ucr.edu/AsmTools/HLA/HLADoc/HTMLDoc/dll.html

 

An IDE for HLA, RadASM:

  http://radasm.visualassembler.com

 

For the next step, MASM32:

  http://www.masm32.com

 

If this is too much, how about FreeBASIC, a free QBasic compiler that can compile DLLs and use in-line assembler:

  http://www.freebasic.net

 

And an IDE for this, FBIde:

  http://fbide.sourceforge.net

 

/gustav

 

 

 

Response from Gustav Brock to Jim DeMarco:

 

Hi Jim

 

Sounds great!

 

No they are not classes. I simply pass ByRef an array to a function which shuffles around the content of the array ccording to some rules and other params. Would I need to wrap such a function in a class?

 

/gustav

 

 

Comment added from Marty Connelly:

 

Some of these replacements for VB intrinsic functions might speed things up.

Make sure you read the accompanying notes before using some may require a TLB

http://www.xbeat.net/vbspeed/index.htm

 

But it sounds like you are using mostly math functions.

Trig functions can be enhanced from basic VBA calls but would require C.

Sometimes you can get a bit more speed from multidimensional arrays by the order of looping on the indexes.

 

For example you are not going to get much speed increase by using *0.5 instead of  /2 maybe 1-2%

 

 

Comment from Jim DeMarco:

 

 

Private Declare Sub ShuffleArray Lib "gustavsdll" (ByVal p1 As Long,

ByVal p2 As Long, ByRef aSomeArray() As Long)

 

 

Versus:

 

 

Dim oMyArrayTool as gustavdll.ArrayTool

Set oMyArrayTool = new ArrayTool

oMyArrayTool.GoGetThatArray(lngP1, lngP2, MyArray())

 

 

Admittedly more code but not that complicated (same result either way).  One an API note I have seen components that had COM and API style interfaces.  I don't know if API style access is inherent in COM objects though.  Could those developers have created two interfaces to the components?  Maybe someone else can answer that.

 

Jim D.

 

 

Response from Gustav Brock:

 

Hi Jim

 

I see now what you mean. No, that is indeed not complicated.

 

/gustav

 

 

... and ...

 

 

If you are working with really for sure definitely absolutely fixed size arrays in VB6 dll you can turn off the Remove Array Bounds Checks option for about 25% speed performance increase.

 

With the chance of a GPF (Note: General Protect fault errors are caused when using code that does not consistently manage it's variable sizes. This results in application or/and OS failures.) 

 

 

/gustav

 

 

 

Response from Shamil Salakhetdinov:

 

 

Jim,

 

If you set Instancing property of ArrayTool custom class to GlobalMultiUse then you can just write:

 

GoGetThatArray  lngP1, lngP2, MyArray()

 

...in client code.

 

Shamil

 

 

 

Comment from Marty Connelly:

 

 

Personally if I am using arrays or a lot of matrix math like Fourier Transforms. I develop in Intel Fortran compiler for Windows & Visual Fortran but I can write Fortran in my sleep. It is COM compliant and callable from VBA. I have written DOS assembler a long time ago what I could do in a day in Fortran would take me 6 weeks in assembler just because I would have to relearn so much. Microsoft VB with arrays has a lot of overhead of error, type and range checking.

 

Come to think of it IBM Fortran compilers and maybe others used to produce an optional ASM listing that might help you out.

 

For Intel Fortran  Note: it also optimizes on array loops for parallel processing assuming multi cores.

 

http://www.intel.com/cd/software/products/asmo-na/eng/compilers/fwin/219725.htm

 

 

Response from Gustav Brock:

 

Hi Marty

 

Thanks! For those of you working with dot net note that this compiler (also) integrates with Visual Studio. However, it is so many years since I touched Fortran as a happy student that I have forgotten it 99%.

It certainly looks like a perfect choice for heavy floating point operations - which I don't need - at a fair cost.

 

It could be interesting to see how the computing time would be in VB(A) for the sinus approximation sample here:

 

http://www.intel.com/software/products/compilers/fwin/docs/Getting_Started.htm

 

/gustav

 

 

 

Comment from Gustav Brock in response from comments from Marty Connelly, Shamil Salakhetdinov, Fred Hooper etc...

 

 

Hi Marty, Shamil, Fred et all

 

Well, I did a small and quite surprising test inspired by Shamil. Here is a test routine which can be seen as typical for what I do. The array is not large but it is read from and written to a bunch of times.

 

Here is the local test using standard VBA:

 

 

Function ArrayTimeLocal(ByVal lngLoopMax As Long) As Long

   

  Const lngItems                      As Long = 100

 

  Dim alngTmp(1 To lngItems, 1 To 2)  As Long

  Dim lngLoop                         As Long

  Dim lngItem                         As Long

  Dim lngResult                       As Long

  Dim lngSeconds                   As Long

  Dim dblStart                        As Double

  Dim dblStop                         As Double

 

  dblStart = Timer

 

  For lngLoop = 1 To lngLoopMax

    For lngItem = 1 To lngItems

      alngTmp(lngItem, 1) = lngLoop * 10

      If alngTmp(lngItem, 1) / 10 = 100 Then

        lngResult = 1

      Else

        lngResult = 0

      End If

    Next

  Next

 

  dblStop = Timer

  lngSeconds = CLng(dblStop - dblStart)

   

  ArrayTimeLocal = lngSeconds

   

End Function

 

 

And this is the test function using a DLL containing nearly identical code:

 

 

Declare Function ArrayTime Lib "arraydll.dll" Alias "ArrayTime@4" (ByVal lngLoops As Long) As Long

 

Function ArrayTimeDLL(ByVal lngLoopMax As Long) As Long

 

  ArrayTimeDLL = ArrayTime(lngLoopMax)

 

End Function

 

 

The DLL was programmed and compiled in FreeBASIC and the FBIde which I earlier posted links for.

 

Setting lngLoopMax to 10^6 returns these running times for the two functions:

 

 

  ArrayTimeLocal: 34 seconds

  ArrayTimeDLL: 2.2 seconds (measured with 10^7 loops)

 

 

Thus this simple tool gives a speed improvement of 15.5 to 1 ... not bad!

 

Nothing comes free, and the trouble is - as far as I can see - that the dll has to be programmed to run rock stable. If it errors out, Access halts or simply quits - no errors, no GPF, just poof away.

 

With this result I think I'll leave the assembler stuff for now. Still, if anyone with PowerBasic or other compiler could make similar tests and publish the results, we could rank these.

 

/gustav

 

 

 

Response from Shamil Salakhetdinov:

 

Hi Gustav,

 

With switched off array bounds check and integer overflow check your sample code runs in less than 1 second when in VB6 bActiveX dll.

 

Similar code in C++(VS.NET 2003) runs instantaneously.

 

C++ allows to measure time when 10^6 cycles are additionally cycled 10^7 times!

 

Below is sample C++ code. Maybe I did make some mistakes -

10^7 * 10^6 loops in just two seconds looks incredible speed gain under C++ - these are

989,999,010,000,000 cycles...

 

And in 19 seconds 9,899,990,100,000,000 cycles can be executed.

 

 

long ArrayTimeLocal(long lngLoopMax, long& lngTotalCnt); int _tmain(int argc, _TCHAR* argv[]) { 

long dblStart;  long dblStop;  long lngResult;  long lngCnt = 0;

 __int64 totalCnt = 0;

 time(&dblStart);

 for (int i = 1; i<=10000000; i++) {

  lngResult = ArrayTimeLocal(1000000, lngCnt);

  totalCnt += ((__int64)lngCnt);

  if ((i % 1000000) == 0)

   printf("Result = %ld, Counter = %I64d\n",

    lngResult, totalCnt);

 }

    time(&dblStop);

 lngResult = (long)difftime(dblStop,dblStart);  printf("Final Result = %ld, Final Counter = %I64d\n",

     lngResult, totalCnt);

}

 

long ArrayTimeLocal(long lngLoopMax, long& lngTotalCnt) {

  const long lngItems = 100;

  long alngTmp[lngItems-1][1];

  long lngLoop;

  long lngItem;

  long lngResult;

  long lngSeconds;

  long dblStart;

  long dblStop;

 

  lngTotalCnt = 0;

  time(&dblStart);

  for (lngLoop=1; lngLoop < lngLoopMax; lngLoop++) {

   for (lngItem=1; lngItem < lngItems; lngItem++) {

  alngTmp[lngItem-1][0] = lngLoop * 10;

  if (alngTmp[lngItem-1][0] / 10 == 100) lngResult = 1;

  else lngResult = 0;

  lngTotalCnt++;

   }

  }

  time(&dblStop);

  lngSeconds = (long)difftime(dblStop,dblStart);

  return lngSeconds;

}

 

 

And here is result of this code test run:

 

 

Result = 0, Counter = 98999901000000

Result = 0, Counter = 197999802000000

Result = 0, Counter = 296999703000000

Result = 0, Counter = 395999604000000

Result = 0, Counter = 494999505000000

Result = 0, Counter = 593999406000000

Result = 0, Counter = 692999307000000

Result = 0, Counter = 791999208000000

Result = 0, Counter = 890999109000000

Result = 0, Counter = 989999010000000

Final Result = 2, Final Counter = 989999010000000

 

 

Shamil

 

 

Comment from Gustav Brock:

 

Hi Shamil

 

I just read your post following this, and your conclusion about C# seems to be true.

 

Your results from C++ is an eye-opener. I hardly can believe that speed improvement!

But for a true comparison, could I persuade you to compile it to an DLL and call that from VB(A) the same way I did with the DLL compiled in FreeBASIC?

 

You would probably need 10^7 loops or - if you measurement holds - 10^8 loops.

 

/gustav

 

 

 

Code sample from Shamil Salakhetdinov:

 

 

Gustav,

 

I think if you say that you have forgotten 99% Fortran then you can convert your code into C++ with same efforts as on Fortran.  I mean  - if your code is just "arrays shuffling" as you say then VB(A)-> C++ conversion is almost line by line...

 

I did recheck - your code runs just in 5 seconds on VB6 with array bounds checks and integer overflow checks switched off. These are 100,000,000 loops.

 

I did also test your sample code on C# and VB.NET - and it runs in 5-6 seconds with switched off integer overflow checks (it looks that there is no way to switch off array bounds checks for C# and VB.NET) .

 

Here is VB.NETcode I used for testing:

 

VB.NET

 

Module testArrays

 

    Sub Main()

        Dim lngResult As Long = 0

        Dim lngCnt As Long = 0

        Dim lngTotalCnt As Long = 0

        lngResult = ArrayTimeLocal(1000000, lngTotalCnt)

        lngTotalCnt += lngCnt

        Console.WriteLine(String.Format( _

         "Final Result = {0:#,##0}, Final Counter = {1:#,##0}", _

         lngResult, lngTotalCnt))

    End Sub

 

    Function ArrayTimeLocal(ByVal lngLoopMax As Long, ByRef lngTotalCnt As

Long) As Long

 

        Const lngItems As Long = 100

 

        Dim alngTmp(lngItems - 1, 1) As Long

        Dim lngLoop As Long

        Dim lngItem As Long

        Dim lngResult As Long

        Dim lngSeconds As Long

        Dim dblStart As Double

        Dim dblStop As Double

        Dim lngCnt As Long = 0

        dblStart = Timer

 

        For lngLoop = 0 To lngLoopMax - 1

            For lngItem = 0 To lngItems - 1

                alngTmp(lngItem, 1) = lngLoop * 10

                If alngTmp(lngItem, 1) / 10 = 100 Then

                    lngResult = 1

                Else

                    lngResult = 0

                End If

                lngCnt += 1

            Next

        Next

 

        dblStop = Timer

        lngSeconds = CLng(dblStop - dblStart)

 

        lngTotalCnt = lngCnt

        ArrayTimeLocal = lngSeconds

 

    End Function

 

End Module

 

 

Output

 

Final Result = 5, Final Counter = 100,000,000

 

 

C#

 

using System;

using Microsoft.VisualBasic;

 

namespace testArraysCS

{

 class TestArrays

 {

  [STAThread]

  unsafe static void Main(string[] args)

  {

   long lngTotalCnt = 0;

   long lngResult = 0;

 

   lngResult = ArrayTimeLocal(1000000, ref lngTotalCnt);

   Console.WriteLine(String.Format(

    "Final Result = {0:#,##0}, Final Counter = {1:#,##0}",

    lngResult, lngTotalCnt));

  }

 

  unsafe static long ArrayTimeLocal(long lngLoopMax, ref long lngTotalCnt) {

   const long lngItems = 100;

   long[,] alngTmp = new long[lngItems,1] ;

   long lngLoop;

   long lngItem;

   long lngResult=0;

   double dblStart;

   double dblStop;

   long lngSeconds;

 

   Console.WriteLine("Array looping test started...");

   dblStart = Microsoft.VisualBasic.DateAndTime.Timer;

   lngTotalCnt = 0;

   for (lngLoop=0; lngLoop < lngLoopMax; lngLoop++) {

    for (lngItem=0; lngItem < lngItems; lngItem++) {

     alngTmp[lngItem,0] = lngLoop * 10;

     if (alngTmp[lngItem,0] / 10 == 100) lngResult = 1;

     else lngResult = 0;

     lngTotalCnt++;

    }

   }

   dblStop = Microsoft.VisualBasic.DateAndTime.Timer;

   Console.WriteLine("Array looping test ended.");

   lngSeconds = (long)(dblStop - dblStart);

   return lngSeconds;

  }

 

 }

}

 

 

Output

 

Array looping test started...

Array looping test ended.

Final Result = 6, Final Counter = 100,000,000

 

 

Recapitulation:

===========

 

C++ & Fortran (and COBOL?) rule and rock forever! :)

 

Shamil

 

 

Additional response from Shamil Salakhetdinov:

 

 

Gustav,

 

And finally here is managed C++, which runs instantaneously:

 

 

#include "stdafx.h"

 

#using <mscorlib.dll>

#using <Microsoft.VisualBasic.dll>

 

using namespace System;

 

static long ArrayTimeLocal(long lngLoopMax, long& lngTotalCnt); int _tmain() {  long lngTotalCnt = 0; 

long lngResult = 0;

 

 lngResult = ArrayTimeLocal(1000000, lngTotalCnt);  Console::WriteLine(String::Format(

  S"Final Result = {0:#,##0}, Final Counter = {1:#,##0}",

  __box(lngResult), __box(lngTotalCnt))); }

 

static long ArrayTimeLocal(long lngLoopMax, long& lngTotalCnt) {  const long lngItems = 100;  long

alngTmp[lngItems-1][2];  long lngLoop;  long lngItem;  long lngResult=0;  double dblStart;  double

dblStop;  long lngSeconds;

 

 Console::WriteLine("Array looping test started...");  dblStart =

Microsoft::VisualBasic::DateAndTime::Timer;

 lngTotalCnt = 0;

 for (lngLoop=0; lngLoop < lngLoopMax; lngLoop++) {

  for (lngItem=0; lngItem < lngItems; lngItem++) {

   alngTmp[lngItem][0] = lngLoop * 10;

   if (alngTmp[lngItem][0] / 10 == 100) lngResult = 1;

   else lngResult = 0;

   lngTotalCnt++;

  }

 }

 dblStop = Microsoft::VisualBasic::DateAndTime::Timer;

 Console::WriteLine("Array looping test ended.");  lngSeconds = (long)(dblStop - dblStart);

return lngSeconds; }

 

 

Output

 

Array looping test started...

Array looping test ended.

Final Result = 0, Final Counter = 100,000,000

 

 

And it takes ~18 seconds on my PC to run this test ADDITIONALLY looped 100 times....

 

Shamil

 

 

Comment from Gustav Brock:

 

Hi Shamil

 

Oh my ... could you create a DLL with the essentials from your ArrayTimeLocal skipping the console parts? It just need to return the lngSeconds.

 

Looks like I need some C++ stuff for this project!

 

/gustav

 

 

Response from Shamil Salakhetdinov:

 

 

Gustav,

 

Yes, I can make a C++ dll but maybe you first (re)define your test function call interface because even if you call very quick C++ function 1000 times from VB6 you can loose all the advantages this C++ function gives.

 

Currently - here is C++ (non managed) console applications results for a function similar to yours:

 

10,000,000,000 your cycles in 13 seconds (it looks like I did some mistakes in my previous time calculations - I have to recheck)

 

=====================================

Final Result = 13, Final Counter = 10000000000

=====================================

 

Here is the C++ code for the last test:

 

 

#include "stdafx.h"

#include <time.h>

 

static long ArrayTimeLocal(long lngLoopMax, long& lngTotalCnt, bool useTracePrinting = false);

int _tmain(int argc, _TCHAR* argv[]) {

 _int64 lngTotalCnt = 0;

 long lngCnt = 0;

 time_t /*double*/ dblStart;

 time_t /*double*/ dblStop;

 long lngSeconds = 0;

 

 time(&dblStart);

 for (int i=1; i<=10; i++) {

    ArrayTimeLocal(10000000, lngCnt);

    lngTotalCnt += lngCnt;

 }

 

 time(&dblStop);

 lngSeconds = (long)difftime(dblStop,dblStart);;

 printf("Final Result = %ld, Final Counter = %I64d\n",

     lngSeconds, lngTotalCnt);

}

 

static long ArrayTimeLocal(long lngLoopMax, long& lngTotalCnt, bool

useTracePrinting) {

 const long lngItems = 100;

 long alngTmp[lngItems][2];

 long lngLoop;

 long lngItem;

 long lngResult = 0;

 time_t /*double*/ dblStart;

 time_t /*double*/ dblStop;

 long lngSeconds;

 long lngCnt = 0;

 

 if (useTracePrinting) printf("Array looping test started..\n");  time(&dblStart);  for (lngLoop=0;

lngLoop < lngLoopMax; lngLoop++) {

  for (lngItem=0; lngItem < lngItems; lngItem++) {

   alngTmp[lngItem][0] = lngLoop * 10;

   if (alngTmp[lngItem][0] / 10 == 100) lngResult = 1;

   else lngResult = 0;

   lngCnt++;

  }

 }

 time(&dblStop);

 if (useTracePrinting) printf("Array looping test ended.\n");  lngSeconds =

(long)difftime(dblStop,dblStart);;

 if (useTracePrinting) printf("Result = %lf, Counter = %ld\n",

     lngSeconds, lngTotalCnt);

 lngTotalCnt = lngCnt;

 return lngSeconds;

}

 

 

I will try to move now all variable from stack to static memory - I expect it may bring even more speed execution gains. We will see.

 

As soon as you define your final call interface I will make a test C++ .dll...

 

Shamil

 

 

Response from Gustav Brook:

 

 

Hi Shamil

 

For "redefining the interface" you mean that a Long is not enough to specify a count of loops large enough to obtain a running time of some seconds? That's the only parameter I wish to pass. The only needed value to return is the running duration in seconds.

 

If so, couldn't we expand with an additional loop to multiply the count of loops:

 

 

for (lngSequence=0; lngSequence < lngSequences; lngSequence++) {  for (lngLoop=0; lngLoop <

lngLoopMax; lngLoop++) {

  for (lngItem=0; lngItem < lngItems; lngItem++) {

   alngTmp[lngItem][0] = lngLoop * 10;

   if (alngTmp[lngItem][0] / 10 == 100) lngResult = 1;

   else lngResult = 0;

   lngCnt++;

  }

 }

}

 

 

and then add lngSequences as a separate parameter:

 

 

static long ArrayTimeLocal(long lngSequences, long lngLoopMax, long& lngTotalCnt, bool

useTracePrinting = false);

 

 

That would be great.

 

/gustav

 

 

Further comment from Shamil Salakhetdinov:

 

 

With variables moved to (static) memory out of stack the code works for ~6 seconds slower (yes, that was stupid of me to expect it running faster - when getting/putting variable from/to stack Intel processors should work faster). Well, one can see 6 seconds difference on 10,000,000,000 cycle runs only - for usual programming this difference doesn't matter. Here is C++ sample code, which runs 19 seconds on my PC:

 

 

#include "stdafx.h"

#include <time.h>

 

typedef long COUNTER_TYPE;

 

const long lngItems = 100;

long alngTmp[lngItems][2];

long lngLoop;

long lngItem;

long lngResult = 0;

time_t /*double*/ dblStart;

time_t /*double*/ dblStop;

long lngSeconds;

COUNTER_TYPE lngCnt;

 

static long ArrayTimeLocal(long lngLoopMax, COUNTER_TYPE& lngTotalCnt, bool useTracePrinting =

false); int _tmain(int argc, _TCHAR* argv[]) {

 _int64 lngTotalCnt = 0;

 COUNTER_TYPE lngCnt = 0;

 time_t /*double*/ dblStart;

 time_t /*double*/ dblStop;

 long lngSeconds = 0;

 

 time(&dblStart);

 for (int i=1; i<=100; i++) {

    ArrayTimeLocal(1000000, lngCnt);

    lngTotalCnt += lngCnt;

 }

 time(&dblStop);

 lngSeconds = (long)difftime(dblStop,dblStart);;

 printf("Final Result = %ld, Final Counter = %I64d\n",

     lngSeconds, lngTotalCnt);

}

 

static long ArrayTimeLocal(long lngLoopMax, COUNTER_TYPE& lngTotalCnt, bool

useTracePrinting) {

 lngCnt=0;

 if (useTracePrinting) printf("Array looping test started..\n");  time(&dblStart);  for (lngLoop=0;

lngLoop < lngLoopMax; lngLoop++) {

  for (lngItem=0; lngItem < lngItems; lngItem++) {

   alngTmp[lngItem][0] = lngLoop * 10;

   if (alngTmp[lngItem][0] / 10 == 100) lngResult = 1;

   else lngResult = 0;

   lngCnt++;

  }

 }

 time(&dblStop);

 if (useTracePrinting) printf("Array looping test ended.\n");  lngSeconds =

(long)difftime(dblStop,dblStart);;

 if (useTracePrinting) printf("Result = %lf, Counter = %ld\n",

     lngSeconds, lngTotalCnt);

 lngTotalCnt = lngCnt;

 return lngSeconds;

}

 

 

Shamil Salakhetdinov responds to Gustav: