If performance is an very important consideration, is it good to consider c++0x? [closed]
I wrote a simple test to check how good c++0x is. Here is the sample C++ code
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
#ifndef __GXX_EXPERIMENTAL_CXX0X__
#define emplace_back push_back
#define auto typeof(vs.begin())
#endif
int main()
{
vector<string> vs;
string s;
while(cin>>s)
{
vs.emplace_back(s);
}
sort(vs.begin(),vs.end());
for(auto it = vs.begin();it != vs.end();++it)
{
cout << (*it) << endl;
}
return 0;
}
Here is a script to run it
#!/bin/bash
inputFile=`mktemp`;
outputFile1=`mktemp`
outputFile2=`mktemp`
cat /dev/urandom | base64 > $inputFile 2> /dev/null &
echo "Generating Sample Input.. ${1:-10} seconds"
sleep ${1:-10}
export TOKILL=`pgrep -P $$ cat`
$(kill $TOKILL) 2> /dev/null > /dev/null
wc -l $inputFile
echo -e "\nTesting without --std=gnu++0x"
g++ Test.C -o old
time ./old < $inputFile > $outputFile1
echo -e "\nTesting with --std==gnu++0x"
g++ Test.C --std=gnu++0x -o new
time ./new < $inputFile > $outputFile2
diff $outputFile1 $outputFile2
rm $inputFile $outputFile1 $outputFile2
Most of the time I tested, C++03 proves better than c++0x. Here is a sample output.
Generating Sample Input.. 10 seconds
845645 /tmp/tmp.YMxZtrVeD0
Testing without --std=gnu++0x
real 0m12.437s
user 0m10.273s
sys 0m2.152s
Testing with --std==gnu++0x
real 0m12.452s
user 0m10.241s
sys 0m2.196s
c++ code is self explanatory. Script generates random strings of equal length seperated by a newline in a temporary file. Number of lines in the generated file is printed.
I'm using vector and sort. Sort will use std::swap. With rvalue references, and std::move, isn't the code supposed to work faster?
My g++ version is
g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
Ok. I'll reword my Question.
If performance is an very important consideration, is it good to consider c++0x?
If the way I conducted the test is wrong, how should I do it correctly to find the answer myself.
Please provide some examples.
This is totally fail. What you've done here:
- Initialize an
std::string
from an uninitialized chunk of characters allocated on the heap. Completely undefined behavior and leaks like hell. - Call
emplace_back(someotherstdstring)
, thereby still copying a std::string.
What you probably really wanted to do is emplace_back(somecharptr)
but even then this would be totally fail. There isn't going to be any real difference of just doing
std::string s0("foo"); // emplace_back("foo")
std::string s1(s0); // emplace_back(s0)
std::string s2((std::string const&)s0); // push_back(s0)
Arguably, the construction from s0
is even more performant because s0
already knows the length of the string, while the length of "foo"
first has to be calculated by the constructor of std::string
.
I recommend to first think through all you have written there. The whole point of emplace_back
is to avoid constructing an object just to pass it to push_back
and copy it. But in your case you already have an object so it doesn't really make sense to pass it through emplace_back
.
Uh, you changed to emplace_back and then emplace_back'd an lvalue? That's not going to make any difference- it's still an lvalue and you're still making a copy. In C++03 then std::string will almost certainly use a swap that's just as good as rvalue references- move semantics are just much more generic. Modern Standard libraries already use something called swaptimization for certain classes that mimics the effect of rvalue references under certain conditions, including vector resizing.
Bottom line: You've picked the most heavily optimized, specialized and focused code in the entire C++ world. This code has effectively already had move semantics applied to it under the hood and you don't use any actual rvalues anywhere. How are rvalue references going to make any difference?
First, I don't see where C++03 is "better". Your timings are close enough together that I'd say it's a tie. And your benchmarking code is flawed. What you're timing is mainly I/O because your input/output code is included in the benchmark.
Second, C++0x allows some potential performance improvements. But it doesn't guarantee anything, and it relies on the standard library to actually take advantage of this throughout.
Finally, through RVO and copy elision (and std::swap
), unnecessary copies can often be avoided in C++03, even without rvalue references. But rvalue references generalizes this, and allows similar optimizations to be applied in far more cases than was possible in C++03
精彩评论