How efficient is std::string compared to null-terminated strings? - c++

I've discovered that std::strings are very slow compared to old-fashioned null-terminated strings, so much slow that they significantly slow down my overall program by a factor of 2.
I expected STL to be slower, I didn't realise it was going to be this much slower.
I'm using Visual Studio 2008, release mode. It shows assignment of a string to be 100-1000 times slower than char* assignment (it's very difficult to test the run-time of a char* assignment). I know it's not a fair comparison, a pointer assignment versus string copy, but my program has lots of string assignments and I'm not sure I could use the "const reference" trick in all places. With a reference counting implementation my program would have been fine, but these implementations don't seem to exist anymore.
My real question is: why don't people use reference counting implementations anymore, and does this mean we all need to be much more careful about avoiding common performance pitfalls of std::string?
My full code is below.
#include <string>
#include <iostream>
#include <time.h>
using std::cout;
void stop()
{
}
int main(int argc, char* argv[])
{
#define LIMIT 100000000
clock_t start;
std::string foo1 = "Hello there buddy";
std::string foo2 = "Hello there buddy, yeah you too";
std::string f;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
f = foo1;
foo1 = foo2;
foo2 = f;
}
double stl = double(clock() - start) / CLOCKS\_PER\_SEC;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
}
double emptyLoop = double(clock() - start) / CLOCKS_PER_SEC;
char* goo1 = "Hello there buddy";
char* goo2 = "Hello there buddy, yeah you too";
char *g;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
g = goo1;
goo1 = goo2;
goo2 = g;
}
double charLoop = double(clock() - start) / CLOCKS_PER_SEC;
cout << "Empty loop = " << emptyLoop << "\n";
cout << "char* loop = " << charLoop << "\n";
cout << "std::string = " << stl << "\n";
cout << "slowdown = " << (stl - emptyLoop) / (charLoop - emptyLoop) << "\n";
std::string wait;
std::cin >> wait;
return 0;
}

Well there are definitely known problems regarding the performance of strings and other containers. Most of them have to do with temporaries and unnecessary copies.
It's not too hard to use it right, but it's also quite easy to Do It Wrong. For example, if you see your code accepting strings by value where you don't need a modifiable parameter, you Do It Wrong:
// you do it wrong
void setMember(string a) {
this->a = a; // better: swap(this->a, a);
}
You better had taken that by const reference or done a swap operation inside, instead of yet another copy. Performance penalty increases for a vector or list in that case. However, you are right definitely that there are known problems. For example in this:
// let's add a Foo into the vector
v.push_back(Foo(a, b));
We are creating one temporary Foo just to add a new Foo into our vector. In a manual solution, that might create the Foo directly into the vector. And if the vector reaches its capacity limit, it has to reallocate a larger memory buffer for its elements. What does it do? It copies each element separately to their new place using their copy constructor. A manual solution might behave more intelligent if it knows the type of the elements before-hand.
Another common problem is introduced temporaries. Have a look at this
string a = b + c + e;
There are loads of temporaries created, which you might avoid in a custom solution that you actually optimize onto performance. Back then, the interface of std::string was designed to be copy-on-write friendly. However, with threads becoming more popular, transparent copy on write strings have problems keeping their state consistent. Recent implementations tend to avoid copy on write strings and instead apply other tricks where appropriate.
Most of those problems are solved however for the next version of the Standard. For example instead of push_back, you can use emplace_back to directly create a Foo into your vector
v.emplace_back(a, b);
And instead of creating copies in a concatenation above, std::string will recognize when it concatenates temporaries and optimize for those cases. Reallocation will also avoid making copies, but will move elements where appropriate to their new places.
For an excellent read, consider Move Constructors by Andrei Alexandrescu.
Sometimes, however, comparisons also tend to be unfair. Standard containers have to support the features they have to support. For example if your container does not keep map element references valid while adding/removing elements from your map, then comparing your "faster" map to the standard map can become unfair, because the standard map has to ensure that elements keep being valid. That was just an example, of course, and there are many such cases that you have to keep in mind when stating "my container is faster than standard ones!!!".

It looks like you're misusing char* in the code you pasted. If you have
std::string a = "this is a";
std::string b = "this is b"
a = b;
you're performing a string copy operation. If you do the same with char*, you're performing a pointer copy operation.
The std::string assignment operation allocates enough memory to hold the contents of b in a, then copies each character one by one. In the case of char*, it does not do any memory allocation or copy the individual characters one by one, it just says "a now points to the same memory that b is pointing to."
My guess is that this is why std::string is slower, because it's actually copying the string, which appears to be what you want. To do a copy operation on a char* you'd need to use the strcpy() function to copy into a buffer that's already appropriately sized. Then you'll have an accurate comparison. But for the purposes of your program you should almost definitely use std::string instead.

When writing C++ code using any utility class (whether STL or your own) instead of eg. good old C null terminated strings, you need to rememeber a few things.
If you benchmark without compiler optimisations on (esp. function inlining), classes will lose. They are not built-ins, even stl. They are implemented in terms of method calls.
Do not create unnesessary objects.
Do not copy objects if possible.
Pass objects as references, not copies, if possible,
Use more specialised method and functions and higher level algorithms. Eg.:
std::string a = "String a"
std::string b = "String b"
// Use
a.swap(b);
// Instead of
std::string tmp = a;
a = b;
b = tmp;
And a final note. When your C-like C++ code starts to get more complex, you need to implement more advanced data structures like automatically expanding arrays, dictionaries, efficient priority queues. And suddenly you realise that its a lot of work and your classes are not really faster then stl ones. Just more buggy.

You are most certainly doing something wrong, or at least not comparing "fairly" between STL and your own code. Of course, it's hard to be more specific without code to look at.
It could be that you're structuring your code using STL in a way that causes more constructors to run, or not re-using allocated objects in a way that matches what you do when you implement the operations yourself, and so on.

