blob: 25c17c43816ea50047d86ba511f952b8ba76f5fc [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <vector>
#include <sstream>
#include "runtime/string-value.h"
#include "util/benchmark.h"
#include "util/cpu-info.h"
#include "util/string-parser.h"
#include "common/names.h"
using namespace impala;
// Benchmark for computing atof. This benchmarks tests converting from
// strings into floats on what we expect to be typical data. The data
// is mostly positive numbers with just a couple of them in scientific
// notation.
//
// Machine Info: Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
// atof: Function Rate Comparison
// ----------------------------------------------------------------------
// Strtod 8.171 1X
// Atof 8.057 0.9861X
// Impala 67.86 8.306X
#define VALIDATE 0
#if VALIDATE
// Use fabs?
#define VALIDATE_RESULT(actual, expected, str) \
if (actual != expected) { \
cout << "Parse Error. " \
<< "String: " << str \
<< ". Parsed: " << actual << endl; \
exit(-1); \
}
#else
#define VALIDATE_RESULT(actual, expected, str)
#endif
struct TestData {
vector<StringValue> data;
vector<string> memory;
vector<double> result;
};
void AddTestData(TestData* data, const string& input) {
data->memory.push_back(input);
const string& str = data->memory.back();
data->data.push_back(StringValue(const_cast<char*>(str.c_str()), str.length()));
}
void AddTestData(TestData* data, int n, double min = -10, double max = 10) {
for (int i = 0; i < n; ++i) {
double val = rand();
val /= RAND_MAX;
val = (val * (max - min)) + min;
stringstream ss;
ss << val;
AddTestData(data, ss.str());
}
}
void TestAtof(int batch_size, void* d) {
TestData* data = reinterpret_cast<TestData*>(d);
for (int i = 0; i < batch_size; ++i) {
int n = data->data.size();
for (int j = 0; j < n; ++j) {
data->result[j] = atof(data->data[j].ptr);
}
}
}
void TestImpala(int batch_size, void* d) {
TestData* data = reinterpret_cast<TestData*>(d);
for (int i = 0; i < batch_size; ++i) {
int n = data->data.size();
for (int j = 0; j < n; ++j) {
const StringValue& str = data->data[j];
StringParser::ParseResult dummy;
double val = StringParser::StringToFloat<double>(str.ptr, str.len, &dummy);
VALIDATE_RESULT(val, data->result[j], str.ptr);
data->result[j] = val;
}
}
}
void TestStrtod(int batch_size, void* d) {
TestData* data = reinterpret_cast<TestData*>(d);
for (int i = 0; i < batch_size; ++i) {
int n = data->data.size();
for (int j = 0; j < n; ++j) {
data->result[j] = strtod(data->data[j].ptr, NULL);
}
}
}
int main(int argc, char **argv) {
CpuInfo::Init();
cout << Benchmark::GetMachineInfo() << endl;
TestData data;
// Most data is probably positive
AddTestData(&data, 1000, -5, 1000);
AddTestData(&data, "1.1e12");
data.result.resize(data.data.size());
Benchmark suite("atof");
suite.AddBenchmark("Strtod", TestStrtod, &data);
suite.AddBenchmark("Atof", TestAtof, &data);
suite.AddBenchmark("Impala", TestImpala, &data);
cout << suite.Measure();
return 0;
}