STL and Usual C : Average time-cost of execution

5 views
Skip to first unread message

Alex Vinokur

unread,
Dec 25, 1998, 3:00:00 AM12/25/98
to
Hi,

Several functions (methods, operators) were measured.

--------------------------------------
C-functions | STL-methods (operators)
--------------------------------------
strcpy | operator= (string)
strcat | operator+= (string)
strlen | size () (string)
malloc&free | new&delete (string)
--------------------------------------

Average time-cost of execution was obtained.

Here are the results of the experiment.

Alex

//##########################################################################

//################# 1. Program
#############################################
//##########################################################################

#include <iostream>
#include <string>
#include <sys/time.h>

//=================================================
int main()
{
#define PRINT(x, y) cout << "Test#" << x << " [" << y << "] \t: " <<
"\tAverage time = " << (time_end - time_start) / TOTAL_Iterations << "
nsec" << endl
#define PRINTS(x, y) PRINT(x, y) << endl

//=======================
const int TOTAL_Tests = 5;
const int TOTAL_Iterations = 1000;
const int C_ARRAY_size = 7;
//===========
hrtime_t time_start;
hrtime_t time_end;
//===========

char c1 [C_ARRAY_size] = "CCC111";
char c0 [C_ARRAY_size * TOTAL_Iterations + 1];

string s0;
string s1 = "SSS111";
//===============
//======================

for (int theTest = 1; theTest <= TOTAL_Tests; theTest++)
{
//=======================
cout << endl << "\t" << "##### Test#" << theTest << "
#####" << endl;

//======= strcpy ================
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
strcpy (c0, c1);
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINT (theTest, "strcpy()\t");
//===============================
//======= operator= ================
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
s0 = s1;
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINTS (theTest, "STL : operator=");
//===============================

//======= strcat ================
strcpy (c0, "");
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
strcat (c0, c1);
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINT (theTest, "strcat()\t");
//===============================
//======= operator+= ================
s0 = string ();
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
s0 += s1;
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINTS (theTest, "STL : operator+=");
//===============================

//======= strlen ================
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
strlen (c0);
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINT (theTest, "strlen()\t");
//===============================
//======= size () ================
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
s0.size ();
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINTS (theTest, "STL : size ()\t");
//===============================


//======= malloc ================
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
free ((char *) malloc (4));
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINT (theTest, "malloc&free\t");
//===============================
//======= new&delete ================
time_start = gethrtime();
for (int theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
{
string ("ABCD");
} // for (theIteration = 1; theIteration <=
TOTAL_Iterations; theIteration++)
time_end = gethrtime();
PRINTS (theTest, "STL : new&delete");
//===============================


} // for (theTest = 1; theTest <= TOTAL_Tests; theTest++)
//======================
return 0;
}

//##########################################################################

//################# 2. Platform etc
########################################
//##########################################################################

SunOS 5.6 Generic_105181-09 sun4m sparc SUNW,SPARCstation-5
gcc version 2.8.1


//##########################################################################

//################# 3. Results of experiment
###############################
//##########################################################################

##### Test#1 #####
Test#1 [strcpy() ] : Average time = 890 nsec
Test#1 [STL : operator=] : Average time = 515 nsec

Test#1 [strcat() ] : Average time = 86770 nsec
Test#1 [STL : operator+=] : Average time = 4682 nsec

Test#1 [strlen() ] : Average time = 98352 nsec
Test#1 [STL : size () ] : Average time = 286 nsec

Test#1 [malloc&free ] : Average time = 4680 nsec
Test#1 [STL : new&delete] : Average time = 2671 nsec


##### Test#2 #####
Test#2 [strcpy() ] : Average time = 678 nsec
Test#2 [STL : operator=] : Average time = 521 nsec

Test#2 [strcat() ] : Average time = 83619 nsec
Test#2 [STL : operator+=] : Average time = 2485 nsec

Test#2 [strlen() ] : Average time = 97888 nsec
Test#2 [STL : size () ] : Average time = 286 nsec

Test#2 [malloc&free ] : Average time = 4592 nsec
Test#2 [STL : new&delete] : Average time = 2801 nsec


##### Test#3 #####
Test#3 [strcpy() ] : Average time = 679 nsec
Test#3 [STL : operator=] : Average time = 523 nsec

Test#3 [strcat() ] : Average time = 88326 nsec
Test#3 [STL : operator+=] : Average time = 2426 nsec

Test#3 [strlen() ] : Average time = 135749 nsec
Test#3 [STL : size () ] : Average time = 287 nsec

Test#3 [malloc&free ] : Average time = 4594 nsec
Test#3 [STL : new&delete] : Average time = 2859 nsec


##### Test#4 #####
Test#4 [strcpy() ] : Average time = 846 nsec
Test#4 [STL : operator=] : Average time = 521 nsec

Test#4 [strcat() ] : Average time = 88333 nsec
Test#4 [STL : operator+=] : Average time = 2424 nsec

Test#4 [strlen() ] : Average time = 102409 nsec
Test#4 [STL : size () ] : Average time = 286 nsec

Test#4 [malloc&free ] : Average time = 4594 nsec
Test#4 [STL : new&delete] : Average time = 2969 nsec


##### Test#5 #####
Test#5 [strcpy() ] : Average time = 845 nsec
Test#5 [STL : operator=] : Average time = 887 nsec

Test#5 [strcat() ] : Average time = 88568 nsec
Test#5 [STL : operator+=] : Average time = 2421 nsec

Test#5 [strlen() ] : Average time = 104744 nsec
Test#5 [STL : size () ] : Average time = 286 nsec

Test#5 [malloc&free ] : Average time = 5071 nsec
Test#5 [STL : new&delete] : Average time = 2673 nsec

