Which is faster?

J

Justin Robbs

I need to fill a number of character fields with spaces or zero's
depending on the field. Which method is faster.

char var[10] = " ";
var[9] = '\0';

or

char var[10];
sprintf( var, " " );

or

char var[10];
strcpy( var, " " );
var[9] = '\0';

or

int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';

Thanks for the help.

Justin
 
A

Ahmed S. Badran

Justin said:
I need to fill a number of character fields with spaces or zero's
depending on the field. Which method is faster.

char var[10] = " ";
var[9] = '\0';
I would think this one is the fastest, will probably be translated by the
compiler by a 'multiple store' instruction.
or

char var[10];
sprintf( var, " " );
Involves a function call, pushing to the stack, changing program counter,
going back and forth.
or

char var[10];
strcpy( var, " " );
var[9] = '\0'; same as above
or

int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';

Faster than the function calls, the entire code fragment will be probably
held in the processor cache, I would say this one could be comparable to the
first. This way you will have lots of 'very fast executing' instructions
with minimal processor-memory transactions (of course not taking into
account the memory writeback from the cache), compared to probably a single
'multiple store' in the first case. However, I personally think the laster
would be the fastest
Thanks for the help.

Think about that too;

int i =0;
char tmp= ' ';
while (i < 10) {
var[i++] = tmp;
}

I would think this would be the fastest, everything will be cached on the
processors cache, including the variables.

Ahmed
 
C

Christopher Benson-Manica

Justin Robbs said:
I need to fill a number of character fields with spaces or zero's
depending on the field. Which method is faster.

How about

char var[10];
memset( var, ' ', sizeof var - 1 );
var[9]=0;

? I don't recommend that method, however :)
char var[10] = " ";
var[9] = '\0';

I'd say this is your best bet for speed, since all the work can be
accomplished at compile time.
char var[10];
sprintf( var, " " );
char var[10];
strcpy( var, " " );
var[9] = '\0';

strcpy appends a null terminator (assuming the destination string is
large enough), so you don't need to do that explicitly.
int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';


This is probably slowest, since the library routines may be able to
use special implementation features to speed up the operation. I
could be wrong on that, however.
 
J

John Cochran

I need to fill a number of character fields with spaces or zero's
depending on the field. Which method is faster.

Benchmark the various ways on your system and find out for yourself.
Also, is speed really that much of an issue?

But, here are some comments on each of your methods.
char var[10] = " ";
var[9] = '\0';

This method will only work at the time you declare the variable. Attempting
the following code
var = " ";
will not work. Given that limitation, the assignment
var[9] = '\0';
is useless because the string is already NUL terminated.
or

char var[10];
sprintf( var, " " );
I suspect that this is the worst of the lot since printf and family have
a far amount of overhead.

or

char var[10];
strcpy( var, " " );
var[9] = '\0';
I suspect that this would be towards the top of the list in speed, but
that var[9] = '\0'; is useless. Get rid of it.
or

int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';


Ick. This one doesn't do what you expect. It contains a buffer overflow.
But if you fix it, it's performance may be comparable to using strcpy().
The only question is the overhead of a function call to strcpy() and if
the vender supplied library uses machine specific tricks to gain speed.

But, I'll repeat an old saying about programming.

Premature optimization is the root of all evil.
Tony Hoare, restated by Donald Knuth.

Think carefully about if this assignment to a string really matters in
terms of performance. It most likely doesn't. Pick good algorythms for
your code and then make the implimentation of the good algorythms as clear
as possible. As a simple example, imagine the relative performance of
2 sort algorythms.

Program one.
Uses a bubble sort as its primary algorythm and is optimized as much
as possible.

Program two.
Uses a heap sort as its primary algorythm and not a lot of attention is
made to reduce CPU cycles.

For very small amounts of data, program one may be faster, but for larger
amounts of data, program two will be so much faster than program one, it
isn't even funny. An O(N log N) algorythm vs an O(N^2) algorythm totaly
swamps any effect optimization may have.

Use the strcpy() and simply make your program readable.
 
E

Eric Sosman

Justin said:
I need to fill a number of character fields with spaces or zero's
depending on the field. Which method is faster.

Answer #1: It's impossible to say. The C language
is implemented on many platforms with different performance
characteristics. Method X may be faster than Method Y on
Platform A, but slower on Platform B, and run at identical
speed on Platform C.

Answer #2: It is surpassingly unlikely that the speed
of such a trivial operation will have any detectable effect
on the speed of your program. You are almost certainly
optimizing the wrong thing; an old friend of mine used to
characterize this as "Cleaning the bottle caps off the
beach so the sand will be nice and smooth around the
whale carcasses."

Answer #3: Interspersed below.
char var[10] = " ";
var[9] = '\0';

