int main()

in be/src/benchmarks/convert-timestamp-benchmark.cc [710:1024]


int main(int argc, char* argv[]) {
  impala::InitCommonRuntime(argc, argv, true, impala::TestInfo::BE_TEST);
  impala::InitFeSupport();
  TestEnv test_env;
  CHECK(test_env.Init().ok());

  cout << Benchmark::GetMachineInfo() << endl;

  ABORT_IF_ERROR(TimezoneDatabase::Initialize());

  const string& local_tz_name = TimezoneDatabase::LocalZoneName();
  DCHECK(local_tz_name != "");

  PTR_CCTZ_LOCAL_TZ = TimezoneDatabase::FindTimezone(local_tz_name);
  DCHECK(PTR_CCTZ_LOCAL_TZ != nullptr);

  SimpleDateFormatTokenizer::InitCtx();

  const vector<TimestampValue> tsvalue_data =
      AddTestDataDateTimes(1000, "1953-04-22 01:02:03");

  // Benchmark UtcToUnixTime conversion with glibc/cctz/boost
  Benchmark bm_utc_to_unix("UtcToUnixTime");
  TestData<TimestampValue, time_t, glibc_utc_to_unix_time> glibc_utc_to_unix_data =
      tsvalue_data;
  TestData<TimestampValue, time_t, cctz_utc_to_unix_time> cctz_utc_to_unix_data =
      tsvalue_data;
  TestData<TimestampValue, time_t, boost_utc_to_unix_time> boost_utc_to_unix_data =
      tsvalue_data;

  glibc_utc_to_unix_data.add_to_benchmark(bm_utc_to_unix, "(glibc)");
  cctz_utc_to_unix_data.add_to_benchmark(bm_utc_to_unix, "(Google/CCTZ)");
  boost_utc_to_unix_data.add_to_benchmark(bm_utc_to_unix, "(boost)");
  cout << bm_utc_to_unix.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<time_t>*>{
      &cctz_utc_to_unix_data.result(), &glibc_utc_to_unix_data.result(),
      &boost_utc_to_unix_data.result()});

  // Benchmark LocalToUnixTime conversion with glibc/cctz
  Benchmark bm_local_to_unix("LocalToUnixTime");
  TestData<TimestampValue, time_t, glibc_local_to_unix_time> glibc_local_to_unix_data =
      tsvalue_data;
  TestData<TimestampValue, time_t, cctz_local_to_unix_time> cctz_local_to_unix_data =
      tsvalue_data;

  glibc_local_to_unix_data.add_to_benchmark(bm_local_to_unix, "(glibc)");
  cctz_local_to_unix_data.add_to_benchmark(bm_local_to_unix, "(Google/CCTZ)");
  cout << bm_local_to_unix.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<time_t>*>{
      &glibc_local_to_unix_data.result(), &cctz_local_to_unix_data.result()});

  // Benchmark FromUtc with boost/cctz
  vector<TimestampVal> tsval_data;
  for (const TimestampValue& tsvalue: tsvalue_data) {
    TimestampVal tsval;
    tsvalue.ToTimestampVal(&tsval);
    tsval_data.push_back(tsval);
  }

  Benchmark bm_from_utc("FromUtc");
  TestData<TimestampVal, TimestampVal, boost_from_utc> boost_from_utc_data = tsval_data;
  TestData<TimestampVal, TimestampVal, cctz_from_utc> cctz_from_utc_data = tsval_data;

  boost_from_utc_data.add_to_benchmark(bm_from_utc, "(boost)");
  cctz_from_utc_data.add_to_benchmark(bm_from_utc, "(Google/CCTZ)");
  cout << bm_from_utc.Measure() << endl;

  // We don't expect boost/cctz FromUtc results to match (they use non-compatible
  // time-zone databases for conversion).

  // Benchmark ToUtc with boost/cctz
  Benchmark bm_to_utc("ToUtc");
  TestData<TimestampVal, TimestampVal, boost_to_utc> boost_to_utc_data = tsval_data;
  TestData<TimestampVal, TimestampVal, cctz_to_utc> cctz_to_utc_data = tsval_data;

  boost_to_utc_data.add_to_benchmark(bm_to_utc, "(boost)");
  cctz_to_utc_data.add_to_benchmark(bm_to_utc, "(Google/CCTZ)");
  cout << bm_to_utc.Measure() << endl;

  // We don't expect boost/cctz ToUtc results to match (they use non-compatible time-zone
  // databases for conversion).

  // Benchmark UtcToLocal with glibc/cctz
  Benchmark bm_utc_to_local("UtcToLocal");
  TestData<TimestampValue, TimestampValue, glibc_utc_to_local> glibc_utc_to_local_data =
      tsvalue_data;
  TestData<TimestampValue, TimestampValue, cctz_utc_to_local> cctz_utc_to_local_data =
      tsvalue_data;
  TestData<TimestampValue, TimestampValue, jvm_utc_to_local> jvm_utc_to_local_data =
      tsvalue_data;

  glibc_utc_to_local_data.add_to_benchmark(bm_utc_to_local, "(glibc)");
  cctz_utc_to_local_data.add_to_benchmark(bm_utc_to_local, "(Google/CCTZ)");
  jvm_utc_to_local_data.add_to_benchmark(bm_utc_to_local, "(JVM)");
  cout << bm_utc_to_local.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<TimestampValue>*>{
      &glibc_utc_to_local_data.result(), &cctz_utc_to_local_data.result()});

  // Benchmark UnixTimeToLocalPtime with glibc/cctz
  vector<time_t> time_data;
  for (const TimestampValue& tsvalue: tsvalue_data) {
    time_t unix_time;
    tsvalue.ToUnixTime(UTCPTR, &unix_time);
    time_data.push_back(unix_time);
  }

  Benchmark bm_unix_time_to_local_ptime("UnixTimeToLocalPtime");
  TestData<
      time_t,
      boost::posix_time::ptime,
      glibc_unix_time_to_local_ptime> glibc_unix_time_to_local_ptime_data = time_data;
  TestData<
    time_t,
    boost::posix_time::ptime,
    cctz_unix_time_to_local_ptime> cctz_unix_time_to_local_ptime_data = time_data;

  glibc_unix_time_to_local_ptime_data.add_to_benchmark(bm_unix_time_to_local_ptime,
      "(glibc)");
  cctz_unix_time_to_local_ptime_data.add_to_benchmark(bm_unix_time_to_local_ptime,
      "(Google/CCTZ)");
  cout << bm_unix_time_to_local_ptime.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<boost::posix_time::ptime>*>{
      &glibc_unix_time_to_local_ptime_data.result(),
      &cctz_unix_time_to_local_ptime_data.result()});

  // Benchmark UnixTimeToUtcPtime with glibc/cctz/fastpath
  Benchmark bm_unix_time_to_utc_ptime("UnixTimeToUtcPtime");
  TestData<
      time_t,
      boost::posix_time::ptime,
      glibc_unix_time_to_utc_ptime> glibc_unix_time_to_utc_ptime_data = time_data;
  TestData<
      time_t,
      boost::posix_time::ptime,
      cctz_unix_time_to_utc_ptime> cctz_unix_time_to_utc_ptime_data = time_data;
  TestData<
      time_t,
      boost::posix_time::ptime,
      fastpath_unix_time_to_utc_ptime> fastpath_unix_time_to_utc_ptime_data = time_data;
  TestData<
      time_t,
      boost::posix_time::ptime,
      split_unix_time_to_utc_ptime> split_unix_time_to_utc_ptime_data = time_data;

  glibc_unix_time_to_utc_ptime_data.add_to_benchmark(bm_unix_time_to_utc_ptime,
      "(glibc)");
  cctz_unix_time_to_utc_ptime_data.add_to_benchmark(bm_unix_time_to_utc_ptime,
      "(Google/CCTZ)");
  fastpath_unix_time_to_utc_ptime_data.add_to_benchmark(bm_unix_time_to_utc_ptime,
      "(fast path)");
  split_unix_time_to_utc_ptime_data.add_to_benchmark(bm_unix_time_to_utc_ptime,
      "(day split)");
  cout << bm_unix_time_to_utc_ptime.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<boost::posix_time::ptime>*>{
      &glibc_unix_time_to_utc_ptime_data.result(),
      &cctz_unix_time_to_utc_ptime_data.result(),
      &fastpath_unix_time_to_utc_ptime_data.result(),
      &split_unix_time_to_utc_ptime_data.result()});

  // Benchmark UtcFromUnixTimeMicros improvement in IMPALA-7417.
  vector<time_t> microsec_data;
  for (int i = 0; i < tsvalue_data.size(); ++i) {
    const TimestampValue& tsvalue = tsvalue_data[i];
    time_t unix_time;
    tsvalue.ToUnixTime(UTCPTR, &unix_time);
    int micros = (i * 1001) % MICROS_PER_SEC; // add some sub-second part
    microsec_data.push_back(unix_time * MICROS_PER_SEC + micros);
  }

  Benchmark bm_utc_from_unix_time_micros("UtcFromUnixTimeMicros");
  TestData<int64_t, TimestampValue, sec_split_utc_from_unix_time_micros>
      sec_split_utc_from_unix_time_micros_data = microsec_data;
  TestData<int64_t, TimestampValue, day_split_utc_from_unix_time_micros>
      day_split_utc_from_unix_time_micros_data = microsec_data;

  sec_split_utc_from_unix_time_micros_data.add_to_benchmark(bm_utc_from_unix_time_micros,
      "(sec split (old))");
  day_split_utc_from_unix_time_micros_data.add_to_benchmark(bm_utc_from_unix_time_micros,
      "(day split)");
  cout << bm_utc_from_unix_time_micros.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<TimestampValue>*>{
      &sec_split_utc_from_unix_time_micros_data.result(),
      &day_split_utc_from_unix_time_micros_data.result()});

  // Benchmark FromUnixTimeNanos improvement in IMPALA-7417.
  vector<SplitNanoAndSecond> nanosec_data;
  for (int i = 0; i < tsvalue_data.size(); ++i) {
    const TimestampValue& tsvalue = tsvalue_data[i];
    time_t unix_time;
    tsvalue.ToUnixTime(UTCPTR, &unix_time);
    int nanos = (i * 1001) % NANOS_PER_SEC; // add some sub-second part
    nanosec_data.push_back(SplitNanoAndSecond {unix_time, nanos} );
  }

  Benchmark bm_utc_from_unix_time_nanos("FromUnixTimeNanos");
  TestData<SplitNanoAndSecond, TimestampValue, old_split_utc_from_unix_time_nanos>
      old_split_utc_from_unix_time_nanos_data = nanosec_data;
  TestData<SplitNanoAndSecond, TimestampValue, new_split_utc_from_unix_time_nanos>
      new_split_utc_from_unix_time_nanos_data = nanosec_data;

  old_split_utc_from_unix_time_nanos_data.add_to_benchmark(bm_utc_from_unix_time_nanos,
      "(sec split (old))");
  new_split_utc_from_unix_time_nanos_data.add_to_benchmark(bm_utc_from_unix_time_nanos,
      "(sec split (new))");
  cout << bm_utc_from_unix_time_nanos.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<TimestampValue>*>{
      &old_split_utc_from_unix_time_nanos_data.result(),
      &new_split_utc_from_unix_time_nanos_data.result()});

  // Benchmark FromSubsecondUnixTime before and after IMPALA-7417.
  vector<double> double_data;
  for (int i = 0; i < tsvalue_data.size(); ++i) {
    const TimestampValue& tsvalue = tsvalue_data[i];
    time_t unix_time;
    tsvalue.ToUnixTime(UTCPTR, &unix_time);
    double nanos = (i * 1001) % NANOS_PER_SEC; // add some sub-second part
    double_data.push_back((double)unix_time + nanos / NANOS_PER_SEC);
  }

  Benchmark from_subsecond_unix_time("FromSubsecondUnixTime");
  TestData<double, TimestampValue, from_subsecond_unix_time_old>
      from_subsecond_unix_time_old_data = double_data;
  TestData<double, TimestampValue, from_subsecond_unix_time_new>
      from_subsecond_unix_time_new_data = double_data;

  from_subsecond_unix_time_old_data.add_to_benchmark(from_subsecond_unix_time, "(old)");
  from_subsecond_unix_time_new_data.add_to_benchmark(from_subsecond_unix_time, "(new)");
  cout << from_subsecond_unix_time.Measure() << endl;

  bail_if_results_dont_match(vector<const vector<TimestampValue>*>{
      &from_subsecond_unix_time_old_data.result(),
      &from_subsecond_unix_time_new_data.result()});

  // If number of threads is specified, run multithreaded tests.
  int num_of_threads = (argc < 2) ? 0 : atoi(argv[1]);
  if (num_of_threads >= 1) {
    const int BATCH_SIZE = 1000;
    cout << "Number of threads: " << num_of_threads << endl;

    uint64_t m1 = 0, m2 = 0, m3 = 0;

    // UtcToUnixTime
    cout << endl << "UtcToUnixTime:" << endl;
    m1 = glibc_utc_to_unix_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(glibc)");
    m2 = cctz_utc_to_unix_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(Google/CCTZ)");
    m3 = boost_utc_to_unix_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(boost)");
    cout << "cctz speedup: " << double(m1)/double(m2) << endl;
    cout << "boost speedup: " << double(m1)/double(m3) << endl;

    // LocalToUnixTime
    cout << endl << "LocalToUnixTime:" << endl;
    m1 = glibc_local_to_unix_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(glibc)");
    m2 = cctz_local_to_unix_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(Google/CCTZ)");
    cout << "speedup: " << double(m1)/double(m2) << endl;

    // FromUtc
    cout << endl << "FromUtc:" << endl;
    m1 = boost_from_utc_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsval_data, "(boost)");
    m2 = cctz_from_utc_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsval_data, "(Google/CCTZ)");
    cout << "speedup: " << double(m1)/double(m2) << endl;

    // ToUtc
    cout << endl << "ToUtc:" << endl;
    m1 = boost_to_utc_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsval_data, "(boost)");
    m2 = cctz_to_utc_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsval_data, "(Google/CCTZ)");
    cout << "speedup: " << double(m1)/double(m2) << endl;

    // UtcToLocal
    cout << endl <<  "UtcToLocal:" << endl;
    m1 = glibc_utc_to_local_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(glibc)");
    m2 = cctz_utc_to_local_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(Google/CCTZ)");
    m3 = jvm_utc_to_local_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, tsvalue_data, "(JVM)");
    cout << "cctz speedup: " << double(m1)/double(m2) << endl;
    cout << "jvm speedup: " << double(m1)/double(m3) << endl;

    // UnixTimeToLocalPtime
    cout << endl << "UnixTimeToLocalPtime:" << endl;
    m1 = glibc_unix_time_to_local_ptime_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, time_data, "(glibc)");
    m2 = cctz_unix_time_to_local_ptime_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, time_data, "(Google/CCTZ)");
    cout << "speedup: " << double(m1)/double(m2) << endl;

    // UnixTimeToUtcPtime
    cout << endl << "UnixTimeToUtcPtime:" << endl;
    m1 = glibc_unix_time_to_utc_ptime_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, time_data, "(glibc)");
    m2 = cctz_unix_time_to_utc_ptime_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, time_data, "(Google/CCTZ)");
    m3 = fastpath_unix_time_to_utc_ptime_data.measure_multithreaded_elapsed_time(
        num_of_threads, BATCH_SIZE, time_data, "(fast path)");
    cout << "cctz speedup: " << double(m1)/double(m2) << endl;
    cout << "fast path speedup: " << double(m1)/double(m3) << endl;
  }
  return 0;
}