//##########################################################################


[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Greg Chicares

unread,
Dec 27, 1998, 3:00:00 AM12/27/98
to
Thank you for posting this research.

I tried your program on a 300MHz Pentium II running win95,
with timer modifications listed below. I made one run only
(TOTAL_Tests = 1) to make this posting more compact, and
increased TOTAL_Iterations to 10000 in the hope of gaining
more accuracy.

***Borland C++ 5.02 with its builtin Rogue Wave standard library,
with greatest speed optimization:

[strcpy() ] : Average time = 416.953nsec
[STL : operator=] : Average time = 112.305nsec

[strcat() ] : Average time = 481765nsec
[STL : operator+=] : Average time = 1.23518e+06nsec

[strlen() ] : Average time = 238205nsec
[STL : size () ] : Average time = 7.20763nsec

[malloc&free ] : Average time = 727.133nsec
[STL : new&delete] : Average time = 1816.66nsec

Of these eight tests, the first one and the last two show
great variability (as much as a multiplier of three) in
timings between runs. The others are generally reproducible
within a percent or two.

***egcs 1.1 (mingw32) with -O3 optimization:

[strcpy() ] : Average time = 407.985nsec
[STL : operator=] : Average time = 40.6477nsec

[strcat() ] : Average time = 481520nsec
[STL : operator+=] : Average time = 833.99nsec

[strlen() ] : Average time = 7.29144nsec
[STL : size () ] : Average time = 7.12382nsec

[malloc&free ] : Average time = 2088.54nsec
[STL : new&delete] : Average time = 1444.38nsec

Variability is observed as above, except that the third test
here also varies considerably; probably this is because its
run time is much smaller with egcs.

Conclusions:
- Compared to C strings, C++ standard library strings seem as
fast or faster--sometimes much faster. This test suite
suggests no reason to prefer <cstring> to <string>, unless
one is constrained to use Rogue Wave and often uses
operator +=.
- C++ standard library implementations vary greatly. The
Rogue Wave operator+= seems slow; perhaps it is optimized
for a different use than egcs's.
- C standard library implementations also vary: in the
strlen() test, for instance, egcs seems to have a great
advantage over Borland.

Here are the changes I made to the timing code. The hardware
timer on my platform has approximately millisecond accuracy.
Results are reported in nanoseconds above only for
comparability with the original posting.

***In the global area after <string> is included: ***
//#include <sys/time.h>
#include <windows.h>
// MS windows uses a proprietary 64-bit integer "LARGE_INTEGER".
// They define it as a union, but Mingw32 defines it as a struct.
// Therefore I convert it to a long double. Substitute appropriate
// timing routines on any other architecture.
#include <limits.h>
long double foo(LARGE_INTEGER L)
{
unsigned long Lo = *(unsigned long*)&L;
long Hi = (long)*(1+(long*)&L);
long double z = Hi;
z *= ULONG_MAX;
z += Lo;
&Lo; &Hi;
return z;
}
#define hrtime_t long double
hrtime_t gethrtime()
{
LARGE_INTEGER z;
QueryPerformanceCounter(&z);
return foo(z);
}
using namespace std;

*** at the beginning of main(): ***
LARGE_INTEGER f;
QueryPerformanceFrequency(&f);
long double freq = foo(f) / 1000000000.0;

#define PRINT(x, y)\
cout << "Test#" << x << " [" << y << "] \t: " <<\
"\tAverage time = " <<\

(time_end - time_start) / (TOTAL_Iterations*freq) << "\
nsec" << endl
*** end of modifications ***

Phlip

unread,
Dec 29, 1998, 3:00:00 AM12/29/98
to
Greg Chicares escribió:

>Thank you for posting this research.

And thanks for this... But...

>[strcpy() ] : Average time = 416.953nsec

>[STL : operator=] : Average time = 112.305nsec


Two points. 'operator=' initializes copy-on-write if the source is also a
'string'. Were you pulling from a literal or a 'string'?

Second point: <screaming> It's not STL it's the Standard Library!
</screaming>

>Conclusions:
> - Compared to C strings, C++ standard library strings seem as
> fast or faster--sometimes much faster. This test suite
> suggests no reason to prefer <cstring> to <string>, unless
> one is constrained to use Rogue Wave and often uses
> operator +=.


Do not prematurely optimize. Use whatever system is easiest and most robust
at the moment. But at optimization time, pay attention to what's actually
going on. 'strcat()', for example, does not reallocate any internal buffer.
'operator+=' might, but then it might not if an existing buffer has spare
room.

-- Phlip at politizen dot com (address munged)
======= http://users.deltanet.com/~tegan/home.html =======
-- The first few lines of code must "hook" the
computer, and make it "care" about the program --

J. Kanze

unread,
Dec 30, 1998, 3:00:00 AM12/30/98
to
"Phlip" <add...@web.page> writes:

|> Do not prematurely optimize. Use whatever system is easiest and most robust
|> at the moment. But at optimization time, pay attention to what's actually
|> going on. 'strcat()', for example, does not reallocate any internal buffer.
|> 'operator+=' might, but then it might not if an existing buffer has spare
|> room.

And what does strcat do if the existing buffer doesn't have enough spare
room?

Once again, if correctness is not an issue, just write:

int main() { return 0 ; }

and be done with it.

--
James Kanze +33 (0)1 39 23 84 71 mailto: ka...@gabi-soft.fr
GABI Software, 22 rue Jacques-Lemercier, 78000 Versailles, France
Conseils en informatique orientée objet --
-- Beratung in objektorientierter Datenverarbeitung

Reply all
Reply to author
Forward
0 new messages