Here's another benchmark, showing yet another possibility that may be worth considering, if you can:
#include <algorithm>
#include <string>
#include <iterator>
#include <iostream>
#include <vector>
#include <functional>
#include <ctype.h>
#include <time.h>
#include <limits.h>
class not_isalpha {
bool table[UCHAR_MAX];
public:
not_isalpha() {
for (int i=0; i<UCHAR_MAX; i++)
table[i] = !isalpha(i);
}
bool operator()(char input){
return table[(unsigned char)input];
}
};
template <class T>
T gen_random(size_t len) {
T x;
x.reserve(len);
std::generate_n(std::back_inserter(x), len, rand);
return x;
}
template <class Container, class stripper>
clock_t test(Container const &input, Container &result, stripper strip) {
result.reserve(input.size());
clock_t start = clock();
std::remove_copy_if(input.begin(), input.end(), std::back_inserter(result), strip);
return clock() - start;
}
void show(std::string const &label, clock_t ticks) {
std::cout << label << ": " << ticks/(double)CLOCKS_PER_SEC << " Seconds\n";
}
int main(){
typedef std::vector<char> T;
static const size_t size = 50000000;
T x(gen_random<T>(size));
T result;
show("not_isalpha, vector", test(x, result, not_isalpha()));
show("::isalpha, vector", test(x, result, std::not1(std::ptr_fun(isalpha))));
std::string input2(x.begin(), x.end());
std::string result2;
show("not_isalpha, string", test(input2, result2, not_isalpha()));
show("::isalpha, string", test(input2, result2, std::not1(std::ptr_fun(isalpha))));
return 0;
}
At least in my testing, with both VC++ (10), and g++ (4.7.0), std::vector
comes out faster than string.
VC++ 10:
not_isalpha, vector: 0.246 Seconds
::isalpha, vector: 0.401 Seconds
not_isalpha, string: 0.473 Seconds
::isalpha, string: 0.631 Seconds
g++ 4.7.0:
not_isalpha, vector: 0.212 Seconds
::isalpha, vector: 0.382 Seconds
not_isalpha, string: 0.285 Seconds
::isalpha, string: 0.413 Seconds
Using our own table-driven version of isalpha
helps speed quite a bit compared to using ::isalpha
, but using std::vector
improves speed even more, especially with VC++ (though the difference is fairly substantial with g++ as well).
For those who like to compare compilers, it's worth noting that g++ is not only faster overall, but also more consistently fast. With g++, the worst case is only about two times slower than the fastest. With VC++, the worst case is about three times slower.