// Simple performance test program. // Objectives: To see if gcc 3.4.1 makes iostreams significantly faster than // gcc 3.3, and to compare it to "raw c". #include #include #include #include #include #include /** * Convert a string to an arbitrary type. * \param C the type to convert to. * \param value the value to convert. */ template C to(const std::string &value) { std::istringstream s(value); C c; if(s >> c) { if(!s.eof() && s.peek() != EOF) throw std::runtime_error("Trailing junk in \"" + value + '"'); return c; } else throw std::runtime_error("Bad value: \"" + value + '"'); } /** * Test reading integers. */ unsigned long long sumints(std::istream& in) { unsigned long long sum = 0; int i; while(in >> i) sum += i; return sum; } /** * Test reading integers (or something else), and growing and sorting a * vector. */ template Num median(std::istream& in) { std::vector nums; Num num; while(in >> num) nums.push_back(num); sort(nums.begin(), nums.end()); if(/* odd */ nums.size() % 2) return nums[nums.size()/2]; else return ((nums[nums.size()/2] + nums[nums.size()/2-1]) / 2); } /** * Test reading raw characters. Result should be similar to wc. */ class WordCount { public: WordCount(std::istream& in) : chars_(0), words_(0), lines_(0) { char ch; bool inword = false; while(in.get(ch)) { if(!(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r')) { inword = true; } else { if(inword) { ++words_; inword = false; } } if(ch == '\n') ++lines_; ++chars_; } } int chars() const { return chars_; } int words() const { return words_; } int lines() const { return lines_; } private: int chars_, words_, lines_; }; /** * Main programs, run a specified number of iterations of a specified * selection of tests. */ int main(int argc, char* argv[]) { try { int iterations = 1; bool do_median = false, do_sum = false, do_wc = false; for(int i = 1; i < argc; ++i) { if(argv[i][0] == '-') switch(argv[i][1]) { case 'i': iterations = to(argv[++i]); break; case 'm': do_median = true; break; case 's': do_sum = true; break; case 'w': do_wc = true; break; default: std::cerr << "Unknown flag: " << argv[i] << std::endl; exit(1); } else { std::cerr << "Unknown argument: " << argv[i] << std::endl; exit(1); } } for(int i = 0; i < iterations; ++i) { if(do_median) { std::ifstream data("numbers.txt"); if(!data) { std::cerr << "No data." << std::endl; exit(1); } std::cout << "Median: " << median(data) << std::endl; } if(do_sum) { std::ifstream data("numbers.txt"); if(!data) { std::cerr << "No data." << std::endl; exit(1); } std::cout << "Sum: " << sumints(data) << std::endl; } if(do_wc) { std::ifstream data("numbers.txt"); if(!data) { std::cerr << "No data." << std::endl; exit(1); } WordCount wc(data); std::cout << ' ' << wc.lines() << ' ' << wc.words() << ' ' << wc.chars() << " numbers.txt" << std::endl; } } } catch(const std::exception& err) { std::cerr << "Error: " << err.what() << std::endl; exit(1); } }