| // 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. |
| |
| // Date 2021/11/17 14:57:49 |
| |
| #include <pthread.h> |
| #include <cstddef> |
| #include <memory> |
| #include <iostream> |
| #include <set> |
| #include <string> |
| #include <gflags/gflags.h> |
| #include <gtest/gtest.h> |
| #include "butil/time.h" |
| #include "butil/macros.h" |
| #include "bvar/bvar.h" |
| #include "bvar/multi_dimension.h" |
| #include "butil/third_party/rapidjson/rapidjson.h" |
| #include "butil/third_party/rapidjson/document.h" |
| |
| const size_t OPS_PER_THREAD = 200000; |
| |
| const size_t OPS_PER_THREAD_INTRECORDER = 2000; |
| |
| static const int num_thread = 24; |
| |
| static const int idc_count = 20; |
| static const int method_count = 20; |
| static const int status_count = 50; |
| |
| static const std::list<std::string> labels = {"idc", "method", "status"}; |
| |
| static void *thread_adder(void *arg) { |
| bvar::Adder<uint64_t> *reducer = (bvar::Adder<uint64_t> *)arg; |
| butil::Timer timer; |
| timer.start(); |
| for (size_t i = 0; i < OPS_PER_THREAD; ++i) { |
| (*reducer) << 2; |
| } |
| timer.stop(); |
| return (void *)(timer.n_elapsed()); |
| } |
| |
| static long start_perf_test_with_madder(size_t num_thread, bvar::Adder<uint64_t>* adder) { |
| EXPECT_TRUE(adder->valid()); |
| pthread_t threads[num_thread]; |
| for (size_t i = 0; i < num_thread; ++i) { |
| pthread_create(&threads[i], NULL, &thread_adder, (void *)adder); |
| } |
| long totol_time = 0; |
| for (size_t i = 0; i < num_thread; ++i) { |
| void *ret = NULL; |
| pthread_join(threads[i], &ret); |
| totol_time += (long)ret; |
| } |
| long avg_time = totol_time / (OPS_PER_THREAD * num_thread); |
| EXPECT_EQ(2ul * num_thread * OPS_PER_THREAD, adder->get_value()); |
| return avg_time; |
| } |
| |
| static void *thread_maxer(void *arg) { |
| bvar::Maxer<uint64_t> *reducer = (bvar::Maxer<uint64_t> *)arg; |
| butil::Timer timer; |
| timer.start(); |
| for (size_t i = 1; i <= OPS_PER_THREAD; ++i) { |
| (*reducer) << 2 * i * OPS_PER_THREAD; |
| } |
| timer.stop(); |
| return (void *)(timer.n_elapsed()); |
| } |
| |
| static long start_perf_test_with_mmaxer(size_t num_thread, bvar::Maxer<uint64_t>* maxer) { |
| EXPECT_TRUE(maxer->valid()); |
| pthread_t threads[num_thread]; |
| for (size_t i = 0; i < num_thread; ++i) { |
| pthread_create(&threads[i], NULL, &thread_maxer, (void *)maxer); |
| } |
| long totol_time = 0; |
| for (size_t i = 0; i < num_thread; ++i) { |
| void *ret = NULL; |
| pthread_join(threads[i], &ret); |
| totol_time += (long)ret; |
| } |
| long avg_time = totol_time / (OPS_PER_THREAD * num_thread); |
| EXPECT_EQ(2ul * OPS_PER_THREAD * OPS_PER_THREAD, maxer->get_value()); |
| return avg_time; |
| } |
| |
| static void *thread_miner(void *arg) { |
| bvar::Miner<uint64_t> *reducer = (bvar::Miner<uint64_t> *)arg; |
| butil::Timer timer; |
| timer.start(); |
| for (size_t i = 1; i <= OPS_PER_THREAD; ++i) { |
| (*reducer) << -2 * i * OPS_PER_THREAD; |
| } |
| timer.stop(); |
| return (void *)(timer.n_elapsed()); |
| } |
| |
| static long start_perf_test_with_mminer(size_t num_thread, bvar::Miner<uint64_t>* miner) { |
| EXPECT_TRUE(miner->valid()); |
| pthread_t threads[num_thread]; |
| for (size_t i = 0; i < num_thread; ++i) { |
| pthread_create(&threads[i], NULL, &thread_miner, (void *)miner); |
| } |
| long totol_time = 0; |
| for (size_t i = 0; i < num_thread; ++i) { |
| void *ret = NULL; |
| pthread_join(threads[i], &ret); |
| totol_time += (long)ret; |
| } |
| long avg_time = totol_time / (OPS_PER_THREAD * num_thread); |
| EXPECT_EQ(-2ul * OPS_PER_THREAD * OPS_PER_THREAD, miner->get_value()); |
| return avg_time; |
| } |
| |
| static void *thread_intrecorder(void *arg) { |
| bvar::IntRecorder *reducer = (bvar::IntRecorder *)arg; |
| butil::Timer timer; |
| timer.start(); |
| for (size_t i = 1; i <= OPS_PER_THREAD_INTRECORDER; ++i) { |
| (*reducer) << 2 * i * OPS_PER_THREAD_INTRECORDER; |
| } |
| timer.stop(); |
| return (void *)(timer.n_elapsed()); |
| } |
| |
| static long start_perf_test_with_mintrecorder(size_t num_thread, bvar::IntRecorder* intrecorder) { |
| EXPECT_TRUE(intrecorder->valid()); |
| pthread_t threads[num_thread]; |
| for (size_t i = 0; i < num_thread; ++i) { |
| pthread_create(&threads[i], NULL, &thread_intrecorder, (void *)intrecorder); |
| } |
| long totol_time = 0; |
| for (size_t i = 0; i < num_thread; ++i) { |
| void *ret = NULL; |
| pthread_join(threads[i], &ret); |
| totol_time += (long)ret; |
| } |
| long avg_time = totol_time / (OPS_PER_THREAD_INTRECORDER * num_thread); |
| EXPECT_EQ(2ul * (1 + OPS_PER_THREAD_INTRECORDER) / 2 * OPS_PER_THREAD_INTRECORDER, intrecorder->average()); |
| return avg_time; |
| } |
| |
| class MultiDimensionTest : public testing::Test { |
| protected: |
| void SetUp() {} |
| void TearDown() { |
| } |
| }; |
| |
| TEST_F(MultiDimensionTest, madder) { |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::MultiDimension<bvar::Adder<uint32_t> > my_madder1("request_count_madder_uint32_t", labels); |
| bvar::Adder<uint32_t>* my_adder1 = my_madder1.get_stats(labels_value); |
| ASSERT_TRUE(my_adder1); |
| ASSERT_TRUE(my_adder1->valid()); |
| *my_adder1 << 2 << 4; |
| ASSERT_EQ(6u, my_adder1->get_value()); |
| |
| bvar::MultiDimension<bvar::Adder<double> > my_madder2("request_count_madder_double", labels); |
| bvar::Adder<double>* my_adder2 = my_madder2.get_stats(labels_value); |
| ASSERT_TRUE(my_adder2); |
| ASSERT_TRUE(my_adder2->valid()); |
| *my_adder2 << 2.0 << 4.0; |
| ASSERT_EQ(6.0, my_adder2->get_value()); |
| |
| bvar::MultiDimension<bvar::Adder<int> > my_madder3("request_count_madder_int", labels); |
| bvar::Adder<int>* my_adder3 = my_madder3.get_stats(labels_value); |
| ASSERT_TRUE(my_adder3); |
| ASSERT_TRUE(my_adder3->valid()); |
| *my_adder3 << -9 << 1 << 0 << 3; |
| ASSERT_EQ(-5, my_adder3->get_value()); |
| |
| bvar::MultiDimension<bvar::Adder<std::string> > my_madder_str("my_string", labels); |
| bvar::Adder<std::string> *my_str1 = my_madder_str.get_stats(labels_value); |
| ASSERT_TRUE(my_str1); |
| std::string str1 = "world"; |
| *my_str1 << "hello " << str1; |
| ASSERT_STREQ("hello world", my_str1->get_value().c_str()); |
| } |
| |
| TEST_F(MultiDimensionTest, mmadder_perf) { |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::MultiDimension<bvar::Adder<uint64_t> > my_madder1("request_count_madder_uint64_t", labels); |
| bvar::Adder<uint64_t>* my_adder = my_madder1.get_stats(labels_value); |
| ASSERT_TRUE(my_adder); |
| |
| std::ostringstream oss; |
| for (size_t i = 1; i <= num_thread; ++i) { |
| my_adder->reset(); |
| oss << i << '\t' << start_perf_test_with_madder(i, my_adder) << '\n'; |
| } |
| LOG(INFO) << "Adder performance:\n" << oss.str(); |
| } |
| |
| TEST_F(MultiDimensionTest, mmaxer) { |
| bvar::MultiDimension<bvar::Maxer<int> > my_mmaxer("request_count_mmaxer", labels); |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::Maxer<int>* my_maxer = my_mmaxer.get_stats(labels_value); |
| ASSERT_TRUE(my_maxer); |
| *my_maxer << 1 << 2 << 3; |
| ASSERT_EQ(3, my_maxer->get_value()); |
| } |
| |
| TEST_F(MultiDimensionTest, mmaxer_perf) { |
| bvar::MultiDimension<bvar::Maxer<uint64_t> > my_mmaxer("request_count_mmaxer", labels); |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::Maxer<uint64_t>* my_maxer = my_mmaxer.get_stats(labels_value); |
| ASSERT_TRUE(my_maxer); |
| |
| std::ostringstream oss; |
| for (size_t i = 1; i <= num_thread; ++i) { |
| my_maxer->reset(); |
| oss << i << '\t' << start_perf_test_with_mmaxer(i, my_maxer) << '\n'; |
| } |
| LOG(INFO) << "Maxer performance:\n" << oss.str(); |
| } |
| |
| TEST_F(MultiDimensionTest, mminer) { |
| bvar::MultiDimension<bvar::Miner<int> > my_mminer("client_request_count_mminer", labels); |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::Miner<int>* my_miner = my_mminer.get_stats(labels_value); |
| ASSERT_TRUE(my_miner); |
| *my_miner << 1 << 2 << 3; |
| ASSERT_EQ(1, my_miner->get_value()); |
| } |
| |
| TEST_F(MultiDimensionTest, mminer_perf) { |
| bvar::MultiDimension<bvar::Miner<uint64_t> > my_mminer("request_count_mminer", labels); |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::Miner<uint64_t>* my_miner = my_mminer.get_stats(labels_value); |
| ASSERT_TRUE(my_miner); |
| |
| std::ostringstream oss; |
| for (size_t i = 1; i <= num_thread; ++i) { |
| my_miner->reset(); |
| oss << i << '\t' << start_perf_test_with_mminer(i, my_miner) << '\n'; |
| } |
| LOG(INFO) << "Miner performance:\n" << oss.str(); |
| } |
| |
| |
| TEST_F(MultiDimensionTest, mintrecoder) { |
| bvar::MultiDimension<bvar::IntRecorder> my_mintrecorder("client_request_count_mintrecorder", labels); |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::IntRecorder* my_intrecorder = my_mintrecorder.get_stats(labels_value); |
| ASSERT_TRUE(my_intrecorder); |
| *my_intrecorder << 1 << 2 << 3; |
| ASSERT_EQ(2, my_intrecorder->average()); |
| } |
| |
| TEST_F(MultiDimensionTest, mintrecorder_perf) { |
| bvar::MultiDimension<bvar::IntRecorder> my_mintrecorder("request_count_mintrecorder", labels); |
| std::list<std::string> labels_value = {"bj", "get", "200"}; |
| bvar::IntRecorder* my_intrecorder = my_mintrecorder.get_stats(labels_value); |
| ASSERT_TRUE(my_intrecorder); |
| |
| std::ostringstream oss; |
| for (size_t i = 1; i <= num_thread; ++i) { |
| my_intrecorder->reset(); |
| oss << i << '\t' << start_perf_test_with_mintrecorder(i, my_intrecorder) << '\n'; |
| } |
| LOG(INFO) << "IntRecorder performance:\n" << oss.str(); |
| } |
| |
| TEST_F(MultiDimensionTest, stats) { |
| std::vector<std::list<std::string> > vec_labels; |
| std::vector<std::list<std::string> > vec_labels_no_sort; |
| bvar::MultiDimension<bvar::Adder<int> > my_madder("test_stats", labels); |
| ASSERT_EQ(0, my_madder.count_stats()); |
| std::list<std::string> labels_value1 = {"tc", "get", "200"}; |
| ASSERT_FALSE(my_madder.has_stats(labels_value1)); |
| vec_labels.push_back(labels_value1); |
| vec_labels_no_sort.push_back(labels_value1); |
| bvar::Adder<int>* adder1 = my_madder.get_stats(labels_value1); |
| ASSERT_TRUE(adder1); |
| ASSERT_TRUE(my_madder.has_stats(labels_value1)); |
| std::vector<std::list<std::string> > ret_labels; |
| my_madder.list_stats(&ret_labels); |
| ASSERT_EQ(vec_labels, ret_labels); |
| ASSERT_EQ(1, my_madder.count_stats()); |
| |
| std::list<std::string> labels_value2 = {"nj", "get", "200"}; |
| ASSERT_FALSE(my_madder.has_stats(labels_value2)); |
| bvar::Adder<int>* adder2 = my_madder.get_stats(labels_value2); |
| ASSERT_TRUE(adder2); |
| ASSERT_TRUE(my_madder.has_stats(labels_value2)); |
| vec_labels.push_back(labels_value2); |
| vec_labels_no_sort.push_back(labels_value2); |
| my_madder.list_stats(&ret_labels); |
| sort(vec_labels.begin(), vec_labels.end()); |
| sort(ret_labels.begin(), ret_labels.end()); |
| ASSERT_EQ(vec_labels, ret_labels); |
| ASSERT_EQ(2, my_madder.count_stats()); |
| |
| std::list<std::string> labels_value3 = {"hz", "post", "500"}; |
| ASSERT_FALSE(my_madder.has_stats(labels_value3)); |
| bvar::Adder<int>* adder3 = my_madder.get_stats(labels_value3); |
| ASSERT_TRUE(adder3); |
| ASSERT_TRUE(my_madder.has_stats(labels_value3)); |
| vec_labels.push_back(labels_value3); |
| vec_labels_no_sort.push_back(labels_value3); |
| my_madder.list_stats(&ret_labels); |
| sort(vec_labels.begin(), vec_labels.end()); |
| sort(ret_labels.begin(), ret_labels.end()); |
| ASSERT_EQ(vec_labels, ret_labels); |
| ASSERT_EQ(3, my_madder.count_stats()); |
| |
| std::list<std::string> labels_value4 = {"gz", "post", "500"}; |
| ASSERT_FALSE(my_madder.has_stats(labels_value4)); |
| bvar::Adder<int>* adder4 = my_madder.get_stats(labels_value4); |
| ASSERT_TRUE(adder4); |
| ASSERT_TRUE(my_madder.has_stats(labels_value4)); |
| ASSERT_EQ(4, my_madder.count_stats()); |
| vec_labels.push_back(labels_value4); |
| vec_labels_no_sort.push_back(labels_value4); |
| my_madder.list_stats(&ret_labels); |
| sort(vec_labels.begin(), vec_labels.end()); |
| sort(ret_labels.begin(), ret_labels.end()); |
| ASSERT_EQ(vec_labels, ret_labels); |
| ASSERT_EQ(4, my_madder.count_stats()); |
| |
| my_madder.delete_stats(labels_value4); |
| ASSERT_FALSE(my_madder.has_stats(labels_value4)); |
| ASSERT_EQ(3, my_madder.count_stats()); |
| vec_labels_no_sort.pop_back(); |
| my_madder.list_stats(&ret_labels); |
| sort(vec_labels_no_sort.begin(), vec_labels_no_sort.end()); |
| sort(ret_labels.begin(), ret_labels.end()); |
| ASSERT_EQ(vec_labels_no_sort, ret_labels); |
| |
| ASSERT_TRUE(my_madder.has_stats(labels_value1)); |
| ASSERT_TRUE(my_madder.has_stats(labels_value2)); |
| ASSERT_TRUE(my_madder.has_stats(labels_value3)); |
| ASSERT_FALSE(my_madder.has_stats(labels_value4)); |
| |
| my_madder.clear_stats(); |
| ASSERT_EQ(0, my_madder.count_stats()); |
| ASSERT_FALSE(my_madder.has_stats(labels_value1)); |
| ASSERT_FALSE(my_madder.has_stats(labels_value2)); |
| ASSERT_FALSE(my_madder.has_stats(labels_value3)); |
| ASSERT_FALSE(my_madder.has_stats(labels_value4)); |
| bvar::Adder<int> *adder5 = my_madder.get_stats(labels_value1); |
| ASSERT_TRUE(adder5); |
| } |
| |
| TEST_F(MultiDimensionTest, get_description) { |
| bvar::MultiDimension<bvar::Adder<int> > my_madder("test_get_description", labels); |
| std::list<std::string> labels_value1 = {"gz", "post", "200"}; |
| bvar::Adder<int>* adder1 = my_madder.get_stats(labels_value1); |
| ASSERT_TRUE(adder1); |
| *adder1 << 1; |
| std::list<std::string> labels_value2 = {"tc", "post", "200"}; |
| bvar::Adder<int>* adder2 = my_madder.get_stats(labels_value2); |
| ASSERT_TRUE(adder2); |
| *adder2 << 2; |
| |
| const std::string description = my_madder.get_description(); |
| LOG(INFO) << "description=" << description; |
| BUTIL_RAPIDJSON_NAMESPACE::Document doc; |
| doc.Parse(description.c_str()); |
| ASSERT_FALSE(doc.HasParseError()); |
| ASSERT_TRUE(doc.IsObject()); |
| ASSERT_TRUE(doc.HasMember("name")); |
| ASSERT_TRUE(doc["name"].IsString()); |
| ASSERT_STREQ("test_get_description", doc["name"].GetString()); |
| |
| ASSERT_TRUE(doc.HasMember("stats_count")); |
| ASSERT_TRUE(doc["stats_count"].IsInt()); |
| ASSERT_EQ(2, doc["stats_count"].GetInt()); |
| |
| ASSERT_TRUE(doc.HasMember("labels")); |
| ASSERT_TRUE(doc["labels"].IsArray()); |
| |
| BUTIL_RAPIDJSON_NAMESPACE::Value& labels = doc["labels"]; |
| ASSERT_EQ(3, labels.Size()); |
| ASSERT_STREQ(labels[0].GetString(), "idc"); |
| ASSERT_STREQ(labels[1].GetString(), "method"); |
| ASSERT_STREQ(labels[2].GetString(), "status"); |
| } |
| |
| TEST_F(MultiDimensionTest, mlatencyrecorder) { |
| std::string old_bvar_dump_interval; |
| std::string old_mbvar_dump; |
| std::string old_bvar_latency_p1; |
| std::string old_bvar_latency_p2; |
| std::string old_bvar_latency_p3; |
| |
| GFLAGS_NAMESPACE::GetCommandLineOption("bvar_dump_interval", &old_bvar_dump_interval); |
| GFLAGS_NAMESPACE::GetCommandLineOption("mbvar_dump", &old_mbvar_dump); |
| GFLAGS_NAMESPACE::GetCommandLineOption("bvar_latency_p1", &old_bvar_latency_p1); |
| GFLAGS_NAMESPACE::GetCommandLineOption("bvar_latency_p2", &old_bvar_latency_p2); |
| GFLAGS_NAMESPACE::GetCommandLineOption("bvar_latency_p3", &old_bvar_latency_p3); |
| |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_dump_interval", "1"); |
| GFLAGS_NAMESPACE::SetCommandLineOption("mbvar_dump", "true"); |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_latency_p1", "60"); |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_latency_p2", "70"); |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_latency_p3", "80"); |
| |
| bvar::MultiDimension<bvar::LatencyRecorder> my_mlatencyrecorder("client_request_count_mlatencyrecorder", labels); |
| std::list<std::string> labels_value = {"tc", "get", "200"}; |
| bvar::LatencyRecorder* my_latencyrecorder = my_mlatencyrecorder.get_stats(labels_value); |
| ASSERT_TRUE(my_latencyrecorder); |
| *my_latencyrecorder << 1 << 2 << 3 << 4 << 5 << 6 << 7; |
| sleep(1); |
| ASSERT_EQ(4, my_latencyrecorder->latency()); |
| ASSERT_EQ(7, my_latencyrecorder->max_latency()); |
| ASSERT_LE(7, my_latencyrecorder->qps()); |
| ASSERT_EQ(7, my_latencyrecorder->count()); |
| |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_dump_interval", old_bvar_dump_interval.c_str()); |
| GFLAGS_NAMESPACE::SetCommandLineOption("mbvar_dump", old_mbvar_dump.c_str()); |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_latency_p1", old_bvar_latency_p1.c_str()); |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_latency_p2", old_bvar_latency_p2.c_str()); |
| GFLAGS_NAMESPACE::SetCommandLineOption("bvar_latency_p3", old_bvar_latency_p3.c_str()); |
| } |
| |
| TEST_F(MultiDimensionTest, mstatus) { |
| bvar::MultiDimension<bvar::Status<int> > my_mstatus("my_mstatus", labels); |
| std::list<std::string> labels_value {"tc", "get", "200"}; |
| bvar::Status<int>* my_status = my_mstatus.get_stats(labels_value); |
| ASSERT_TRUE(my_status); |
| my_status->set_value(1); |
| ASSERT_EQ(1, my_status->get_value()); |
| } |
| |
| typedef size_t (*hash_fun)(const std::list<std::string>& labels_name); |
| |
| static uint64_t perf_hash(hash_fun fn) { |
| uint64_t cost = 0; |
| for (int i = 0; i < idc_count; i++) { |
| std::ostringstream oss_idc; |
| oss_idc << "idc" << i; |
| for (int j = 0; j < method_count; j++) { |
| std::ostringstream oss_method; |
| oss_method << "method" << j; |
| for (int k = 0; k < status_count; k++) { |
| std::ostringstream oss_status; |
| oss_status << "status" << k; |
| std::list<std::string> labels_value {oss_idc.str(), oss_method.str(), oss_status.str()}; |
| butil::Timer timer(butil::Timer::STARTED); |
| size_t hash_code = fn(labels_value); |
| EXPECT_NE(0, hash_code); |
| timer.stop(); |
| cost += timer.n_elapsed(); |
| } |
| } |
| } |
| return cost; |
| } |
| |
| static size_t hash_fun1(const std::list<std::string>& labels_value) { |
| size_t hash_value = 0; |
| for (auto &k : labels_value) { |
| hash_value += std::hash<std::string>()(k); |
| } |
| return hash_value; |
| } |
| |
| static size_t hash_fun2(const std::list<std::string>& labels_value) { |
| std::string hash_str; |
| for (auto &k : labels_value) { |
| hash_str.append(k); |
| } |
| return std::hash<std::string>()(hash_str); |
| } |
| |
| static size_t hash_fun3(const std::list<std::string>& labels_value) { |
| std::ostringstream oss; |
| for (auto &k : labels_value) { |
| oss << k; |
| } |
| return std::hash<std::string>()(oss.str()); |
| } |
| |
| TEST_F(MultiDimensionTest, test_hash) { |
| std::ostringstream oss; |
| oss << "hash_fun1 \t" << perf_hash(hash_fun1) << "\n" |
| << "hash_fun2 \t" << perf_hash(hash_fun2) << "\n" |
| << "hash_fun3 \t" << perf_hash(hash_fun3) << "\n"; |
| LOG(INFO) << "Hash fun performance:\n" << oss.str(); |
| } |
| |