First, this isn't "filling a field," it's initializing
an array and then overwriting part of it. The distinction
is important because the first line works only as an
initializer; you can't just assign arrays with the `='
operator.

Second, it's silly. You initialize `var' to contain
nine spaces followed by a zero, and then you overwrite that
zero with another zero. What's the point of the overwrite?
or

char var[10];
sprintf( var, " " );

This is probably the slowest of the alternatives you've
presented. No guarantees, of course.
or

char var[10];
strcpy( var, " " );
var[9] = '\0';

Again, why set var[9] to zero twice? Are you afraid it
won't remember its value unless reminded? ("Hey there,
var[9]: Pay attention or I'll make you stay after class and
clean the erasers!")

int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';


Why set var[9] to a space, only to turn right around and
overwrite the space with a zero? You could save time (HUGE
amounts of time ;-) by stopping the loop after nine iterations
instead of ten.
Thanks for the help.

You're welcome. The biggest help I think I can be is to
suggest that you not worry about the speed of such a trivial
thing until and unless you've *measured* the performance of
your program and determined that the timing of this fragment
is crucial. (A consequence of this philosophy of "help" is
that I'm not even going to mention the manymanymany other
ways you might go about this task.)
 
D

Dan Pop

In said:
I need to fill a number of character fields with spaces or zero's
depending on the field. Which method is faster.

Are you absolutely sure that it makes any *prctical* difference to your
program?
char var[10] = " ";
var[9] = '\0';

or

char var[10];
sprintf( var, " " );

or

char var[10];
strcpy( var, " " );
var[9] = '\0';

or

int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';


How about the OBVIOUS?

char var[10] = " ";

Although the null character is invisible, it's built into the string
literal used as initialiser.

For zero-filling, use the following instead:

char var[10] = { 0 };

Although it's not obvious, it will fill var with zeros. When used on a
struct, it will set each field to the right form of zero (integer zero,
floating point zero, null pointer).

Dan
 
C

Christopher Benson-Manica

Eric Sosman said:
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';

Why set var[9] to a space, only to turn right around and
overwrite the space with a zero? You could save time (HUGE
amounts of time ;-) by stopping the loop after nine iterations
instead of ten.

Note that as written, it's var[10] that gets set to 0 - perhaps OP
hoped that UB in this case would result in instant completion? ;)
 
D

Dan Pop

In said:
Justin said:
int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';


Why set var[9] to a space, only to turn right around and
overwrite the space with a zero?


That's NOT what the code is doing. It's the non-existing var[10] that
is set to zero, to generate lots of fun at debug time ;-)
You could save time (HUGE
amounts of time ;-) by stopping the loop after nine iterations
instead of ten.

Nah, that would make the code boringly correct.

Dan
 
E

Eric Sosman

Christopher said:
Eric Sosman said:
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';

Why set var[9] to a space, only to turn right around and
overwrite the space with a zero? You could save time (HUGE
amounts of time ;-) by stopping the loop after nine iterations
instead of ten.

Note that as written, it's var[10] that gets set to 0 - perhaps OP
hoped that UB in this case would result in instant completion? ;)


Good catch; I read too hastily (perhaps infected by
the O.P.'s emphasis on speed).
 
J

Justin Robbs

Justin Robbs said:
I need to fill a number of character fields with spaces or zero's
depending on the field. Which method is faster.

char var[10] = " ";
var[9] = '\0';

I usually don't initialize my char's and forgot about the null
terminator at the end.
or

char var[10];
sprintf( var, " " );

or

char var[10];
strcpy( var, " " );
var[9] = '\0';

I usually don't use strcpy and forgot about the null terminator
at the end.
or

int i;
char var[10];
for(i=0; i<10; i++)

Sorry, I went to fast this should obviously be for(i=0;i<9;i++)
{
var = ' ';
}
var = '\0';

Thanks for the help.

Justin


This is kind of a reply to all regarding whether this will make a
realistic difference in speed. I hope it is not bad form to
respond this way.

I am writing a routine to send Credit Card transactions to the
authorizer. Obviously the biggest speed issue will be the
network speed, however, I was just trying to cut down the amount
of time I spend preparing the transactions. It is not just one
field that needs to be set to spaces. The authorizer sent me the
record layout for the authorization request. This layout is a
catch all that contains a number of fields that I won't need.
For example, there is approximately 100 char's dedicated to
shipping address that need to be set to spaces. This is being
developed for a convenience store so shipping address is not
really necessary. There are also fields for dealing with
reversals, PIN data, and various card specific fields that will
only be used in certain situations.

I appreciate the helpful responses. I actually figured that for
loop would be slower than the function calls. I am a self taught
C programmer so I am kind of learning by necessity. I know it is
trivial to be concerned with these small amounts of time savings,
I try to use a common sense approach to making my code run
quickly and cleanly. A lot of small savings add up to larger
ones eventually. Plus, this knowledge may help make a more
significant time savings in a project further down the road.

Thanks,
Justin
 
J

Justin Robbs

Dan Pop said:
In <[email protected]> Eric Sosman
Justin said:
int i;
char var[10];
for(i=0; i<10; i++)
{
var = ' ';
}
var = '\0';


Why set var[9] to a space, only to turn right around and
overwrite the space with a zero?


That's NOT what the code is doing. It's the non-existing var[10] that
is set to zero, to generate lots of fun at debug time ;-)
You could save time (HUGE
amounts of time ;-) by stopping the loop after nine iterations
instead of ten.