This test is testing two fundamentally different things: a shallow copy vs. a deep copy. It's essential to understand the difference and how to avoid deep copies in C++ since a C++ object, by default, provides value semantics for its instances (as with the case with plain old data types) which means that assigning one to the other is generally going to copy.
I "corrected" your test and got this:
char* loop = 19.921
string = 0.375
slowdown = 0.0188244
Apparently we should cease using C-style strings since they are soooo much slower! In actuality, I deliberately made my test as flawed as yours by testing shallow copying on the string side vs. strcpy on the :
#include <string>
#include <iostream>
#include <ctime>
using namespace std;
#define LIMIT 100000000
char* make_string(const char* src)
{
return strcpy((char*)malloc(strlen(src)+1), src);
}
int main(int argc, char* argv[])
{
clock_t start;
string foo1 = "Hello there buddy";
string foo2 = "Hello there buddy, yeah you too";
start = clock();
for (int i=0; i < LIMIT; i++)
foo1.swap(foo2);
double stl = double(clock() - start) / CLOCKS_PER_SEC;
char* goo1 = make_string("Hello there buddy");
char* goo2 = make_string("Hello there buddy, yeah you too");
char *g;
start = clock();
for (int i=0; i < LIMIT; i++) {
g = make_string(goo1);
free(goo1);
goo1 = make_string(goo2);
free(goo2);
goo2 = g;
}
double charLoop = double(clock() - start) / CLOCKS_PER_SEC;
cout << "char* loop = " << charLoop << "\n";
cout << "string = " << stl << "\n";
cout << "slowdown = " << stl / charLoop << "\n";
string wait;
cin >> wait;
}
The main point is, and this actually gets to the heart of your ultimate question, you have to know what you are doing with the code. If you use a C++ object, you have to know that assigning one to the other is going to make a copy of that object (unless assignment is disabled, in which case you'll get an error). You also have to know when it's appropriate to use a reference, pointer, or smart pointer to an object, and with C++11, you should also understand the difference between move and copy semantics.
My real question is: why don't people use reference counting
implementations anymore, and does this mean we all need to be much
more careful about avoiding common performance pitfalls of
std::string?
People do use reference-counting implementations. Here's an example of one:
shared_ptr<string> ref_counted = make_shared<string>("test");
shared_ptr<string> shallow_copy = ref_counted; // no deep copies, just
// increase ref count
The difference is that string doesn't do it internally as that would be inefficient for those who don't need it. Things like copy-on-write are generally not done for strings either anymore for similar reasons (plus the fact that it would generally make thread safety an issue). Yet we have all the building blocks right here to do copy-on-write if we wish to do so: we have the ability to swap strings without any deep copying, we have the ability to make pointers, references, or smart pointers to them.
To use C++ effectively, you have to get used to this way of thinking involving value semantics. If you don't, you might enjoy the added safety and convenience but do it at heavy cost to the efficiency of your code (unnecessary copies are certainly a significant part of what makes poorly written C++ code slower than C). After all, your original test is still dealing with pointers to strings, not char[] arrays. If you were using character arrays and not pointers to them, you'd likewise need to strcpy to swap them. With strings you even have a built-in swap method to do exactly what you are doing in your test efficiently, so my advice is to spend a bit more time learning C++.

If you have an indication of the eventual size of your vector you can prevent excessive resizes by calling reserve() before filling it up.

The main rules of optimization:
Rule 1: Don't do it.
Rule 2: (For experts only) Don't do it yet.
Are you sure that you have proven that it is really the STL that is slow, and not your algorithm?

Good performance isn't always easy with STL, but generally, it is designed to give you the power. I found Scott Meyers' "Effective STL" an eye-opener for understanding how to deal with the STL efficiently. Read!
As others said, you are probably running into frequent deep copies of the string, and compare that to a pointer assignment / reference counting implementation.
Generally, any class designed towards your specific needs, will beat a generic class that's designed for the general case. But learn to use the generic class well, and learn to ride the 80:20 rules, and you will be much more efficient than someone rolling everything on their own.
One specific drawback of std::string is that it doesn't give performance guarantees, which makes sense. As Tim Cooper mentioned, STL does not say whether a string assignment creates a deep copy. That's good for a generic class, because reference counting can become a real killer in highly concurrent applications, even though it's usually the best way for a single threaded app.

They didn't go wrong. STL implementation is generally speaking better than yours.
I'm sure that you can write something better for a very particular case, but a factor of 2 is too much... you really must be doing something wrong.

If used correctly, std::string is as efficient as char*, but with the added protection.
If you are experiencing performance problems with the STL, it's likely that you are doing something wrong.
Additionally, STL implementations are not standard across compilers. I know that SGI's STL and STLPort perform generally well.
That said, and I am being completely serious, you could be a C++ genius and have devised code that is far more sophisticated than the STL. It's not likely , but who knows, you could be the LeBron James of C++.

I would say that STL implementations are better than the traditional implementations. Also did you try using a list instead of a vector, because vector is efficient for some purpose and list is efficient for some other

std::string will always be slower than C-strings. C-strings are simply a linear array of memory. You cannot get any more efficient than that, simply as a data structure. The algorithms you use (like strcat() or strcpy()) are generally equivalent to the STL counterparts. The class instantiation and method calls will be, in relative terms, significantly slower than C-string operations (even worse if the implementation uses virtuals). The only way you could get equivalent performance is if the compiler does optimization.

string const string& char* Java string
---------------------------------------------------------------------------------------------------
Efficient no ** yes yes yes
assignment
Thread-safe yes yes yes yes
memory management yes no no yes
done for you
** There are 2 implementations of std::string: reference counting or deep-copy. Reference counting introduces performance problems in multi-threaded programs, EVEN for just reading strings, and deep-copy is obviously slower as shown above. See:
Why VC++ Strings are not reference counted?
As this table shows, 'string' is better than 'char*' in some ways and worse in others, and 'const string&' is similar in properties to 'char*'. Personally I'm going to continue using 'char*' in many places. The enormous amount of copying of std::string's that happens silently, with implicit copy constructors and temporaries makes me somewhat ambivalent about std::string.

A large part of the reason might be the fact that reference-counting is no longer used in modern implementations of STL.
Here's the story (someone correct me if I'm wrong): in the beginning, STL implementations used reference counting, and were fast but not thread-safe - the implementors expected application programmers to insert their own locking mechanisms at higher levels, to make them thread-safe, because if locking was done at 2 levels then this would slow things down twice as much.
However, the programmers of the world were too ignorant or lazy to insert locks everywhere. For example, if a worker thread in a multi-threaded program needed to read a std::string commandline parameter, then a lock would be needed even just to read the string, otherwise crashes could ensue. (2 threads increment the reference count simultaneously on different CPU's (+1), but decrement it separately (-2), so the reference count goes down to zero, and the memory is freed.)
So implementors ditched reference counting and instead had each std::string always own its own copy of the string. More programs worked, but they were all slower.
So now, even a humble assignment of one std::string to another, (or equivalently, passing a std::string as a parameter to a function), takes about 400 machine code instructions instead of the 2 it takes to assign a char*, a slowdown of 200 times.
I tested the magnitude of the inefficiency of std::string on one major program, which had an overall slowdown of about 100% compared with null-terminated strings. I also tested raw std::string assignment using the following code, which said that std::string assignment was 100-900 times slower. (I had trouble measuring the speed of char* assignment). I also debugged into the std::string operator=() function - I ended up knee deep in the stack, about 7 layers deep, before hitting the 'memcpy()'.
I'm not sure there's any solution. Perhaps if you need your program to be fast, use plain old C++, and if you're more concerned about your own productivity, you should use Java.
#define LIMIT 800000000
clock_t start;
std::string foo1 = "Hello there buddy";
std::string foo2 = "Hello there buddy, yeah you too";
std::string f;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
f = foo1;
foo1 = foo2;
foo2 = f;
}
double stl = double(clock() - start) / CLOCKS_PER_SEC;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
}
double emptyLoop = double(clock() - start) / CLOCKS_PER_SEC;
char* goo1 = "Hello there buddy";
char* goo2 = "Hello there buddy, yeah you too";
char *g;
start = clock();
for (int i=0; i < LIMIT; i++) {
stop();
g = goo1;
goo1 = goo2;
goo2 = g;
}
double charLoop = double(clock() - start) / CLOCKS_PER_SEC;
TfcMessage("done", 'i', "Empty loop = %1.3f s\n"
"char* loop = %1.3f s\n"
"std::string loop = %1.3f s\n\n"
"slowdown = %f",
emptyLoop, charLoop, stl,
(stl - emptyLoop) / (charLoop - emptyLoop));

