This is an automated email from the ASF dual-hosted git repository.
alexey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kudu.git
The following commit(s) were added to refs/heads/master by this push:
new fda493d [master-test] added GetTableSchema() microbenchmarks
fda493d is described below
commit fda493d3038661ab2bfcd9d54ff67eef0de9fa9d
Author: Alexey Serbin <[email protected]>
AuthorDate: Mon Apr 27 10:54:35 2020 -0700
[master-test] added GetTableSchema() microbenchmarks
Added a couple of GetTableSchema() microbenchmark tests. These are to
gauge the performance of GetTableSchema() RPCs and the direct calls
to the catalog manager with authz enabled and disabled.
Results for a RELEASE build:
GetTableSchema RPC: 45645 req/sec (authz disabled)
GetTableSchema RPC: 43675.2 req/sec (authz enabled)
GetTableSchema function: 1245196.8 req/sec (authz disabled)
GetTableSchema function: 62765.6 req/sec (authz enabled)
Results for a DEBUG build:
GetTableSchema RPC: 5283 req/sec (authz disabled)
GetTableSchema RPC: 4973.8 req/sec (authz enabled)
GetTableSchema function: 91688 req/sec (authz disabled)
GetTableSchema function: 27960.4 req/sec (authz enabled)
Change-Id: Ic1f3d4fe1df426d50bd465c8ca7bbfb6924bffe9
Reviewed-on: http://gerrit.cloudera.org:8080/15828
Tested-by: Kudu Jenkins
Reviewed-by: Andrew Wong <[email protected]>
---
src/kudu/master/master-test.cc | 163 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 161 insertions(+), 2 deletions(-)
diff --git a/src/kudu/master/master-test.cc b/src/kudu/master/master-test.cc
index fc6c101..a8adda3 100644
--- a/src/kudu/master/master-test.cc
+++ b/src/kudu/master/master-test.cc
@@ -17,13 +17,13 @@
#include "kudu/master/master.h"
-#include <time.h>
-
#include <algorithm>
#include <cstdint>
+#include <ctime>
#include <functional>
#include <map>
#include <memory>
+#include <numeric>
#include <ostream>
#include <set>
#include <string>
@@ -33,6 +33,7 @@
#include <utility>
#include <vector>
+#include <boost/optional/optional.hpp>
#include <gflags/gflags_declare.h>
#include <glog/logging.h>
#include <gtest/gtest.h>
@@ -85,6 +86,7 @@
#include "kudu/util/path_util.h"
#include "kudu/util/pb_util.h"
#include "kudu/util/random.h"
+#include "kudu/util/scoped_cleanup.h"
#include "kudu/util/status.h"
#include "kudu/util/test_macros.h"
#include "kudu/util/test_util.h"
@@ -96,6 +98,7 @@ using kudu::pb_util::SecureShortDebugString;
using kudu::rpc::Messenger;
using kudu::rpc::MessengerBuilder;
using kudu::rpc::RpcController;
+using std::accumulate;
using std::map;
using std::multiset;
using std::pair;
@@ -115,6 +118,7 @@ DECLARE_bool(raft_prepare_replacement_before_eviction);
DECLARE_double(sys_catalog_fail_during_write);
DECLARE_int32(diagnostics_log_stack_traces_interval_ms);
DECLARE_int32(master_inject_latency_on_tablet_lookups_ms);
+DECLARE_int32(rpc_service_queue_length);
DECLARE_int64(live_row_count_for_testing);
DECLARE_int64(on_disk_size_for_testing);
DECLARE_string(location_mapping_cmd);
@@ -1056,6 +1060,161 @@ TEST_F(MasterTest,
TestGetTableSchemaIsAtomicWithCreateTable) {
t.join();
}
+class ConcurrentGetTableSchemaTest :
+ public MasterTest,
+ public ::testing::WithParamInterface<bool> {
+ protected:
+ ConcurrentGetTableSchemaTest()
+ : supports_authz_(GetParam()) {
+ }
+
+ void SetUp() override {
+ MasterTest::SetUp();
+ FLAGS_master_support_authz_tokens = supports_authz_;
+ }
+
+ const bool supports_authz_;
+ static const MonoDelta kRunInterval;
+ static const Schema kTableSchema;
+ static const string kTableNamePattern;
+};
+
+const MonoDelta ConcurrentGetTableSchemaTest::kRunInterval =
+ MonoDelta::FromSeconds(5);
+const Schema ConcurrentGetTableSchemaTest::kTableSchema = {
+ {
+ ColumnSchema("key", INT32),
+ ColumnSchema("v1", UINT64),
+ ColumnSchema("v2", STRING)
+ }, 1 };
+const string ConcurrentGetTableSchemaTest::kTableNamePattern =
"test_table_$0"; // NOLINT
+
+// Send multiple GetTableSchema() RPC requests for different tables.
+TEST_P(ConcurrentGetTableSchemaTest, Rpc) {
+ SKIP_IF_SLOW_NOT_ALLOWED();
+
+ // kNumTables corresponds to the number of threads sending GetTableSchema
+ // RPCs. If setting a bit higher than the RPC queue size limit, there is
+ // a chance of overflowing the RPC queue.
+ const int kNumTables = FLAGS_rpc_service_queue_length;
+
+ for (auto idx = 0; idx < kNumTables; ++idx) {
+ EXPECT_OK(CreateTable(Substitute(kTableNamePattern, idx), kTableSchema));
+ }
+
+ AtomicBool done(false);
+
+ // Start many threads that hammer the master with GetTableSchema() calls
+ // for various tables.
+ vector<thread> caller_threads;
+ caller_threads.reserve(kNumTables);
+ vector<uint64_t> call_counters(kNumTables, 0);
+ vector<uint64_t> error_counters(kNumTables, 0);
+ for (auto idx = 0; idx < kNumTables; ++idx) {
+ caller_threads.emplace_back([&, idx]() {
+ auto table_name = Substitute(kTableNamePattern, idx);
+ GetTableSchemaRequestPB req;
+ req.mutable_table()->set_table_name(table_name);
+ while (!done.Load()) {
+ RpcController controller;
+ GetTableSchemaResponsePB resp;
+ CHECK_OK(proxy_->GetTableSchema(req, &resp, &controller));
+ ++call_counters[idx];
+ if (resp.has_error()) {
+ LOG(WARNING) << "GetTableSchema failed: " << SecureDebugString(resp);
+ ++error_counters[idx];
+ break;
+ }
+ }
+ });
+ }
+ SCOPED_CLEANUP({
+ for (auto& t : caller_threads) {
+ t.join();
+ }
+ });
+
+ SleepFor(kRunInterval);
+ done.Store(true);
+
+ const auto errors = accumulate(error_counters.begin(), error_counters.end(),
0UL);
+ if (errors != 0) {
+ FAIL() << Substitute("detected $0 errors", errors);
+ }
+
+ const double total = accumulate(call_counters.begin(), call_counters.end(),
0UL);
+ LOG(INFO) << Substitute(
+ "GetTableSchema RPC: $0 req/sec (authz $1)",
+ total / kRunInterval.ToSeconds(), supports_authz_ ? "enabled" :
"disabled");
+}
+
+// Run multiple threads calling GetTableSchema() directly to system catalog.
+TEST_P(ConcurrentGetTableSchemaTest, DirectMethodCall) {
+ SKIP_IF_SLOW_NOT_ALLOWED();
+
+ constexpr int kNumTables = 200;
+ static const string kUserName = "test-user";
+
+ for (auto idx = 0; idx < kNumTables; ++idx) {
+ EXPECT_OK(CreateTable(Substitute(kTableNamePattern, idx), kTableSchema));
+ }
+
+ AtomicBool done(false);
+ CatalogManager* cm = mini_master_->master()->catalog_manager();
+ const auto* token_signer = supports_authz_
+ ? mini_master_->master()->token_signer() : nullptr;
+ const auto username = supports_authz_
+ ? boost::make_optional<const string&>(kUserName) : boost::none;
+
+ // Start many threads that hammer the master with GetTableSchema() calls
+ // for various tables.
+ vector<thread> caller_threads;
+ caller_threads.reserve(kNumTables);
+ vector<uint64_t> call_counters(kNumTables, 0);
+ vector<uint64_t> error_counters(kNumTables, 0);
+ for (auto idx = 0; idx < kNumTables; ++idx) {
+ caller_threads.emplace_back([&, idx]() {
+ GetTableSchemaRequestPB req;
+ req.mutable_table()->set_table_name(Substitute(kTableNamePattern, idx));
+ while (!done.Load()) {
+ RpcController controller;
+ GetTableSchemaResponsePB resp;
+ {
+ CatalogManager::ScopedLeaderSharedLock l(cm);
+ CHECK_OK(cm->GetTableSchema(&req, &resp, username, token_signer));
+ }
+ ++call_counters[idx];
+ if (resp.has_error()) {
+ LOG(WARNING) << "GetTableSchema failed: " << SecureDebugString(resp);
+ ++error_counters[idx];
+ break;
+ }
+ }
+ });
+ }
+ SCOPED_CLEANUP({
+ for (auto& t : caller_threads) {
+ t.join();
+ }
+ });
+
+ SleepFor(kRunInterval);
+ done.Store(true);
+
+ const auto errors = accumulate(error_counters.begin(), error_counters.end(),
0UL);
+ if (errors != 0) {
+ FAIL() << Substitute("detected $0 errors", errors);
+ }
+
+ const double total = accumulate(call_counters.begin(), call_counters.end(),
0UL);
+ LOG(INFO) << Substitute(
+ "GetTableSchema function: $0 req/sec (authz $1)",
+ total / kRunInterval.ToSeconds(), supports_authz_ ? "enabled" :
"disabled");
+}
+
+INSTANTIATE_TEST_CASE_P(SupportsAuthzTokens,
+ ConcurrentGetTableSchemaTest, ::testing::Bool());
+
// Verifies that on-disk master metadata is self-consistent and matches a set
// of expected contents.
//