252 lines
8.2 KiB
C++
252 lines
8.2 KiB
C++
// 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 2014/10/13 19:47:59
|
|
|
|
#include <pthread.h> // pthread_*
|
|
|
|
#include <cstddef>
|
|
#include <memory>
|
|
#include <iostream>
|
|
#include "butil/time.h"
|
|
#include "butil/macros.h"
|
|
#include "bvar/recorder.h"
|
|
#include "bvar/latency_recorder.h"
|
|
#include <gtest/gtest.h>
|
|
|
|
namespace {
|
|
TEST(RecorderTest, test_complement) {
|
|
LOG(INFO) << "sizeof(LatencyRecorder)=" << sizeof(bvar::LatencyRecorder)
|
|
<< " " << sizeof(bvar::detail::Percentile)
|
|
<< " " << sizeof(bvar::Maxer<int64_t>)
|
|
<< " " << sizeof(bvar::IntRecorder)
|
|
<< " " << sizeof(bvar::Window<bvar::IntRecorder>)
|
|
<< " " << sizeof(bvar::Window<bvar::detail::Percentile>);
|
|
|
|
for (int a = -10000000; a < 10000000; ++a) {
|
|
const uint64_t complement = bvar::IntRecorder::_get_complement(a);
|
|
const int64_t b = bvar::IntRecorder::_extend_sign_bit(complement);
|
|
ASSERT_EQ(a, b);
|
|
}
|
|
}
|
|
|
|
TEST(RecorderTest, test_compress) {
|
|
const uint64_t num = 125345;
|
|
const uint64_t sum = 26032906;
|
|
const uint64_t compressed = bvar::IntRecorder::_compress(num, sum);
|
|
ASSERT_EQ(num, bvar::IntRecorder::_get_num(compressed));
|
|
ASSERT_EQ(sum, bvar::IntRecorder::_get_sum(compressed));
|
|
}
|
|
|
|
TEST(RecorderTest, test_compress_negtive_number) {
|
|
for (int a = -10000000; a < 10000000; ++a) {
|
|
const uint64_t sum = bvar::IntRecorder::_get_complement(a);
|
|
const uint64_t num = 123456;
|
|
const uint64_t compressed = bvar::IntRecorder::_compress(num, sum);
|
|
ASSERT_EQ(num, bvar::IntRecorder::_get_num(compressed));
|
|
ASSERT_EQ(a, bvar::IntRecorder::_extend_sign_bit(bvar::IntRecorder::_get_sum(compressed)));
|
|
}
|
|
}
|
|
|
|
TEST(RecorderTest, sanity) {
|
|
{
|
|
bvar::IntRecorder recorder;
|
|
ASSERT_TRUE(recorder.valid());
|
|
ASSERT_EQ(0, recorder.expose("var1"));
|
|
for (size_t i = 0; i < 100; ++i) {
|
|
recorder << 2;
|
|
}
|
|
ASSERT_EQ(2l, (int64_t)recorder.average());
|
|
ASSERT_EQ("2", bvar::Variable::describe_exposed("var1"));
|
|
std::vector<std::string> vars;
|
|
bvar::Variable::list_exposed(&vars);
|
|
ASSERT_EQ(1UL, vars.size());
|
|
ASSERT_EQ("var1", vars[0]);
|
|
ASSERT_EQ(1UL, bvar::Variable::count_exposed());
|
|
}
|
|
ASSERT_EQ(0UL, bvar::Variable::count_exposed());
|
|
}
|
|
|
|
TEST(RecorderTest, window) {
|
|
bvar::IntRecorder c1;
|
|
ASSERT_TRUE(c1.valid());
|
|
bvar::Window<bvar::IntRecorder> w1(&c1, 1);
|
|
bvar::Window<bvar::IntRecorder> w2(&c1, 2);
|
|
bvar::Window<bvar::IntRecorder> w3(&c1, 3);
|
|
|
|
const int N = 10000;
|
|
int64_t last_time = butil::gettimeofday_us();
|
|
for (int i = 1; i <= N; ++i) {
|
|
c1 << i;
|
|
int64_t now = butil::gettimeofday_us();
|
|
if (now - last_time >= 1000000L) {
|
|
last_time = now;
|
|
LOG(INFO) << "c1=" << c1 << " w1=" << w1 << " w2=" << w2 << " w3=" << w3;
|
|
} else {
|
|
usleep(950);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST(RecorderTest, negative) {
|
|
bvar::IntRecorder recorder;
|
|
ASSERT_TRUE(recorder.valid());
|
|
for (size_t i = 0; i < 3; ++i) {
|
|
recorder << -2;
|
|
}
|
|
ASSERT_EQ(-2, recorder.average());
|
|
}
|
|
|
|
TEST(RecorderTest, positive_overflow) {
|
|
bvar::IntRecorder recorder1;
|
|
ASSERT_TRUE(recorder1.valid());
|
|
for (int i = 0; i < 5; ++i) {
|
|
recorder1 << std::numeric_limits<int64_t>::max();
|
|
}
|
|
ASSERT_EQ(std::numeric_limits<int>::max(), recorder1.average());
|
|
|
|
bvar::IntRecorder recorder2;
|
|
ASSERT_TRUE(recorder2.valid());
|
|
recorder2.set_debug_name("recorder2");
|
|
for (int i = 0; i < 5; ++i) {
|
|
recorder2 << std::numeric_limits<int64_t>::max();
|
|
}
|
|
ASSERT_EQ(std::numeric_limits<int>::max(), recorder2.average());
|
|
|
|
bvar::IntRecorder recorder3;
|
|
ASSERT_TRUE(recorder3.valid());
|
|
recorder3.expose("recorder3");
|
|
for (int i = 0; i < 5; ++i) {
|
|
recorder3 << std::numeric_limits<int64_t>::max();
|
|
}
|
|
ASSERT_EQ(std::numeric_limits<int>::max(), recorder3.average());
|
|
|
|
bvar::LatencyRecorder latency1;
|
|
latency1.expose("latency1");
|
|
latency1 << std::numeric_limits<int64_t>::max();
|
|
|
|
bvar::LatencyRecorder latency2;
|
|
latency2 << std::numeric_limits<int64_t>::max();
|
|
}
|
|
|
|
TEST(RecorderTest, negtive_overflow) {
|
|
bvar::IntRecorder recorder1;
|
|
ASSERT_TRUE(recorder1.valid());
|
|
for (int i = 0; i < 5; ++i) {
|
|
recorder1 << std::numeric_limits<int64_t>::min();
|
|
}
|
|
ASSERT_EQ(std::numeric_limits<int>::min(), recorder1.average());
|
|
|
|
bvar::IntRecorder recorder2;
|
|
ASSERT_TRUE(recorder2.valid());
|
|
recorder2.set_debug_name("recorder2");
|
|
for (int i = 0; i < 5; ++i) {
|
|
recorder2 << std::numeric_limits<int64_t>::min();
|
|
}
|
|
ASSERT_EQ(std::numeric_limits<int>::min(), recorder2.average());
|
|
|
|
bvar::IntRecorder recorder3;
|
|
ASSERT_TRUE(recorder3.valid());
|
|
recorder3.expose("recorder3");
|
|
for (int i = 0; i < 5; ++i) {
|
|
recorder3 << std::numeric_limits<int64_t>::min();
|
|
}
|
|
ASSERT_EQ(std::numeric_limits<int>::min(), recorder3.average());
|
|
|
|
bvar::LatencyRecorder latency1;
|
|
latency1.expose("latency1");
|
|
latency1 << std::numeric_limits<int64_t>::min();
|
|
|
|
bvar::LatencyRecorder latency2;
|
|
latency2 << std::numeric_limits<int64_t>::min();
|
|
}
|
|
|
|
const size_t OPS_PER_THREAD = 20000000;
|
|
|
|
static void *thread_counter(void *arg) {
|
|
bvar::IntRecorder *recorder = (bvar::IntRecorder *)arg;
|
|
butil::Timer timer;
|
|
timer.start();
|
|
for (int i = 0; i < (int)OPS_PER_THREAD; ++i) {
|
|
*recorder << i;
|
|
}
|
|
timer.stop();
|
|
return (void *)(timer.n_elapsed());
|
|
}
|
|
|
|
TEST(RecorderTest, perf) {
|
|
bvar::IntRecorder recorder;
|
|
ASSERT_TRUE(recorder.valid());
|
|
pthread_t threads[8];
|
|
for (size_t i = 0; i < ARRAY_SIZE(threads); ++i) {
|
|
pthread_create(&threads[i], NULL, &thread_counter, (void *)&recorder);
|
|
}
|
|
long totol_time = 0;
|
|
for (size_t i = 0; i < ARRAY_SIZE(threads); ++i) {
|
|
void *ret;
|
|
pthread_join(threads[i], &ret);
|
|
totol_time += (long)ret;
|
|
}
|
|
ASSERT_EQ(((int64_t)OPS_PER_THREAD - 1) / 2, recorder.average());
|
|
LOG(INFO) << "Recorder takes " << totol_time / (OPS_PER_THREAD * ARRAY_SIZE(threads))
|
|
<< "ns per sample with " << ARRAY_SIZE(threads)
|
|
<< " threads";
|
|
}
|
|
|
|
TEST(RecorderTest, latency_recorder_qps_accuracy) {
|
|
bvar::LatencyRecorder lr1(2); // set windows size to 2s
|
|
bvar::LatencyRecorder lr2(2);
|
|
bvar::LatencyRecorder lr3(2);
|
|
bvar::LatencyRecorder lr4(2);
|
|
usleep(3000000); // wait sampler to sample 3 times
|
|
|
|
auto write = [](bvar::LatencyRecorder& lr, int times) {
|
|
for (int i = 0; i < times; ++i) {
|
|
lr << 1;
|
|
}
|
|
};
|
|
write(lr1, 10);
|
|
write(lr2, 11);
|
|
write(lr3, 3);
|
|
write(lr4, 1);
|
|
usleep(1000000); // wait sampler to sample 1 time
|
|
|
|
auto read = [](bvar::LatencyRecorder& lr, double exp_qps, int window_size = 0) {
|
|
int64_t qps_sum = 0;
|
|
int64_t exp_qps_int = (int64_t)exp_qps;
|
|
for (int i = 0; i < 1000; ++i) {
|
|
int64_t qps = window_size ? lr.qps(window_size): lr.qps();
|
|
EXPECT_GE(qps, exp_qps_int - 1);
|
|
EXPECT_LE(qps, exp_qps_int + 1);
|
|
qps_sum += qps;
|
|
}
|
|
double err = fabs(qps_sum / 1000.0 - exp_qps);
|
|
return err;
|
|
};
|
|
ASSERT_GT(0.1, read(lr1, 10/2.0));
|
|
ASSERT_GT(0.1, read(lr2, 11/2.0));
|
|
ASSERT_GT(0.1, read(lr3, 3/2.0));
|
|
ASSERT_GT(0.1, read(lr4, 1/2.0));
|
|
|
|
ASSERT_GT(0.1, read(lr1, 10/3.0, 3));
|
|
ASSERT_GT(0.2, read(lr2, 11/3.0, 3));
|
|
ASSERT_GT(0.1, read(lr3, 3/3.0, 3));
|
|
ASSERT_GT(0.1, read(lr4, 1/3.0, 3));
|
|
}
|
|
|
|
} // namespace
|