Nah, that would make the code boringly correct.


Where is the fun of programming without tiny buffer overflows
that are difficult to detect and cause weird problems that make
you bang your head against the wall? I actually prefer the
larger ones that cause segmentation violation errors. It is
really fun to code for several days, set up a test and watch it
go splat.

Justin
 
D

Dan Pop

I am writing a routine to send Credit Card transactions to the
authorizer. Obviously the biggest speed issue will be the
network speed, however, I was just trying to cut down the amount
of time I spend preparing the transactions. It is not just one
field that needs to be set to spaces. The authorizer sent me the
record layout for the authorization request. This layout is a
catch all that contains a number of fields that I won't need.
For example, there is approximately 100 char's dedicated to
shipping address that need to be set to spaces. This is being
developed for a convenience store so shipping address is not
really necessary. There are also fields for dealing with
reversals, PIN data, and various card specific fields that will
only be used in certain situations.

If you can map this layout with a C structure, you can create an
initialiser object of that type and perform all the initialisations
with a simple struct assignment. Hard to beat, performance-wise.
I appreciate the helpful responses. I actually figured that for
loop would be slower than the function calls. I am a self taught
C programmer so I am kind of learning by necessity. I know it is
trivial to be concerned with these small amounts of time savings,
I try to use a common sense approach to making my code run
quickly and cleanly. A lot of small savings add up to larger
ones eventually.

Or not... Pay attention to the parts of the code requiring most of the
CPU cycles and optimise them at algorithm level, if possible, rather than
at implementation level. This is where the significant savings come from.
Plus, this knowledge may help make a more
significant time savings in a project further down the road.

The time spent in initialisations hardly matters in most real world
projects...

Dan
 
C

CBFalconer

Justin said:
.... snip ...

I am writing a routine to send Credit Card transactions to the
authorizer. Obviously the biggest speed issue will be the
network speed, however, I was just trying to cut down the amount
of time I spend preparing the transactions. It is not just one
field that needs to be set to spaces. The authorizer sent me the
record layout for the authorization request. This layout is a
catch all that contains a number of fields that I won't need.
For example, there is approximately 100 char's dedicated to
shipping address that need to be set to spaces. This is being
developed for a convenience store so shipping address is not
really necessary. There are also fields for dealing with
reversals, PIN data, and various card specific fields that will
only be used in certain situations.

Then, unless memory space is critical, the following might have
the minimum futzing about, and might also be the fastest method:

typedef struct rcd {
/* fields */
} rcd;

