How do the execution speeds of snprintf and strncat compare?
I have a program which concatenates some number of strings in a buffer.
I was using strncpy before. After looking into some suggetions on web to use snprintf instead of strncat, I switched to snprintf. However, I have noticed a delay in execution of this part of program(string concatenat开发者_运维百科ion) then before. Is this possible, that snprintf can slow down the program exucution speed? If not then I will look for some other factors in my program.
if(iOffset<MAX_BUFF_SIZE && iOffset>0)
{
.......
iOffset += snprintf(cBuff+iOffset, sizeof(cBuff)-iOffset, "%s", "String1");
......
}
I repeat the above code snippet like 12 times in order to append strings to cBuff.
Edit : It repeats 12 times after each 1 sec.
There are a couple of suggestions that come to mind:
- don't optimize your program too early
- when you're ready to optimize, use a tool like a profiler to discover where the real slow downs are
If you're not familiar with profiling, or are really eager to know the timing details you can always include timers around your code. See references on gettimeofday() or clock() and the appropriate caveats about those codes. Essentially you can get the time before execution, the time after and compare them. Comment out your line of code and put in the old code and time it.
With all that said ... that's part of what a profiler does for you. Figuring out "why" something is slow is sometimes complex because there may be other considerations going on (ie at the hardware level) that you're not aware of.
The execution of a function 12 times is probably trivial compared to the total execution time of the program.
strncat
suffers from the Schlemiel the Painter problem. The way you're using snprintf
does not (though it's possible to use strncat
that way too, and sidestep the problem that way).
Copying the "repeated concatenation" idiom and just using snprintf
to do it is not genuinely following the suggestion to avoid strcat
. You should be doing something like:
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);
This will be a lot faster than repeated calls to snprintf
, which would incur a lot of overhead for each call, and it would actually be using the idiom correctly.
Assuming that you take into account the issue that Chris Jester-Young referred to, by accounting for the "Schlemiel the Painter" problem, you are likely to find that in a head to head comparison that strncat()
is quicker than snprintf()
- in the way that you are using it.
snprintf()
does have the (albeit minor, in this case) overhead of having to parse the format string that strncat()
does not.
The snippet of code that you provided is different enough from the example given in the linked question to potentially change the comparison.
As Stephen has mentioned, for most platforms running strncpy()
12 times versus snprintf()
should produce a negligible difference. The use of a profiler would be useful here to make sure that you're concentrating on the right area.
In the example that you have provided you are trying to append a const string to your buffer. If that is what you're doing in your real code (rather than just as a simple example) and the string copying is really a significant area of execution time, you might be able to optimise that area.
One common method of optimisation is to find calculations that can be pre-computed at compile time, rather than at execution time. If you are only interested in handling const strings you may be able to effectively precompute the length of the strings and then use memcpy()
, instead of strncpy()
to perform the string append. memcpy()
is typically very well optimised to your platform.
Of course such a solution would be at the expense of having to take more care of buffer overflows and pointer arithmetic.
I'm not a profiler, so I can't say for sure what is slow.
As @chris mentions, strncat can do more work than it needs to in finding the end of the destination string over and over. You might have been able to mitigate that since it appears you are tracking space consumed, so you can start from the end on each subsequent call.
On the other hand, snprintf likely has to do extra work compared to a strcat or strcpy, because it must parse the "%s" on each call to figure out how to deal with the variable argument list.
I'm not surprised that strncat could run faster, especially in the absence of aggressive optimization levels.
People who mentioned not to optimize early after you noticed a slow down are silly. In this case, you don't even need to run a profiler. You already have empirical evidence switching to snprintf slowed down your program.
I work in the financial industry where performance is key and almost always prefer sprintf to snprintf. It is possible to write fast and stable apps with it within a tigthly controlled environment.
精彩评论