Skip to content

Commit 3d37c04

Browse files
committed
impl(bigtable): make dynamic pool options available and update integration tests
1 parent d60f99e commit 3d37c04

7 files changed

Lines changed: 90 additions & 84 deletions

File tree

google/cloud/bigtable/internal/bigtable_random_two_least_used_decorator_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class BigtableRandomTwoLeastUsedTest : public ::testing::Test {
3838
auto instance_name =
3939
bigtable::InstanceResource(Project("my-project"), "my-instance")
4040
.FullName();
41-
DynamicChannelPoolSizingPolicy sizing_policy;
41+
bigtable::experimental::DynamicChannelPoolSizingPolicy sizing_policy;
4242
auto refresh_state = std::make_shared<ConnectionRefreshState>(
4343
fake_cq_impl_, std::chrono::milliseconds(1),
4444
std::chrono::milliseconds(10));

google/cloud/bigtable/internal/bigtable_stub_factory.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,6 @@
2626
#include <functional>
2727
#include <memory>
2828

29-
namespace google::cloud::bigtable {
30-
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
31-
32-
// TODO(#16035): Move this Option to bigtable/options.h in the experimental
33-
// namespace when the feature is ready.
34-
namespace experimental {
35-
/**
36-
* If set, a dynamic channel pool is created for each instance that requests
37-
* are destined. Instances specified as part of this Option have dynamic
38-
* channel pools created and primed as part of DataConnection construction. If
39-
* no Instances are specified, then dynamic channel pool creation is deferred
40-
* until the first request sent, increasing time to first byte latency.
41-
*
42-
* @note This option must be supplied to `MakeDataConnection()` in order to take
43-
* effect.
44-
*/
45-
struct InstanceChannelAffinityOption {
46-
using Type = std::vector<bigtable::InstanceResource>;
47-
};
48-
} // namespace experimental
49-
50-
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
51-
} // namespace google::cloud::bigtable
52-
5329
namespace google {
5430
namespace cloud {
5531
namespace bigtable_internal {

google/cloud/bigtable/internal/dynamic_channel_pool.h

Lines changed: 8 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -34,55 +34,6 @@ namespace cloud {
3434
namespace bigtable_internal {
3535
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
3636

37-
// TODO(#16035): Move this struct and Option to bigtable/options.h in the
38-
// experimental namespace when the feature is ready.
39-
struct DynamicChannelPoolSizingPolicy {
40-
// To reduce channel churn, the pool will not add channels more frequently
41-
// than this period.
42-
std::chrono::milliseconds pool_size_increase_cooldown_interval =
43-
std::chrono::seconds(10);
44-
45-
// Removing unused channels is not as performance critical as adding channels
46-
// to handle a surge in RPC calls. Thus, there are separate cooldown settings
47-
// for each.
48-
std::chrono::milliseconds pool_size_decrease_cooldown_interval =
49-
std::chrono::seconds(120);
50-
51-
struct DiscreteChannels {
52-
explicit DiscreteChannels(int number = 0) : number(number) {}
53-
int number;
54-
};
55-
struct PercentageOfPoolSize {
56-
explicit PercentageOfPoolSize(double percentage = 0.0)
57-
: percentage(percentage) {}
58-
double percentage;
59-
};
60-
absl::variant<DiscreteChannels, PercentageOfPoolSize>
61-
channels_to_add_per_resize = DiscreteChannels{1};
62-
63-
// If the average number of outstanding RPCs is below this threshold,
64-
// the pool size will be decreased.
65-
int minimum_average_outstanding_rpcs_per_channel = 1;
66-
// If the average number of outstanding RPCs is above this threshold,
67-
// the pool size will be increased.
68-
int maximum_average_outstanding_rpcs_per_channel = 25;
69-
70-
// When channels are removed from the pool, we have to wait until all
71-
// outstanding RPCs on that channel are completed before destroying it.
72-
std::chrono::milliseconds remove_channel_polling_interval =
73-
std::chrono::seconds(30);
74-
75-
// Limits how large the pool can grow. Default is twice the minimum_pool_size.
76-
std::size_t maximum_channel_pool_size = 0;
77-
78-
// This is set to the value of GrpcNumChannelsOption.
79-
std::size_t minimum_channel_pool_size = 0;
80-
};
81-
82-
struct DynamicChannelPoolSizingPolicyOption {
83-
using Type = DynamicChannelPoolSizingPolicy;
84-
};
85-
8637
//
8738
// This class manages a pool of Stubs wrapped in a ChannelUsage object, and
8839
// selects one for use using a "Random Two Least Used" strategy.
@@ -107,7 +58,8 @@ class DynamicChannelPool
10758
std::vector<std::shared_ptr<ChannelUsage<T>>> initial_channels,
10859
std::shared_ptr<ConnectionRefreshState> refresh_state,
10960
StubFactoryFn stub_factory_fn,
110-
DynamicChannelPoolSizingPolicy sizing_policy = {}) {
61+
bigtable::experimental::DynamicChannelPoolSizingPolicy sizing_policy =
62+
{}) {
11163
auto pool = std::shared_ptr<DynamicChannelPool>(new DynamicChannelPool(
11264
std::move(instance_name), std::move(cq), std::move(initial_channels),
11365
std::move(refresh_state), std::move(stub_factory_fn),
@@ -207,7 +159,7 @@ class DynamicChannelPool
207159
std::vector<std::shared_ptr<ChannelUsage<T>>> initial_wrapped_channels,
208160
std::shared_ptr<ConnectionRefreshState> refresh_state,
209161
StubFactoryFn stub_factory_fn,
210-
DynamicChannelPoolSizingPolicy sizing_policy)
162+
bigtable::experimental::DynamicChannelPoolSizingPolicy sizing_policy)
211163
: instance_name_(std::move(instance_name)),
212164
cq_(std::move(cq)),
213165
refresh_state_(std::move(refresh_state)),
@@ -293,13 +245,13 @@ class DynamicChannelPool
293245
std::size_t pool_size;
294246
explicit ChannelAddVisitor(std::size_t pool_size) : pool_size(pool_size) {}
295247
std::size_t operator()(
296-
typename DynamicChannelPoolSizingPolicy::DiscreteChannels const& c)
297-
const {
248+
typename bigtable::experimental::DynamicChannelPoolSizingPolicy::
249+
DiscreteChannels const& c) const {
298250
return c.number;
299251
}
300252
std::size_t operator()(
301-
typename DynamicChannelPoolSizingPolicy::PercentageOfPoolSize const& c)
302-
const {
253+
typename bigtable::experimental::DynamicChannelPoolSizingPolicy::
254+
PercentageOfPoolSize const& c) const {
303255
return static_cast<std::size_t>(
304256
std::floor(static_cast<double>(pool_size) * c.percentage));
305257
}
@@ -487,7 +439,7 @@ class DynamicChannelPool
487439
StubFactoryFn stub_factory_fn_;
488440
std::vector<std::shared_ptr<ChannelUsage<T>>> channels_;
489441
std::size_t num_pending_channels_ = 0;
490-
DynamicChannelPoolSizingPolicy sizing_policy_;
442+
bigtable::experimental::DynamicChannelPoolSizingPolicy sizing_policy_;
491443
std::vector<std::shared_ptr<ChannelUsage<T>>> draining_channels_;
492444
future<void> remove_channel_poll_timer_;
493445
future<StatusOr<std::chrono::system_clock::time_point>>

google/cloud/bigtable/internal/dynamic_channel_pool_test.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class DynamicChannelPoolTestWrapper {
103103

104104
namespace {
105105

106+
using ::google::cloud::bigtable::experimental::DynamicChannelPoolSizingPolicy;
106107
using ::google::cloud::bigtable::testing::MockBigtableStub;
107108
using ::google::cloud::testing_util::FakeCompletionQueueImpl;
108109
using ::google::cloud::testing_util::MockCompletionQueueImpl;

google/cloud/bigtable/options.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
*/
4040

4141
#include "google/cloud/bigtable/idempotent_mutation_policy.h"
42+
#include "google/cloud/bigtable/instance_resource.h"
4243
#include "google/cloud/bigtable/internal/endpoint_options.h"
4344
#include "google/cloud/bigtable/retry_policy.h"
4445
#include "google/cloud/bigtable/rpc_retry_policy.h"
@@ -47,6 +48,7 @@
4748
#include "google/cloud/options.h"
4849
#include <chrono>
4950
#include <string>
51+
#include <variant>
5052

5153
namespace google {
5254
namespace cloud {
@@ -173,6 +175,68 @@ struct QueryPlanRefreshFunctionRetryPolicyOption {
173175
using Type = std::shared_ptr<DataRetryPolicy>;
174176
};
175177

178+
/**
179+
* If set, a dynamic channel pool is created for each instance that requests
180+
* are destined. Instances specified as part of this Option have dynamic
181+
* channel pools created and primed as part of DataConnection construction. If
182+
* no Instances are specified, then dynamic channel pool creation is deferred
183+
* until the first request sent, increasing time to first byte latency.
184+
*
185+
* @note This option must be supplied to `MakeDataConnection()` in order to take
186+
* effect.
187+
*/
188+
struct InstanceChannelAffinityOption {
189+
using Type = std::vector<bigtable::InstanceResource>;
190+
};
191+
192+
/**
193+
* If the `InstanceChannelAffinityOption` is set, then all connections will be
194+
* managed by a Dynamic Channel Pool. The `DynamicChannelPoolSizingPolicy` can
195+
* be provided via the `DynamicChannelPoolSizingPolicyOption` and configures
196+
* the behavior of the `DynamicChannelPool`.
197+
*/
198+
struct DynamicChannelPoolSizingPolicy {
199+
// Removing unused channels is not as performance critical as adding channels
200+
// to handle a surge in RPC calls. Thus, there are separate cooldown settings
201+
// for each.
202+
std::chrono::milliseconds pool_size_decrease_cooldown_interval =
203+
std::chrono::seconds(120);
204+
205+
struct DiscreteChannels {
206+
explicit DiscreteChannels(int number = 0) : number(number) {}
207+
int number;
208+
};
209+
struct PercentageOfPoolSize {
210+
explicit PercentageOfPoolSize(double percentage = 0.0)
211+
: percentage(percentage) {}
212+
double percentage;
213+
};
214+
std::variant<DiscreteChannels, PercentageOfPoolSize>
215+
channels_to_add_per_resize = DiscreteChannels{1};
216+
217+
// If the average number of outstanding RPCs is below this threshold,
218+
// the pool size will be decreased.
219+
int minimum_average_outstanding_rpcs_per_channel = 1;
220+
// If the average number of outstanding RPCs is above this threshold,
221+
// the pool size will be increased.
222+
int maximum_average_outstanding_rpcs_per_channel = 25;
223+
224+
// When channels are removed from the pool, we have to wait until all
225+
// outstanding RPCs on that channel are completed before destroying it.
226+
std::chrono::milliseconds remove_channel_polling_interval =
227+
std::chrono::seconds(30);
228+
229+
// Limits how large the pool can grow. Default is twice the minimum_pool_size.
230+
std::size_t maximum_channel_pool_size = 0;
231+
232+
// This is set to the value of GrpcNumChannelsOption.
233+
std::size_t minimum_channel_pool_size = 0;
234+
};
235+
236+
struct DynamicChannelPoolSizingPolicyOption {
237+
using Type = DynamicChannelPoolSizingPolicy;
238+
};
239+
176240
} // namespace experimental
177241

178242
/// The complete list of options accepted by `bigtable::*Client`

google/cloud/bigtable/testing/table_integration_test.cc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,13 @@ void TableAdminTestEnvironment::TearDown() {
122122
}
123123

124124
void TableIntegrationTest::SetUp() {
125-
data_connection_ = MakeDataConnection();
125+
Options options;
126+
if (google::cloud::internal::GetEnv(
127+
"GOOGLE_CLOUD_CPP_BIGTABLE_TESTING_CHANNEL_POOL")
128+
.value_or("") == "dynamic") {
129+
options.set<experimental::InstanceChannelAffinityOption>({});
130+
}
131+
data_connection_ = MakeDataConnection(options);
126132

127133
// In production, we cannot use `DropAllRows()` to cleanup the table because
128134
// the integration tests sometimes consume all the 'DropRowRangeGroup' quota.

google/cloud/bigtable/tests/BUILD.bazel

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,19 @@ package(default_visibility = ["//visibility:private"])
2121

2222
licenses(["notice"]) # Apache 2.0
2323

24+
VARIATIONS = {
25+
"default": {"GOOGLE_CLOUD_CPP_BIGTABLE_TESTING_CHANNEL_POOL": "static"},
26+
"dynamic-pool": {"GOOGLE_CLOUD_CPP_BIGTABLE_TESTING_CHANNEL_POOL": "dynamic"},
27+
}
28+
2429
[cc_test(
25-
name = test.replace("/", "_").replace(".cc", ""),
30+
name = test.replace("/", "_").replace(".cc", "") + "-" + v_label,
2631
timeout = "long",
2732
srcs = [test],
33+
env = v_env,
2834
tags = [
2935
"integration-test",
36+
"integration-test-" + v_label,
3037
],
3138
deps = [
3239
"//:bigtable",
@@ -36,7 +43,7 @@ licenses(["notice"]) # Apache 2.0
3643
"//google/cloud/testing_util:google_cloud_cpp_testing_private",
3744
"@googletest//:gtest_main",
3845
],
39-
) for test in bigtable_client_integration_tests]
46+
) for test in bigtable_client_integration_tests for v_label, v_env in VARIATIONS.items()]
4047

4148
cc_binary(
4249
name = "instance_admin_emulator",

0 commit comments

Comments
 (0)