128 lines
3.0 KiB
C++
128 lines
3.0 KiB
C++
/**
|
|
* Copyright (c) 2021 OceanBase
|
|
* OceanBase CE is licensed under Mulan PubL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PubL v2.
|
|
* You may obtain a copy of Mulan PubL v2 at:
|
|
* http://license.coscl.org.cn/MulanPubL-2.0
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PubL v2 for more details.
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <iostream>
|
|
#include "lib/thread_local/ob_tsi_utils.h"
|
|
|
|
using namespace oceanbase::common;
|
|
using namespace std;
|
|
|
|
unsigned long long get_ticks(void)
|
|
{
|
|
register uint64_t lo, hi;
|
|
__asm__ __volatile__ (
|
|
"rdtscp" : "=a"(lo), "=d"(hi)
|
|
);
|
|
return hi << 32 | lo;
|
|
|
|
}
|
|
|
|
TEST(TestItid, Basic)
|
|
{
|
|
// This thread is allocate a itid before.
|
|
EXPECT_EQ(1, itid_slots[0]);
|
|
|
|
// And the maximum itid is the only ID: 0
|
|
EXPECT_EQ(0, detect_max_itid());
|
|
|
|
// Allow enough ID and check continuance.
|
|
constexpr int64_t STARTER = 1;
|
|
for (int i = 0; i < 1024*64-1; i++) {
|
|
int64_t itid = alloc_itid();
|
|
EXPECT_EQ(i+STARTER, itid);
|
|
EXPECT_EQ(i+STARTER, detect_max_itid());
|
|
}
|
|
|
|
// Return -1 if exceed total count of itid.
|
|
EXPECT_EQ(INVALID_ITID, alloc_itid());
|
|
EXPECT_EQ(INVALID_ITID, alloc_itid());
|
|
|
|
// Maximum itid is 1024*64-1
|
|
EXPECT_EQ(1024*64-1, detect_max_itid());
|
|
|
|
// Maximum itid changes if free the largest one.
|
|
free_itid(1024*64-1);
|
|
EXPECT_EQ(1024*64-2, detect_max_itid());
|
|
|
|
// Free itids and check maximum itid is right.
|
|
for (int i = 1024*64-2; i > 0; i--) {
|
|
free_itid(i);
|
|
EXPECT_EQ(i-1, detect_max_itid());
|
|
}
|
|
}
|
|
|
|
TEST(TestItid, ThreadAllocFree)
|
|
{
|
|
class Runnable
|
|
: public lib::Threads {
|
|
void run(obsys::CThread *, void *) override
|
|
{
|
|
EXPECT_LT(0, get_itid());
|
|
}
|
|
} r;
|
|
r.set_thread_count(100);
|
|
r.start();
|
|
r.wait();
|
|
EXPECT_EQ(0, get_itid());
|
|
EXPECT_EQ(1, get_max_itid());
|
|
r.start();
|
|
r.wait();
|
|
EXPECT_EQ(0, get_itid());
|
|
EXPECT_EQ(1, get_max_itid());
|
|
}
|
|
|
|
int64_t my_get_max_itid() {
|
|
static __thread int64_t itid = 0;
|
|
if (itid == 0) {
|
|
itid++;
|
|
}
|
|
return itid;
|
|
}
|
|
|
|
TEST(TestItid, Perf)
|
|
{
|
|
int64_t current = 0
|
|
, previous = 0;
|
|
constexpr int64_t N = 1000000;
|
|
{
|
|
auto t1 = get_ticks();
|
|
for (int i = 0; i < N; i++) {
|
|
auto itid = get_max_itid();
|
|
EXPECT_EQ(1, itid);
|
|
}
|
|
auto t2 = get_ticks();
|
|
current = t2 - t1;
|
|
}
|
|
{
|
|
auto t1 = get_ticks();
|
|
for (int i = 0; i < N; i++) {
|
|
auto itid = my_get_max_itid();
|
|
EXPECT_EQ(1, itid);
|
|
}
|
|
auto t2 = get_ticks();
|
|
previous = t2 - t1;
|
|
}
|
|
// Performance of current version of get_max_itid() shouldn't worse
|
|
// more than 10% of previous version of this function which just
|
|
// fetch a thread local variable.
|
|
EXPECT_LE(static_cast<int64_t>((double)current * 0.9), previous)
|
|
<< " current: " << current
|
|
<< ", previous: " << previous << endl;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
::testing::InitGoogleTest(&argc, argv);
|
|
return RUN_ALL_TESTS();
|
|
}
|