16a54dfbfSLouis Dionne //===----------------------------------------------------------------------===// 26a54dfbfSLouis Dionne // 36a54dfbfSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 46a54dfbfSLouis Dionne // See https://llvm.org/LICENSE.txt for license information. 56a54dfbfSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 66a54dfbfSLouis Dionne // 76a54dfbfSLouis Dionne //===----------------------------------------------------------------------===// 86a54dfbfSLouis Dionne 9*b2d24947SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14 10*b2d24947SLouis Dionne 1178b4b5ccSLouis Dionne #include "benchmark/benchmark.h" 1278b4b5ccSLouis Dionne #include "test_macros.h" 1378b4b5ccSLouis Dionne 1478b4b5ccSLouis Dionne #include <mutex> 1578b4b5ccSLouis Dionne #include <sstream> 1678b4b5ccSLouis Dionne 1778b4b5ccSLouis Dionne TEST_NOINLINE double istream_numbers(); 1878b4b5ccSLouis Dionne 1978b4b5ccSLouis Dionne double istream_numbers(std::locale* loc) { 2078b4b5ccSLouis Dionne const char* a[] = {"-6 69 -71 2.4882e-02 -100 101 -2.00005 5000000 -50000000", 2178b4b5ccSLouis Dionne "-25 71 7 -9.3262e+01 -100 101 -2.00005 5000000 -50000000", 2278b4b5ccSLouis Dionne "-14 53 46 -6.7026e-02 -100 101 -2.00005 5000000 -50000000"}; 2378b4b5ccSLouis Dionne 2478b4b5ccSLouis Dionne int a1, a2, a3, a4, a5, a6, a7; 2578b4b5ccSLouis Dionne double f1 = 0.0, f2 = 0.0, q = 0.0; 2678b4b5ccSLouis Dionne for (int i = 0; i < 3; i++) { 2778b4b5ccSLouis Dionne std::istringstream s(a[i]); 2878b4b5ccSLouis Dionne if (loc) 2978b4b5ccSLouis Dionne s.imbue(*loc); 3078b4b5ccSLouis Dionne s >> a1 >> a2 >> a3 >> f1 >> a4 >> a5 >> f2 >> a6 >> a7; 3178b4b5ccSLouis Dionne q += (a1 + a2 + a3 + a4 + a5 + a6 + a7 + f1 + f2) / 1000000; 3278b4b5ccSLouis Dionne } 3378b4b5ccSLouis Dionne return q; 3478b4b5ccSLouis Dionne } 3578b4b5ccSLouis Dionne 3678b4b5ccSLouis Dionne struct LocaleSelector { 3778b4b5ccSLouis Dionne std::locale* imbue; 3878b4b5ccSLouis Dionne std::locale old; 3978b4b5ccSLouis Dionne static std::mutex mutex; 4078b4b5ccSLouis Dionne 4178b4b5ccSLouis Dionne LocaleSelector(benchmark::State& state) { 4278b4b5ccSLouis Dionne std::lock_guard guard(mutex); 4378b4b5ccSLouis Dionne switch (state.range(0)) { 4478b4b5ccSLouis Dionne case 0: { 4578b4b5ccSLouis Dionne old = std::locale::global(std::locale::classic()); 4678b4b5ccSLouis Dionne imbue = nullptr; 4778b4b5ccSLouis Dionne break; 4878b4b5ccSLouis Dionne } 4978b4b5ccSLouis Dionne case 1: { 5078b4b5ccSLouis Dionne old = std::locale::global(std::locale::classic()); 5178b4b5ccSLouis Dionne thread_local std::locale loc("en_US.UTF-8"); 5278b4b5ccSLouis Dionne imbue = &loc; 5378b4b5ccSLouis Dionne break; 5478b4b5ccSLouis Dionne } 5578b4b5ccSLouis Dionne case 2: { 5678b4b5ccSLouis Dionne old = std::locale::global(std::locale::classic()); 5778b4b5ccSLouis Dionne static std::locale loc("en_US.UTF-8"); 5878b4b5ccSLouis Dionne imbue = &loc; 5978b4b5ccSLouis Dionne break; 6078b4b5ccSLouis Dionne } 6178b4b5ccSLouis Dionne case 3: { 6278b4b5ccSLouis Dionne old = std::locale::global(std::locale("en_US.UTF-8")); 6378b4b5ccSLouis Dionne imbue = nullptr; 6478b4b5ccSLouis Dionne break; 6578b4b5ccSLouis Dionne } 6678b4b5ccSLouis Dionne } 6778b4b5ccSLouis Dionne } 6878b4b5ccSLouis Dionne 6978b4b5ccSLouis Dionne ~LocaleSelector() { 7078b4b5ccSLouis Dionne std::lock_guard guard(mutex); 7178b4b5ccSLouis Dionne std::locale::global(old); 7278b4b5ccSLouis Dionne } 7378b4b5ccSLouis Dionne }; 7478b4b5ccSLouis Dionne 7578b4b5ccSLouis Dionne std::mutex LocaleSelector::mutex; 7678b4b5ccSLouis Dionne 7778b4b5ccSLouis Dionne static void BM_Istream_numbers(benchmark::State& state) { 7878b4b5ccSLouis Dionne LocaleSelector sel(state); 7978b4b5ccSLouis Dionne double i = 0; 8078b4b5ccSLouis Dionne while (state.KeepRunning()) 8178b4b5ccSLouis Dionne benchmark::DoNotOptimize(i += istream_numbers(sel.imbue)); 8278b4b5ccSLouis Dionne } 8378b4b5ccSLouis Dionne BENCHMARK(BM_Istream_numbers)->DenseRange(0, 3)->UseRealTime()->Threads(1)->ThreadPerCpu(); 8478b4b5ccSLouis Dionne 8578b4b5ccSLouis Dionne static void BM_Ostream_number(benchmark::State& state) { 8678b4b5ccSLouis Dionne LocaleSelector sel(state); 8778b4b5ccSLouis Dionne while (state.KeepRunning()) { 8878b4b5ccSLouis Dionne std::ostringstream ss; 8978b4b5ccSLouis Dionne if (sel.imbue) 9078b4b5ccSLouis Dionne ss.imbue(*sel.imbue); 9178b4b5ccSLouis Dionne ss << 0; 9278b4b5ccSLouis Dionne benchmark::DoNotOptimize(ss.str().c_str()); 9378b4b5ccSLouis Dionne } 9478b4b5ccSLouis Dionne } 9578b4b5ccSLouis Dionne BENCHMARK(BM_Ostream_number)->DenseRange(0, 3)->UseRealTime()->Threads(1)->ThreadPerCpu(); 9678b4b5ccSLouis Dionne 9778b4b5ccSLouis Dionne BENCHMARK_MAIN(); 98