Skip to content

Commit f44e591

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

File tree

7 files changed

+89
-84
lines changed

7 files changed

+89
-84
lines changed

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: 63 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"
@@ -173,6 +174,68 @@ struct QueryPlanRefreshFunctionRetryPolicyOption {
173174
using Type = std::shared_ptr<DataRetryPolicy>;
174175
};
175176

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

178241
/// 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)