Related

C++ constructor performance

In C++17 if we design a class like this:
class Editor {
public:
// "copy" constructor
Editor(const std::string& text) : _text {text} {}
// "move" constructor
Editor(std::string&& text) : _text {std::move(text)} {}
private:
std::string _text;
}
It might seem (to me at least), that the "move" constructor should be much faster than the "copy" constructor.
But if we try to measure actual times, we will see something different:
int current_time()
{
return chrono::high_resolution_clock::now().time_since_epoch().count();
}
int main()
{
int N = 100000;
auto t0 = current_time();
for (int i = 0; i < N; i++) {
std::string a("abcdefgh"s);
Editor {a}; // copy!
}
auto t1 = current_time();
for (int i = 0; i < N; i++) {
Editor {"abcdefgh"s};
}
auto t2 = current_time();
cout << "Copy: " << t1 - t0 << endl;
cout << "Move: " << t2 - t1 << endl;
}
Both copy and move times are in the same range. Here's one of the outputs:
Copy: 36299550
Move: 35762602
I tried with strings as long as 285604 characters, with the same result.
Question: why is "copy" constructor Editor(std::string& text) : _text {text} {} so fast? Doesn't it actually creates a copy of input string?
Update I run the benchmark given here using the following line: g++ -std=c++1z -O2 main.cpp && ./a.out
Update 2 Fixing move constructor, as #Caleth suggests (remove const from the const std::string&& text) improves things!
Editor(std::string&& text) : _text {std::move(text)} {}
Now benchmark looks like:
Copy: 938647
Move: 64
It also depends on your optimization flags. With no optimization, you can (and I did!) get even worse results for the move:
Copy: 4164540
Move: 6344331
Running the same code with -O2 optimization gives a much different result:
Copy: 1264581
Move: 791
See it live on Wandbox.
That's with clang 9.0. On GCC 9.1, the difference is about the same for -O2 and -O3 but not quite as stark between copy and move:
Copy: 775
Move: 508
I'm guessing that's a small string optimization kicking in.
In general, the containers in the standard library work best with optimizations on because they have a lot of little functions that the compiler can easily inline and collapse when asked to do so.
Also in that first constructor, per Herb Sutter, "Prefer passing a read-only parameter by value if you’re going to make a copy of the parameter anyway, because it enables move from rvalue arguments."
Update: For very long strings (300k characters), the results are similar to the above (now using std::chrono::duration in milliseconds to avoid int overflows) with GCC 9.1 and optimizations:
Copy: 22560
Move: 1371
and without optimizations:
Copy: 22259
Move: 1404
const std::string&& looks like a typo.
You can't move from it, so you get a copy instead.
So your tests is really looking at the number of times we have to "build" a string object.
So in the fist test:
for (int i = 0; i < N; i++) {
std::string a("abcdefgh"s); // Build a string once.
Editor {a}; // copy! // Here you build the string again.
} // So basically two expensive memory
// allocations and a copying the string
While in the second test:
for (int i = 0; i < N; i++) {
Editor {"abcdefgh"s}; // You build a string once.
// Then internally you move the allocated
// memory (so only one expensive memory
// allocation and copying the string
}
So the difference between the two loops is one extra string copy.
The problem here. I as a human can spot one easy peephole optimization (and the compiler is better than me).
for (int i = 0; i < N; i++) {
std::string a("abcdefgh"s); // This string is only used in a single
// place where it is passed to a
// function as a const parameter
// So we can optimize it out of the loop.
Editor {a};
}
So if we do a manually yanking of the string outside the loop (equivalent to a valid compiler optimization).
So this loop has the same affect:
std::string a("abcdefgh"s);
for (int i = 0; i < N; i++) {
Editor {a};
}
Now this loop only has 1 allocation and copy.
So now both loops look the same in terms of the expensive operations.
Now as a human I am not going to spot (quickly) all the optimization possible. I am just trying to point out here that your quick test here you will not spot a lot of optimizations that the compiler will do and thus estimations and doing timings like this are hard.
On paper you're right, but in practice this is quite easily optimisable so you'll probably find the compiler has ruined your benchmark.
You could benchmark with "optimisations" turned off, but that in itself holds little real-world benefit. It may be possible to trick the compiler in release mode by adding some code that prevents such an optimisation, but off the top of my head I can't imagine what that would look like here.
It's also a relatively small string that can be copied really quickly nowadays.
I think you should just trust your instinct here (because it's correct), while remembering that in practice it might not actually make a lot of difference. But the move certainly won't be worse than the copy.
Sometimes we can and should write obviously "more efficient" code without being able to prove that it'll actually perform better on any particular day of the week with any particular phase of the moon/planetary alignment, because compilers are already trying to make your code as fast as possible.
People may tell you that this is therefore a "premature optimisation", but it really isn't: it's just sensible code.

Should I return reference to heap object or return value?

I have these two simple functions. I thought that func1 was a good solution since you pass an object by reference. My textbook gave func2 as the answer for the best solution. Is this only because you aren't deallocateing heapstr? What if I declared heapstr in main and then passed it to the function so I was able to delete it afterwards?
#include <iostream>
using namespace std;
string& func1(const string &str) {
string* heapstr=new string();
for (int i = 0; i < str.size(); ++i) {
*heapstr += str[i];
}
return *heapstr;
}
string func2(const string &str) {
string heapstr;
for (int i = 0; i < str.size(); ++i) {
heapstr += str[i];
}
return heapstr;
}
int main() {
cout << func1("aaa") << endl;
cout << func2("aaa") << endl;
}
Should I return reference to heap object or return value?
Return by value.
There are a lot of reasons why, but none are really related to performance, because the compiler is good enough at optimising things, and even if it wasn't, most programs are I/O-bound, i.e. the time you wait for data from files or network sockets eats up all your performance, not the time spent by CPU operations themselves.
See for example the "C++ Core Guidelines" by Herb Sutter and Bjarne Stroustrup, which say at section "Return containers by value (relying on move or copy elision for efficiency)":
Reason
To simplify code and eliminate a need for explicit memory management.
As for your two functions...
My textbook gave func2 as the answer for the best solution. Is this only because you aren't deallocateing heapstr?
The memory leak is one of the problems. But the point is simply that returning by value is simpler and less error-prone. It's all about correctness, not speed. You wouldn't return an int* if you could just return an int instead, would you?
What if I declared heapstr in main and then passed it to the function so I was able to delete it afterwards?
You would introduce a lot of possibilities for memory leaks, crashes and undefined behaviour into your code. It would become longer, harder to write, harder to read, harder to maintain, harder to debug and harder to justify in a code review. In return, you would gain absolutely nothing.
The text book is correct. (Shocker.)
Func1 is faulty in every respect in which it differs from func2. It allocates an object from the heap without regard to how that object will be deleted. Then it returns a reference to the new object, hiding the pointer that might have otherwise been used to delete it. There is no efficiency gain, in fact Func1 is probably a bit slower. In any case, recite after me: "Avoid Early Optimization."
Since the advent of the Standard Template Library, many moons ago, it is almost never best to use operator new. The last time I used operator new was ca. 2003, and I wrapped the pointer in the equivalent of what we now know as a unique_ptr. Before you use operator new, read all about learn all about smart pointers and RAII.
Since this is textbook example, you should consider its context to underestand what it wants to show exactly(its goal is to minimize memory usage as you or using a safe programming pattern?!). But two hint
When you use new operator to allocate memory, you must de-allocate it using delete. The code has memory leak for heapstr at func1.
Also in the more realistic projects its not safe to share objects between methods. Its management(i.e who currently modified this or who is responsible to de-allocate its memory when object is not needed longer) became hard.
PS: I do not have C++17 but it optimize following as well. For more details read #BoPersson comments.
PS: Stack allocation is faster, but in your example you have a copy operation at func2 return. In your example as #Jive Dadson said there is no difference due ot compiler optimization but in general case, suppose following code
#include <iostream>
#include <string>
using namespace std;
string& func1(const string &str) {
string* heapstr = new string();
cout << "func1 " << heapstr << endl;
for (int i = 0; i < str.size(); ++i) {
*heapstr += str[i];
}
return *heapstr;
}
string func2(const string &str) {
string heapstr;
for (int i = 0; i < str.size(); ++i) {
heapstr += str[i];
}
cout << &heapstr << endl;
return heapstr;
}
int main() {
string a = func1("aaa");
string b = func2("aaa");
cout << "main " << a << endl;
}
PS: (As #Jive Dadson said there is no difference in your example, but in mine)If we define performance as run time, maybe func1. Also if we define performance as memory usage, func1. If we define performance as good programming pattern, func2. Totally func2 is more preferred.

memcpy vs for loop - What's the proper way to copy an array from a pointer?

I have a function foo(int[] nums) which I understand is essentially equivalent to foo(int* nums). Inside foo I need to copy the contents of the array pointed to by numsinto some int[10] declared within the scope of foo. I understand the following is invalid:
void foo (int[] nums)
{
myGlobalArray = *nums
}
What is the proper way to copy the array? Should I use memcpy like so:
void foo (int[] nums)
{
memcpy(&myGlobalArray, nums, 10);
}
or should I use a for loop?
void foo(int[] nums)
{
for(int i =0; i < 10; i++)
{
myGlobalArray[i] = nums[i];
}
}
Is there a third option that I'm missing?
Yes, the third option is to use a C++ construct:
std::copy(&nums[0], &nums[10], myGlobalArray);
With any sane compiler, it:
should be optimum in the majority of cases (will compile to memcpy() where possible),
is type-safe,
gracefully copes when you decide to change the data-type to a non-primitive (i.e. it calls copy constructors, etc.),
gracefully copes when you decide to change to a container class.
Memcpy will probably be faster, but it's more likely you will make a mistake using it.
It may depend on how smart your optimizing compiler is.
Your code is incorrect though. It should be:
memcpy(myGlobalArray, nums, 10 * sizeof(int) );
Generally speaking, the worst case scenario will be in an un-optimized debug build where memcpy is not inlined and may perform additional sanity/assert checks amounting to a small number of additional instructions vs a for loop.
However memcpy is generally well implemented to leverage things like intrinsics etc, but this will vary with target architecture and compiler. It is unlikely that memcpy will ever be worse than a for-loop implementation.
People often trip over the fact that memcpy sizes in bytes, and they write things like these:
// wrong unless we're copying bytes.
memcpy(myGlobalArray, nums, numNums);
// wrong if an int isn't 4 bytes or the type of nums changed.
memcpy(myGlobalArray, nums, numNums);
// wrong if nums is no-longer an int array.
memcpy(myGlobalArray, nums, numNums * sizeof(int));
You can protect yourself here by using language features that let you do some degree of reflection, that is: do things in terms of the data itself rather than what you know about the data, because in a generic function you generally don't know anything about the data:
void foo (int* nums, size_t numNums)
{
memcpy(myGlobalArray, nums, numNums * sizeof(*nums));
}
Note that you don't want the "&" infront of "myGlobalArray" because arrays automatically decay to pointers; you were actually copying "nums" to the address in memory where the pointer to the myGlobalArray[0] was being held.
(Edit note: I'd typo'd int[] nums when I mean't int nums[] but I decided that adding C array-pointer-equivalence chaos helped nobody, so now it's int *nums :))
Using memcpy on objects can be dangerous, consider:
struct Foo {
std::string m_string;
std::vector<int> m_vec;
};
Foo f1;
Foo f2;
f2.m_string = "hello";
f2.m_vec.push_back(42);
memcpy(&f1, &f2, sizeof(f2));
This is the WRONG way to copy objects that aren't POD (plain old data). Both f1 and f2 now have a std::string that thinks it owns "hello". One of them is going to crash when they destruct, and they both think they own the same vector of integers that contains 42.
The best practice for C++ programmers is to use std::copy:
std::copy(nums, nums + numNums, myGlobalArray);
Note per Remy Lebeau or since C++11
std::copy_n(nums, numNums, myGlobalArray);
This can make compile time decisions about what to do, including using memcpy or memmove and potentially using SSE/vector instructions if possible. Another advantage is that if you write this:
struct Foo {
int m_i;
};
Foo f1[10], f2[10];
memcpy(&f1, &f2, sizeof(f1));
and later on change Foo to include a std::string, your code will break. If you instead write:
struct Foo {
int m_i;
};
enum { NumFoos = 10 };
Foo f1[NumFoos], f2[NumFoos];
std::copy(f2, f2 + numFoos, f1);
the compiler will switch your code to do the right thing without any additional work for you, and your code is a little more readable.
For performance, use memcpy (or equivalents). It's highly optimised platform-specific code for shunting lots of data around fast.
For maintainability, consider what you're doing - the for loop may be more readable and easier to understand. (Getting a memcpy wrong is a fast route to a crash or worse)
Essentially, as long as you are dealing with POD types (Plain Ol' Data), such as int, unsigned int, pointers, data-only structs, etc... you are safe to use mem*.
If your array contains objects, use the for loop, as the = operator may be required to ensure proper assignment.
A simple loop is slightly faster for about 10-20 bytes and less (It's a single compare+branch, see OP_T_THRES), but for larger sizes, memcpy is faster and portable.
Additionally, if the amount of memory you want to copy is constant, you can use memcpy to let the compiler decide what method to use.
Side note: the optimizations that memcpy uses may significantly slow your program down in a multithreaded environment when you're copying a lot of data above the OP_T_THRES size mark since the instructions this invokes are not atomic and the speculative execution and caching behavior for such instructions doesn't behave nicely when multiple threads are accessing the same memory. Easiest solution is to not share memory between threads and only merge the memory at the end. This is good multi-threading practice anyway.

Very poor boost::lexical_cast performance

Windows XP SP3. Core 2 Duo 2.0 GHz.
I'm finding the boost::lexical_cast performance to be extremely slow. Wanted to find out ways to speed up the code. Using /O2 optimizations on visual c++ 2008 and comparing with java 1.6 and python 2.6.2 I see the following results.
Integer casting:
c++:
std::string s ;
for(int i = 0; i < 10000000; ++i)
{
s = boost::lexical_cast<string>(i);
}
java:
String s = new String();
for(int i = 0; i < 10000000; ++i)
{
s = new Integer(i).toString();
}
python:
for i in xrange(1,10000000):
s = str(i)
The times I'm seeing are
c++: 6700 milliseconds
java: 1178 milliseconds
python: 6702 milliseconds
c++ is as slow as python and 6 times slower than java.
Double casting:
c++:
std::string s ;
for(int i = 0; i < 10000000; ++i)
{
s = boost::lexical_cast<string>(d);
}
java:
String s = new String();
for(int i = 0; i < 10000000; ++i)
{
double d = i*1.0;
s = new Double(d).toString();
}
python:
for i in xrange(1,10000000):
d = i*1.0
s = str(d)
The times I'm seeing are
c++: 56129 milliseconds
java: 2852 milliseconds
python: 30780 milliseconds
So for doubles c++ is actually half the speed of python and 20 times slower than the java solution!!. Any ideas on improving the boost::lexical_cast performance? Does this stem from the poor stringstream implementation or can we expect a general 10x decrease in performance from using the boost libraries.
Edit 2012-04-11
rve quite rightly commented about lexical_cast's performance, providing a link:
http://www.boost.org/doc/libs/1_49_0/doc/html/boost_lexical_cast/performance.html
I don't have access right now to boost 1.49, but I do remember making my code faster on an older version. So I guess:
the following answer is still valid (if only for learning purposes)
there was probably an optimization introduced somewhere between the two versions (I'll search that)
which means that boost is still getting better and better
Original answer
Just to add info on Barry's and Motti's excellent answers:
Some background
Please remember Boost is written by the best C++ developers on this planet, and reviewed by the same best developers. If lexical_cast was so wrong, someone would have hacked the library either with criticism or with code.
I guess you missed the point of lexical_cast's real value...
Comparing apples and oranges.
In Java, you are casting an integer into a Java String. You'll note I'm not talking about an array of characters, or a user defined string. You'll note, too, I'm not talking about your user-defined integer. I'm talking about strict Java Integer and strict Java String.
In Python, you are more or less doing the same.
As said by other posts, you are, in essence, using the Java and Python equivalents of sprintf (or the less standard itoa).
In C++, you are using a very powerful cast. Not powerful in the sense of raw speed performance (if you want speed, perhaps sprintf would be better suited), but powerful in the sense of extensibility.
Comparing apples.
If you want to compare a Java Integer.toString method, then you should compare it with either C sprintf or C++ ostream facilities.
The C++ stream solution would be 6 times faster (on my g++) than lexical_cast, and quite less extensible:
inline void toString(const int value, std::string & output)
{
// The largest 32-bit integer is 4294967295, that is 10 chars
// On the safe side, add 1 for sign, and 1 for trailing zero
char buffer[12] ;
sprintf(buffer, "%i", value) ;
output = buffer ;
}
The C sprintf solution would be 8 times faster (on my g++) than lexical_cast but a lot less safe:
inline void toString(const int value, char * output)
{
sprintf(output, "%i", value) ;
}
Both solutions are either as fast or faster than your Java solution (according to your data).
Comparing oranges.
If you want to compare a C++ lexical_cast, then you should compare it with this Java pseudo code:
Source s ;
Target t = Target.fromString(Source(s).toString()) ;
Source and Target being of whatever type you want, including built-in types like boolean or int, which is possible in C++ because of templates.
Extensibility? Is that a dirty word?
No, but it has a well known cost: When written by the same coder, general solutions to specific problems are usually slower than specific solutions written for their specific problems.
In the current case, in a naive viewpoint, lexical_cast will use the stream facilities to convert from a type A into a string stream, and then from this string stream into a type B.
This means that as long as your object can be output into a stream, and input from a stream, you'll be able to use lexical_cast on it, without touching any single line of code.
So, what are the uses of lexical_cast?
The main uses of lexical casting are:
Ease of use (hey, a C++ cast that works for everything being a value!)
Combining it with template heavy code, where your types are parametrized, and as such you don't want to deal with specifics, and you don't want to know the types.
Still potentially relatively efficient, if you have basic template knowledge, as I will demonstrate below
The point 2 is very very important here, because it means we have one and only one interface/function to cast a value of a type into an equal or similar value of another type.
This is the real point you missed, and this is the point that costs in performance terms.
But it's so slooooooowwww!
If you want raw speed performance, remember you're dealing with C++, and that you have a lot of facilities to handle conversion efficiently, and still, keep the lexical_cast ease-of-use feature.
It took me some minutes to look at the lexical_cast source, and come with a viable solution. Add to your C++ code the following code:
#ifdef SPECIALIZE_BOOST_LEXICAL_CAST_FOR_STRING_AND_INT
namespace boost
{
template<>
std::string lexical_cast<std::string, int>(const int &arg)
{
// The largest 32-bit integer is 4294967295, that is 10 chars
// On the safe side, add 1 for sign, and 1 for trailing zero
char buffer[12] ;
sprintf(buffer, "%i", arg) ;
return buffer ;
}
}
#endif
By enabling this specialization of lexical_cast for strings and ints (by defining the macro SPECIALIZE_BOOST_LEXICAL_CAST_FOR_STRING_AND_INT), my code went 5 time faster on my g++ compiler, which means, according to your data, its performance should be similar to Java's.
And it took me 10 minutes of looking at boost code, and write a remotely efficient and correct 32-bit version. And with some work, it could probably go faster and safer (if we had direct write access to the std::string internal buffer, we could avoid a temporary external buffer, for example).
You could specialize lexical_cast for int and double types. Use strtod and strtol in your's specializations.
namespace boost {
template<>
inline int lexical_cast(const std::string& arg)
{
char* stop;
int res = strtol( arg.c_str(), &stop, 10 );
if ( *stop != 0 ) throw_exception(bad_lexical_cast(typeid(int), typeid(std::string)));
return res;
}
template<>
inline std::string lexical_cast(const int& arg)
{
char buffer[65]; // large enough for arg < 2^200
ltoa( arg, buffer, 10 );
return std::string( buffer ); // RVO will take place here
}
}//namespace boost
int main(int argc, char* argv[])
{
std::string str = "22"; // SOME STRING
int int_str = boost::lexical_cast<int>( str );
std::string str2 = boost::lexical_cast<std::string>( str_int );
return 0;
}
This variant will be faster than using default implementation, because in default implementation there is construction of heavy stream objects. And it is should be little faster than printf, because printf should parse format string.
lexical_cast is more general than the specific code you're using in Java and Python. It's not surprising that a general approach that works in many scenarios (lexical cast is little more than streaming out then back in to and from a temporary stream) ends up being slower than specific routines.
(BTW, you may get better performance out of Java using the static version, Integer.toString(int). [1])
Finally, string parsing and deparsing is usually not that performance-sensitive, unless one is writing a compiler, in which case lexical_cast is probably too general-purpose, and integers etc. will be calculated as each digit is scanned.
[1] Commenter "stepancheg" doubted my hint that the static version may give better performance. Here's the source I used:
public class Test
{
static int instanceCall(int i)
{
String s = new Integer(i).toString();
return s == null ? 0 : 1;
}
static int staticCall(int i)
{
String s = Integer.toString(i);
return s == null ? 0 : 1;
}
public static void main(String[] args)
{
// count used to avoid dead code elimination
int count = 0;
// *** instance
// Warmup calls
for (int i = 0; i < 100; ++i)
count += instanceCall(i);
long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; ++i)
count += instanceCall(i);
long finish = System.currentTimeMillis();
System.out.printf("10MM Time taken: %d ms\n", finish - start);
// *** static
// Warmup calls
for (int i = 0; i < 100; ++i)
count += staticCall(i);
start = System.currentTimeMillis();
for (int i = 0; i < 10000000; ++i)
count += staticCall(i);
finish = System.currentTimeMillis();
System.out.printf("10MM Time taken: %d ms\n", finish - start);
if (count == 42)
System.out.println("bad result"); // prevent elimination of count
}
}
The runtimes, using JDK 1.6.0-14, server VM:
10MM Time taken: 688 ms
10MM Time taken: 547 ms
And in client VM:
10MM Time taken: 687 ms
10MM Time taken: 610 ms
Even though theoretically, escape analysis may permit allocation on the stack, and inlining may introduce all code (including copying) into the local method, permitting elimination of redundant copying, such analysis may take quite a lot of time and result in quite a bit of code space, which has other costs in code cache that don't justify themselves in real code, as opposed to microbenchmarks like seen here.
What lexical cast is doing in your code can be simplified to this:
string Cast( int i ) {
ostringstream os;
os << i;
return os.str();
}
There is unfortunately a lot going on every time you call Cast():
a string stream is created possibly allocating memory
operator << for integer i is called
the result is stored in the stream, possibly allocating memory
a string copy is taken from the stream
a copy of the string is (possibly) created to be returned.
memory is deallocated
Thn in your own code:
s = Cast( i );
the assignment involves further allocations and deallocations are performed. You may be able to reduce this slightly by using:
string s = Cast( i );
instead.
However, if performance is really importanrt to you, you should considerv using a different mechanism. You could write your own version of Cast() which (for example) creates a static stringstream. Such a version would not be thread safe, but that might not matter for your specific needs.
To summarise, lexical_cast is a convenient and useful feature, but such convenience comes (as it always must) with trade-offs in other areas.
Unfortunately I don't have enough rep yet to comment...
lexical_cast is not primarily slow because it's generic (template lookups happen at compile-time, so virtual function calls or other lookups/dereferences aren't necessary). lexical_cast is, in my opinion, slow, because it builds on C++ iostreams, which are primarily intended for streaming operations and not single conversions, and because lexical_cast must check for and convert iostream error signals. Thus:
a stream object has to be created and destroyed
in the string output case above, note that C++ compilers have a hard time avoiding buffer copies (an alternative is to format directly to the output buffer, like sprintf does, though sprintf won't safely handle buffer overruns)
lexical_cast has to check for stringstream errors (ss.fail()) in order to throw exceptions on conversion failures
lexical_cast is nice because (IMO) exceptions allow trapping all errors without extra effort and because it has a uniform prototype. I don't personally see why either of these properties necessitate slow operation (when no conversion errors occur), though I don't know of such C++ functions which are fast (possibly Spirit or boost::xpressive?).
Edit: I just found a message mentioning the use of BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to enable an "itoa" optimisation: http://old.nabble.com/lexical_cast-optimization-td20817583.html. There's also a linked article with a bit more detail.
lexical_cast may or may not be as slow in relation to Java and Python as your bencharks indicate because your benchmark measurements may have a subtle problem. Any workspace allocations/deallocations done by lexical cast or the iostream methods it uses are measured by your benchmarks because C++ doesn't defer these operations. However, in the case of Java and Python, the associated deallocations may in fact have simply been deferred to a future garbage collection cycle and missed by the benchmark measurements. (Unless a GC cycle by chance occurs while the benchmark is in progress and in that case you'd be measuring too much). So it's hard to know for sure without examining specifics of the Java and Python implementations how much "cost" should be attributed to the deferred GC burden that may (or may not) be eventually imposed.
This kind of issue obviously may apply to many other C++ vs garbage collected language benchmarks.
As Barry said, lexical_cast is very general, you should use a more specific alternative, for example check out itoa (int->string) and atoi (string -> int).
if speed is a concern, or you are just interested in how fast such casts can be with C++, there's an interested thread regarding it.
Boost.Spirit 2.1(which is to be released with Boost 1.40) seems to be very fast, even faster than the C equivalents(strtol(), atoi() etc. ).
I use this very fast solution for POD types...
namespace DATATYPES {
typedef std::string TString;
typedef char* TCString;
typedef double TDouble;
typedef long THuge;
typedef unsigned long TUHuge;
};
namespace boost {
template<typename TYPE>
inline const DATATYPES::TString lexical_castNumericToString(
const TYPE& arg,
const DATATYPES::TCString fmt) {
enum { MAX_SIZE = ( std::numeric_limits<TYPE>::digits10 + 1 ) // sign
+ 1 }; // null
char buffer[MAX_SIZE] = { 0 };
if (sprintf(buffer, fmt, arg) < 0) {
throw_exception(bad_lexical_cast(typeid(TYPE),
typeid(DATATYPES::TString)));
}
return ( DATATYPES::TString(buffer) );
}
template<typename TYPE>
inline const TYPE lexical_castStringToNumeric(const DATATYPES::TString& arg) {
DATATYPES::TCString end = 0;
DATATYPES::TDouble result = std::strtod(arg.c_str(), &end);
if (not end or *end not_eq 0) {
throw_exception(bad_lexical_cast(typeid(DATATYPES::TString),
typeid(TYPE)));
}
return TYPE(result);
}
template<>
inline DATATYPES::THuge lexical_cast(const DATATYPES::TString& arg) {
return (lexical_castStringToNumeric<DATATYPES::THuge>(arg));
}
template<>
inline DATATYPES::TString lexical_cast(const DATATYPES::THuge& arg) {
return (lexical_castNumericToString<DATATYPES::THuge>(arg,"%li"));
}
template<>
inline DATATYPES::TUHuge lexical_cast(const DATATYPES::TString& arg) {
return (lexical_castStringToNumeric<DATATYPES::TUHuge>(arg));
}
template<>
inline DATATYPES::TString lexical_cast(const DATATYPES::TUHuge& arg) {
return (lexical_castNumericToString<DATATYPES::TUHuge>(arg,"%lu"));
}
template<>
inline DATATYPES::TDouble lexical_cast(const DATATYPES::TString& arg) {
return (lexical_castStringToNumeric<DATATYPES::TDouble>(arg));
}
template<>
inline DATATYPES::TString lexical_cast(const DATATYPES::TDouble& arg) {
return (lexical_castNumericToString<DATATYPES::TDouble>(arg,"%f"));
}
} // end namespace boost

cout or printf which of the two has a faster execution speed C++?

I have been coding in C++ for a long time. I always wondered which has a faster execution speed printf or cout?
Situation: I am designing an application in C++ and I have certain constraints such as time limit for execution. My application has loads printing commands on the console. So which one would be preferable printf or cout?
Each has its own overheads. Depending on what you print, either may be faster.
Here are two points that come to mind -
printf() has to parse the "format" string and act upon it, which adds a cost.
cout has a more complex inheritance hierarchy and passes around objects.
In practice, the difference shouldn't matter for all but the weirdest cases. If you think it really matters - measure!
EDIT -
Oh, heck, I don't believe I'm doing this, but for the record, on my very specific test case, with my very specific machine and its very specific load, compiling in Release using MSVC -
Printing 150,000 "Hello, World!"s (without using endl) takes about -
90ms for printf(), 79ms for cout.
Printing 150,000 random doubles takes about -
3450ms for printf(), 3420ms for cout.
(averaged over 10 runs).
The differences are so slim this probably means nothing...
Do you really need to care which has a faster execution speed? They are both used simply for printing text to the console/stdout, which typically isn't a task that demands ultra-high effiency. For that matter, I wouldn't imagine there to be a large difference in speed anyway (though one might expect printf to be marginally quicker because it lacks the minor complications of object-orientedness). Yet given that we're dealing with I/O operations here, even a minor difference would probably be swamped by the I/O overhead. Certainly, if you compared the equivalent methods for writing to files, that would be the case.
printf is simply the standard way to output text to stdout in C.
'cout' piping is simply the standard way to output text to stdout in C++.
Saying all this, there is a thread on the comp.lang.cc group discussing the same issue. Consensus does however seem to be that you should choose one over the other for reasons other than performance.
The reason C++ cout is slow is the default sync with stdio.
Try executing the following to deactivate this issue.
ios_base::sync_with_stdio(false)
http://www.cplusplus.com/reference/iostream/ios_base/sync_with_stdio/
http://msdn.microsoft.com/es-es/library/7yxhba01.aspx
On Windows at least, writing to the console is a huge bottleneck, so a "noisy" console mode program will be far slower than a silent one. So on that platform, slight differences in the library functions used to address the console will probably make no significant difference in practice.
On other platforms it may be different. Also it depends just how much console output you are doing, relative to other useful work.
Finally, it depends on your platform's implementation of the C and C++ I/O libraries.
So there is no general answer to this question.
Performance is a non-issue for comparison; can't think of anything where it actually counts (developing a console-program). However, there's a few points you should take into account:
Iostreams use operator chaining instead of va_args. This means that your program can't crash because you passed the wrong number of arguments. This can happen with printf.
Iostreams use operator overloading instead of va_args -- this means your program can't crash because you passed an int and it was expecting a string. This can happen with printf.
Iostreams don't have native support for format strings (which is the major root cause of #1 and #2). This is generally a good thing, but sometimes they're useful. The Boost format library brings this functionality to Iostreams for those who need it with defined behavior (throws an exception) rather than undefined behavior (as is the case with printf). This currently falls outside the standard.
Iostreams, unlike their printf equivilants, can handle variable length buffers directly themselves instead of you being forced to deal with hardcoded cruft.
Go for cout.
I recently was working on a C++ console application on windows that copied files using CopyFileEx and was echoing the 'to' and 'from' paths to the console for each copy and then displaying the average throughput at the end of the operation.
When I ran the console application using printf to echo out the strings I was getting 4mb/sec, when replacing the printf with std::cout the throughput dropped to 800kb/sec.
I was wondering why the std::cout call was so much more expensive and even went so far as to echo out the same string on each copy to get a better comparison on the calls. I did multiple runs to even out the comparison, but the 4x difference persisted.
Then I found this answer on stackoverflow..
Switching on buffering for stdout did the trick, now my throughput numbers for printf and std::cout are pretty much the same.
I have not dug any deeper into how printf and cout differ in console output buffering, but setting the output buffer before I begin writing to the console solved my problem.
Another Stack Overflow question addressed the relative speed of C-style formatted I/O vs. C++ iostreams:
Why is snprintf faster than ostringstream or is it?
http://www.fastformat.org/performance.html
Note, however, that the benchmarks discussed were for formatting to memory buffers. I'd guess that if you're actually performing the I/O to a console or file that the relative speed differences would be much smaller due to the I/O taking more of the overall time.
If you're using C++, you should use cout instead as printf belongs to the C family of functions. There are many improvements made for cout that you may benefit from. As for speed, it isn't an issue as console I/O is going to be slow anyway.
In practical terms I have always found printf to be faster than cout. But then again, cout does a lot more for you in terms of type safety. Also remember printf is a simple function whereas cout is an object based on a complex streams hierarchy, so it's not really fair to compare execution times.
To settle this:
#include <iostream>
#include <cstdio>
#include <ctime>
using namespace std;
int main( int argc, char * argcv[] ) {
const char * const s1 = "some text";
const char * const s2 = "some more text";
int x = 1, y = 2, z = 3;
const int BIG = 2000;
time_t now = time(0);
for ( int i = 0; i < BIG; i++ ) {
if ( argc == 1 ) {
cout << i << s1 << s2 << x << y << z << "\n";
}
else {
printf( "%d%s%s%d%d%d\n", i, s1, s2, x, y, z );
}
}
cout << (argc == 1 ? "cout " : "printf " ) << time(0) - now << endl;
}
produces identical timings for cout and printf.
Why don't you do an experiment? On average for me, printing the string helloperson;\n using printf takes, on average, 2 clock ticks, while cout using endl takes a huge amount of time - 1248996720685 clock ticks. Using cout with "\n" as the newline takes only 41981 clock ticks. The short URL for my code is below:
cpp.sh/94qoj
link may have expired.
To answer your question, printf is faster.
#include <iostream>
#include <string>
#include <ctime>
#include <stdio.h>
using namespace std;
int main()
{
clock_t one;
clock_t two;
clock_t averagePrintf;
clock_t averageCout;
clock_t averagedumbHybrid;
for (int j = 0; j < 100; j++) {
one = clock();
for (int d = 0; d < 20; d++) {
printf("helloperson;");
printf("\n");
}
two = clock();
averagePrintf += two-one;
one = clock();
for (int d = 0; d < 20; d++) {
cout << "helloperson;";
cout << endl;
}
two = clock();
averageCout += two-one;
one = clock();
for (int d = 0; d < 20; d++) {
cout << "helloperson;";
cout << "\n";
}
two = clock();
averagedumbHybrid += two-one;
}
averagePrintf /= 100;
averageCout /= 100;
averagedumbHybrid /= 100;
cout << "printf took " << averagePrintf << endl;
cout << "cout took " << averageCout << endl;
cout << "hybrid took " << averagedumbHybrid << endl;
}
Yes, I did use the word dumb. I first made it for myself, thinking that the results were crazy, so I searched it up, which ended up with me posting my code.
Hope it helps,
Ndrewffght
If you ever need to find out for performance reasons, something else is fundamentally wrong with your application - consider using some other logging facility or UI ;)
Under the hood, they will both use the same code, so speed differences will not matter.
If you are running on Windows only, the non-standard cprintf() might be faster as it bypasses a lot of the streams stuff.
However it is an odd requirement. Nobody can read that fast. Why not write output to a file, then the user can browse the file at their leisure?
Anecdotical evidence:
I've once designed a logging class to use ostream operators - the implementation was insanely slow (for huge amounts of data).
I didn't analyze that to much, so it might as well have been caused by not using ostreams correctly, or simply due to the amount of data logged to disk. (The class has been scrapped because of the performance problems and in practice printf / fmtmsg style was preferred.)
I agree with the other replies that in most cases, it doesn't matter. If output really is a problem, you should consider ways to avoid / delay it, as the actual display updates typically cost more than a correctly implemented string build. Thousands of lines scrolling by within milliseconds isn't very informative anyway.
You should never need to ask this question, as the user will only be able to read slower than both of them.
If you need fast execution, don't use either.
As others have mentioned, use some kind of logging if you need a record of the operations.