rcd blankrcd = { /* initializer statements */

......

whatever function initandsend(/* datafields */)
{
rcd therecord;

rcd = blankrcd;
/* code to set only needed fields */
/* code to send it out */
}
 
J

Justin Robbs

CBFalconer said:
Then, unless memory space is critical, the following might have
the minimum futzing about, and might also be the fastest method:

typedef struct rcd {
/* fields */
} rcd;

rcd blankrcd = { /* initializer statements */

.....

whatever function initandsend(/* datafields */)
{
rcd therecord;

rcd = blankrcd;
/* code to set only needed fields */
/* code to send it out */
}

That, my friend, is an excellent solution. All this talk about
improving the algorythm had me thinking about how to do that. I
could figure out any good solution other than manually
initializing the fields as described in the other posts. That is
just what I was looking for.

Have a good one.

Justin
 
J

Justin Robbs

Dan Pop said:
In <[email protected]> "Justin Robbs"

If you can map this layout with a C structure, you can create an
initialiser object of that type and perform all the initialisations
with a simple struct assignment. Hard to beat, performance-wise.

I read CBFalconer's response first but if I am understanding what
you are saying, it appears to be the same suggestion. Thanks for
the help.
Or not... Pay attention to the parts of the code requiring most of the
CPU cycles and optimise them at algorithm level, if possible, rather than
at implementation level. This is where the significant savings come from.


The time spent in initialisations hardly matters in most real world
projects...

I was just going on the theory of I could drive a semi to work or
a hybrid car, but since I only live 3/4 of a mile from work it
makes precious little difference to the environment. However, I
still feel like I am doing my part by not driving a giant fuel
guzzler. The same thinking applies here. I don't want to incur
a performance penalty when I can just code it efficiently from
the beginning. Were I trying to fix a performance bottle neck
this would be a drop in the bucket? However, since this is all
new code, I might as well do it right from the beginning.

Thanks,
Justin
 
S

Sam Dennis

Justin said:
[How to initialise an array of characters most quickly]
I don't want to incur a performance penalty when I can just code it
efficiently from the beginning. [...] However, since this is all new
code, I might as well do it right from the beginning.

Doing it correctly means doing the obvious thing, which could save time
for you and anyone trying to comprehend it; this time can be used to do
the real optimisations, if you like.
I was just going on the theory of I could drive a semi to work or
a hybrid car, but since I only live 3/4 of a mile from work it
makes precious little difference to the environment.

I suppose that walking a mile and a half every day is completely out of
the question, then?
 
C

Christopher Benson-Manica

Eric Sosman said:
Good catch; I read too hastily (perhaps infected by
the O.P.'s emphasis on speed).

Well, to be fair, John Carson's post is what showed it to me, so
(unfortunately) I can't claim any credit.
 
N

Nils Petter Vaskinn

On Wed, 21 Apr 2004 13:46:29 -0600, Justin Robbs wrote:

[snip optimizing program]
I was just going on the theory of I could drive a semi to work or
a hybrid car, but since I only live 3/4 of a mile from work it
makes precious little difference to the environment. However, I
still feel like I am doing my part by not driving a giant fuel
guzzler.

Suppose the building of a hybrid car cause more pollution than
building a giant fuel guzzler. Then suppose the saved pollution during
the lifetime of the car is smaller than the extra pollution in
production.

(This is probably not the case, I'm just adapting your analogy to fit
what is often the case in the world of programming)
The same thinking applies here. I don't want to incur
a performance penalty when I can just code it efficiently from
the beginning.

Often programmer time is much more expensive than CPU time, (the
production vs use analogy), don't waste time micromanaging code unless
you _know_ that the performance of that particular piece of code is
critical.
Were I trying to fix a performance bottle neck
this would be a drop in the bucket? However, since this is all
new code, I might as well do it right from the beginning.

And Dan and CBFs suggestion of using a struct is great for making it
right from the beginning. It's certainly easier (and thus less likely
that you make an error) than manually initializing each and every
field.

Also the suggestion to paying attention to the algorithm before
micromanaging code is a good one, it doesn't help finding the pirfect
tire rubber mixture to make a car go faster if the problems ist that
the wheels are square.

Crossposted and followups set to comp.programming since this no longer
has anything to do specifically with C
 
J

Justin Robbs

Nils Petter Vaskinn said:
On Wed, 21 Apr 2004 13:46:29 -0600, Justin Robbs wrote:

[snip optimizing program]
I was just going on the theory of I could drive a semi to work or
a hybrid car, but since I only live 3/4 of a mile from work it
makes precious little difference to the environment. However, I
still feel like I am doing my part by not driving a giant fuel
guzzler.

Suppose the building of a hybrid car cause more pollution than
building a giant fuel guzzler. Then suppose the saved pollution during
the lifetime of the car is smaller than the extra pollution in
production.

(This is probably not the case, I'm just adapting your analogy to fit
what is often the case in the world of programming)
The same thinking applies here. I don't want to incur
a performance penalty when I can just code it efficiently from
the beginning.

Often programmer time is much more expensive than CPU time, (the
production vs use analogy), don't waste time micromanaging code unless
you _know_ that the performance of that particular piece of code is
critical.
Were I trying to fix a performance bottle neck
this would be a drop in the bucket? However, since this is all
new code, I might as well do it right from the beginning.

And Dan and CBFs suggestion of using a struct is great for making it
right from the beginning. It's certainly easier (and thus less likely
that you make an error) than manually initializing each and every
field.

Also the suggestion to paying attention to the algorithm before
micromanaging code is a good one, it doesn't help finding the pirfect
tire rubber mixture to make a car go faster if the problems ist that
the wheels are square.

I understand the point about finding a better algorithm. My
point was that since I am starting from scratch, I should start
with a good foundation. While my search didn't yield much of a
benefit from the performance standpoint. I did find a much
better way to get the job done. This new method is both faster
and more reliable (due to the reduced chance for programmer
error). Therefore, I think my search has been fruitful and it
was well worth my time posting.

I didn't get the answer I expected, but I did get a solution that
is better on several levels. I don't see what the problem is.
In a different situation I would obviously focus on the algorithm
for a performance increase, but the algorithm was simple here.
Get the transaction data and card data, format it correctly, and
send it to the card host. I am just trying to perform these
steps in the best way.

Thanks,
Justin
 
G

Grant Austin

One of my favorite CS Quotes and a good point of wisdom:

"Premature optimization is the root of all evil
(or at least most of it) in programming."

- Donald Knuth
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,044
Latest member
RonaldNen

Latest Threads

Top