diff --git a/api/envoy/config/cluster/v3/cluster.proto b/api/envoy/config/cluster/v3/cluster.proto index fdaed973a16c..6123bd59c14e 100644 --- a/api/envoy/config/cluster/v3/cluster.proto +++ b/api/envoy/config/cluster/v3/cluster.proto @@ -334,6 +334,31 @@ message Cluster { // The number of random healthy hosts from which the host with the fewest active requests will // be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. google.protobuf.UInt32Value choice_count = 1 [(validate.rules).uint32 = {gte: 2}]; + + // The following formula is used to calculate the dynamic weights when hosts have different load + // balancing weights: + // + // `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + // + // The larger the active request bias is, the more aggressively active requests will lower the + // effective weight when all host weights are not equal. + // + // `active_request_bias` must be greater than or equal to 0.0. + // + // When `active_request_bias == 0.0` the Least Request Load Balancer doesn't consider the number + // of active requests at the time it picks a host and behaves like the Round Robin Load + // Balancer. + // + // When `active_request_bias > 0.0` the Least Request Load Balancer scales the load balancing + // weight by the number of active requests at the time it does a pick. + // + // The value is cached for performance reasons and refreshed whenever one of the Load Balancer's + // host sets changes, e.g., whenever there is a host membership update or a host load balancing + // weight change. + // + // .. note:: + // This setting only takes effect if all host weights are not equal. + core.v3.RuntimeDouble active_request_bias = 2; } // Specific configuration for the :ref:`RingHash` diff --git a/api/envoy/config/cluster/v4alpha/cluster.proto b/api/envoy/config/cluster/v4alpha/cluster.proto index a6e58aef1d4c..6c1302d28941 100644 --- a/api/envoy/config/cluster/v4alpha/cluster.proto +++ b/api/envoy/config/cluster/v4alpha/cluster.proto @@ -337,6 +337,31 @@ message Cluster { // The number of random healthy hosts from which the host with the fewest active requests will // be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. google.protobuf.UInt32Value choice_count = 1 [(validate.rules).uint32 = {gte: 2}]; + + // The following formula is used to calculate the dynamic weights when hosts have different load + // balancing weights: + // + // `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + // + // The larger the active request bias is, the more aggressively active requests will lower the + // effective weight when all host weights are not equal. + // + // `active_request_bias` must be greater than or equal to 0.0. + // + // When `active_request_bias == 0.0` the Least Request Load Balancer doesn't consider the number + // of active requests at the time it picks a host and behaves like the Round Robin Load + // Balancer. + // + // When `active_request_bias > 0.0` the Least Request Load Balancer scales the load balancing + // weight by the number of active requests at the time it does a pick. + // + // The value is cached for performance reasons and refreshed whenever one of the Load Balancer's + // host sets changes, e.g., whenever there is a host membership update or a host load balancing + // weight change. + // + // .. note:: + // This setting only takes effect if all host weights are not equal. + core.v4alpha.RuntimeDouble active_request_bias = 2; } // Specific configuration for the :ref:`RingHash` diff --git a/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst b/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst index 5336dccb14c3..38b6c6fae88a 100644 --- a/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst +++ b/docs/root/intro/arch_overview/upstream/load_balancing/load_balancers.rst @@ -41,11 +41,25 @@ same or different weights. less than or equal to all of the other hosts. * *all weights not equal*: If two or more hosts in the cluster have different load balancing weights, the load balancer shifts into a mode where it uses a weighted round robin schedule in - which weights are dynamically adjusted based on the host's request load at the time of selection - (weight is divided by the current active request count. For example, a host with weight 2 and an - active request count of 4 will have a synthetic weight of 2 / 4 = 0.5). This algorithm provides - good balance at steady state but may not adapt to load imbalance as quickly. Additionally, unlike - P2C, a host will never truly drain, though it will receive fewer requests over time. + which weights are dynamically adjusted based on the host's request load at the time of selection. + + In this case the weights are calculated at the time a host is picked using the following formula: + + `weight = load_balancing_weight / (active_requests + 1)^active_request_bias`. + + :ref:`active_request_bias` + can be configured via runtime and defaults to 1.0. It must be greater than or equal to 0.0. + + The larger the active request bias is, the more aggressively active requests will lower the + effective weight. + + If `active_request_bias` is set to 0.0, the least request load balancer behaves like the round + robin load balancer and ignores the active request count at the time of picking. + + For example, if active_request_bias is 1.0, a host with weight 2 and an active request count of 4 + will have an effective weight of 2 / (4 + 1)^1 = 0.4. This algorithm provides good balance at + steady state but may not adapt to load imbalance as quickly. Additionally, unlike P2C, a host will + never truly drain, though it will receive fewer requests over time. .. _arch_overview_load_balancing_types_ring_hash: diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 91b93b797ffa..4494f39d3822 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -30,6 +30,7 @@ Removed Config or Runtime New Features ------------ * grpc-json: support specifying `response_body` field in for `google.api.HttpBody` message. +* load balancer: added a :ref:`configuration` option to specify the active request bias used by the least request load balancer. * tap: added :ref:`generic body matcher` to scan http requests and responses for text or hex patterns. Deprecated diff --git a/generated_api_shadow/envoy/config/cluster/v3/cluster.proto b/generated_api_shadow/envoy/config/cluster/v3/cluster.proto index 32a6c4e3d7a4..cf6b9cb652b3 100644 --- a/generated_api_shadow/envoy/config/cluster/v3/cluster.proto +++ b/generated_api_shadow/envoy/config/cluster/v3/cluster.proto @@ -334,6 +334,31 @@ message Cluster { // The number of random healthy hosts from which the host with the fewest active requests will // be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. google.protobuf.UInt32Value choice_count = 1 [(validate.rules).uint32 = {gte: 2}]; + + // The following formula is used to calculate the dynamic weights when hosts have different load + // balancing weights: + // + // `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + // + // The larger the active request bias is, the more aggressively active requests will lower the + // effective weight when all host weights are not equal. + // + // `active_request_bias` must be greater than or equal to 0.0. + // + // When `active_request_bias == 0.0` the Least Request Load Balancer doesn't consider the number + // of active requests at the time it picks a host and behaves like the Round Robin Load + // Balancer. + // + // When `active_request_bias > 0.0` the Least Request Load Balancer scales the load balancing + // weight by the number of active requests at the time it does a pick. + // + // The value is cached for performance reasons and refreshed whenever one of the Load Balancer's + // host sets changes, e.g., whenever there is a host membership update or a host load balancing + // weight change. + // + // .. note:: + // This setting only takes effect if all host weights are not equal. + core.v3.RuntimeDouble active_request_bias = 2; } // Specific configuration for the :ref:`RingHash` diff --git a/generated_api_shadow/envoy/config/cluster/v4alpha/cluster.proto b/generated_api_shadow/envoy/config/cluster/v4alpha/cluster.proto index a6e58aef1d4c..6c1302d28941 100644 --- a/generated_api_shadow/envoy/config/cluster/v4alpha/cluster.proto +++ b/generated_api_shadow/envoy/config/cluster/v4alpha/cluster.proto @@ -337,6 +337,31 @@ message Cluster { // The number of random healthy hosts from which the host with the fewest active requests will // be chosen. Defaults to 2 so that we perform two-choice selection if the field is not set. google.protobuf.UInt32Value choice_count = 1 [(validate.rules).uint32 = {gte: 2}]; + + // The following formula is used to calculate the dynamic weights when hosts have different load + // balancing weights: + // + // `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + // + // The larger the active request bias is, the more aggressively active requests will lower the + // effective weight when all host weights are not equal. + // + // `active_request_bias` must be greater than or equal to 0.0. + // + // When `active_request_bias == 0.0` the Least Request Load Balancer doesn't consider the number + // of active requests at the time it picks a host and behaves like the Round Robin Load + // Balancer. + // + // When `active_request_bias > 0.0` the Least Request Load Balancer scales the load balancing + // weight by the number of active requests at the time it does a pick. + // + // The value is cached for performance reasons and refreshed whenever one of the Load Balancer's + // host sets changes, e.g., whenever there is a host membership update or a host load balancing + // weight change. + // + // .. note:: + // This setting only takes effect if all host weights are not equal. + core.v4alpha.RuntimeDouble active_request_bias = 2; } // Specific configuration for the :ref:`RingHash` diff --git a/source/common/runtime/BUILD b/source/common/runtime/BUILD index 3c3201b69a9e..61b63093da25 100644 --- a/source/common/runtime/BUILD +++ b/source/common/runtime/BUILD @@ -34,6 +34,7 @@ envoy_cc_library( ], deps = [ "//include/envoy/runtime:runtime_interface", + "//source/common/protobuf:utility_lib", "@envoy_api//envoy/config/core/v3:pkg_cc_proto", "@envoy_api//envoy/type/v3:pkg_cc_proto", ], diff --git a/source/common/runtime/runtime_protos.h b/source/common/runtime/runtime_protos.h index 06b0e5816d5a..855b145121db 100644 --- a/source/common/runtime/runtime_protos.h +++ b/source/common/runtime/runtime_protos.h @@ -35,6 +35,8 @@ class Double { : runtime_key_(double_proto.runtime_key()), default_value_(double_proto.default_value()), runtime_(runtime) {} + const std::string& runtimeKey() const { return runtime_key_; } + double value() const { return runtime_.snapshot().getDouble(runtime_key_, default_value_); } private: diff --git a/source/common/upstream/BUILD b/source/common/upstream/BUILD index 4182da69370f..14eb0236b542 100644 --- a/source/common/upstream/BUILD +++ b/source/common/upstream/BUILD @@ -182,6 +182,7 @@ envoy_cc_library( "//include/envoy/upstream:upstream_interface", "//source/common/common:assert_lib", "//source/common/protobuf:utility_lib", + "//source/common/runtime:runtime_protos_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", ], ) diff --git a/source/common/upstream/load_balancer_impl.h b/source/common/upstream/load_balancer_impl.h index acf15027ab30..2ec2f605cbd7 100644 --- a/source/common/upstream/load_balancer_impl.h +++ b/source/common/upstream/load_balancer_impl.h @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include #include #include @@ -12,6 +14,7 @@ #include "envoy/upstream/upstream.h" #include "common/protobuf/utility.h" +#include "common/runtime/runtime_protos.h" #include "common/upstream/edf_scheduler.h" namespace Envoy { @@ -368,6 +371,8 @@ class EdfLoadBalancerBase : public ZoneAwareLoadBalancerBase { void initialize(); + virtual void refresh(uint32_t priority); + // Seed to allow us to desynchronize load balancers across a fleet. If we don't // do this, multiple Envoys that receive an update at the same time (or even // multiple load balancers on the same host) will send requests to @@ -376,7 +381,6 @@ class EdfLoadBalancerBase : public ZoneAwareLoadBalancerBase { const uint64_t seed_; private: - void refresh(uint32_t priority); virtual void refreshHostSource(const HostsSource& source) PURE; virtual double hostWeight(const Host& host) PURE; virtual HostConstSharedPtr unweightedHostPick(const HostVector& hosts_to_use, @@ -438,7 +442,8 @@ class RoundRobinLoadBalancer : public EdfLoadBalancerBase { * The benefit of the Maglev table is at the expense of resolution, memory usage is capped. * Additionally, the Maglev table can be shared amongst all threads. */ -class LeastRequestLoadBalancer : public EdfLoadBalancerBase { +class LeastRequestLoadBalancer : public EdfLoadBalancerBase, + Logger::Loggable { public: LeastRequestLoadBalancer( const PrioritySet& priority_set, const PrioritySet* local_priority_set, ClusterStats& stats, @@ -451,26 +456,71 @@ class LeastRequestLoadBalancer : public EdfLoadBalancerBase { choice_count_( least_request_config.has_value() ? PROTOBUF_GET_WRAPPED_OR_DEFAULT(least_request_config.value(), choice_count, 2) - : 2) { + : 2), + active_request_bias_runtime_( + least_request_config.has_value() && least_request_config->has_active_request_bias() + ? std::make_unique(least_request_config->active_request_bias(), + runtime) + : nullptr) { initialize(); } +protected: + void refresh(uint32_t priority) override { + active_request_bias_ = + active_request_bias_runtime_ != nullptr ? active_request_bias_runtime_->value() : 1.0; + + if (active_request_bias_ < 0.0) { + ENVOY_LOG(warn, "upstream: invalid active request bias supplied (runtime key {}), using 1.0", + active_request_bias_runtime_->runtimeKey()); + active_request_bias_ = 1.0; + } + + EdfLoadBalancerBase::refresh(priority); + } + private: void refreshHostSource(const HostsSource&) override {} double hostWeight(const Host& host) override { - // Here we scale host weight by the number of active requests at the time we do the pick. We - // always add 1 to avoid division by 0. It might be possible to do better by picking two hosts - // off of the schedule, and selecting the one with fewer active requests at the time of - // selection. - // TODO(mattklein123): @htuch brings up the point that how we are scaling weight here might not - // be the only/best way of doing this. Essentially, it makes weight and active requests equally - // important. Are they equally important in practice? There is no right answer here and we might - // want to iterate on this as we gain more experience. - return static_cast(host.weight()) / (host.stats().rq_active_.value() + 1); + // This method is called to calculate the dynamic weight as following when all load balancing + // weights are not equal: + // + // `weight = load_balancing_weight / (active_requests + 1)^active_request_bias` + // + // `active_request_bias` can be configured via runtime and its value is cached in + // `active_request_bias_` to avoid having to do a runtime lookup each time a host weight is + // calculated. + // + // When `active_request_bias == 0.0` we behave like `RoundRobinLoadBalancer` and return the + // host weight without considering the number of active requests at the time we do the pick. + // + // When `active_request_bias > 0.0` we scale the host weight by the number of active + // requests at the time we do the pick. We always add 1 to avoid division by 0. + // + // It might be possible to do better by picking two hosts off of the schedule, and selecting the + // one with fewer active requests at the time of selection. + if (active_request_bias_ == 0.0) { + return host.weight(); + } + + if (active_request_bias_ == 1.0) { + return static_cast(host.weight()) / (host.stats().rq_active_.value() + 1); + } + + return static_cast(host.weight()) / + std::pow(host.stats().rq_active_.value() + 1, active_request_bias_); } HostConstSharedPtr unweightedHostPick(const HostVector& hosts_to_use, const HostsSource& source) override; + const uint32_t choice_count_; + + // The exponent used to calculate host weights can be configured via runtime. We cache it for + // performance reasons and refresh it in `LeastRequestLoadBalancer::refresh(uint32_t priority)` + // whenever a `HostSet` is updated. + double active_request_bias_{}; + + const std::unique_ptr active_request_bias_runtime_; }; /** diff --git a/test/common/upstream/BUILD b/test/common/upstream/BUILD index 7c417471775d..32f280f2d6fb 100644 --- a/test/common/upstream/BUILD +++ b/test/common/upstream/BUILD @@ -194,6 +194,8 @@ envoy_cc_test( "//source/common/upstream:upstream_lib", "//test/mocks/runtime:runtime_mocks", "//test/mocks/upstream:upstream_mocks", + "//test/test_common:logging_lib", + "//test/test_common:test_runtime_lib", "@envoy_api//envoy/config/cluster/v3:pkg_cc_proto", ], ) diff --git a/test/common/upstream/load_balancer_impl_test.cc b/test/common/upstream/load_balancer_impl_test.cc index 06e398018e95..ed89540e2968 100644 --- a/test/common/upstream/load_balancer_impl_test.cc +++ b/test/common/upstream/load_balancer_impl_test.cc @@ -13,6 +13,8 @@ #include "test/common/upstream/utility.h" #include "test/mocks/runtime/mocks.h" #include "test/mocks/upstream/mocks.h" +#include "test/test_common/logging.h" +#include "test/test_common/test_runtime.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -1532,6 +1534,89 @@ TEST_P(LeastRequestLoadBalancerTest, WeightImbalance) { EXPECT_EQ(hostSet().healthy_hosts_[0], lb_.chooseHost(nullptr)); } +// Validate that the load balancer defaults to an active request bias value of 1.0 if the runtime +// value is invalid (less than 0.0). +TEST_P(LeastRequestLoadBalancerTest, WeightImbalanceWithInvalidActiveRequestBias) { + envoy::config::cluster::v3::Cluster::LeastRequestLbConfig lr_lb_config; + lr_lb_config.mutable_active_request_bias()->set_runtime_key("ar_bias"); + lr_lb_config.mutable_active_request_bias()->set_default_value(1.0); + LeastRequestLoadBalancer lb_2{priority_set_, nullptr, stats_, runtime_, + random_, common_config_, lr_lb_config}; + + EXPECT_CALL(runtime_.snapshot_, getDouble("ar_bias", 1.0)).WillRepeatedly(Return(-1.0)); + + hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", 1), + makeTestHost(info_, "tcp://127.0.0.1:81", 2)}; + + hostSet().hosts_ = hostSet().healthy_hosts_; + + // Trigger callbacks. The added/removed lists are not relevant. + EXPECT_LOG_CONTAINS( + "warn", "upstream: invalid active request bias supplied (runtime key ar_bias), using 1.0", + hostSet().runCallbacks({}, {})); + + EXPECT_CALL(random_, random()).WillRepeatedly(Return(0)); + + // We should see 2:1 ratio for hosts[1] to hosts[0]. + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + + // Bringing hosts[1] to an active request should yield a 1:1 ratio. + hostSet().healthy_hosts_[1]->stats().rq_active_.set(1); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + + // Settings hosts[0] to an active request and hosts[1] to no active requests should yield a 4:1 + // ratio. + hostSet().healthy_hosts_[0]->stats().rq_active_.set(1); + hostSet().healthy_hosts_[1]->stats().rq_active_.set(0); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); +} + +TEST_P(LeastRequestLoadBalancerTest, WeightImbalanceWithCustomActiveRequestBias) { + // Create a load balancer with a custom active request bias. + envoy::config::cluster::v3::Cluster::LeastRequestLbConfig lr_lb_config; + lr_lb_config.mutable_active_request_bias()->set_runtime_key("ar_bias"); + lr_lb_config.mutable_active_request_bias()->set_default_value(1.0); + LeastRequestLoadBalancer lb_2{priority_set_, nullptr, stats_, runtime_, + random_, common_config_, lr_lb_config}; + + EXPECT_CALL(runtime_.snapshot_, getDouble("ar_bias", 1.0)).WillRepeatedly(Return(0.0)); + + hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", 1), + makeTestHost(info_, "tcp://127.0.0.1:81", 2)}; + + hostSet().hosts_ = hostSet().healthy_hosts_; + hostSet().runCallbacks({}, {}); // Trigger callbacks. The added/removed lists are not relevant. + + EXPECT_CALL(random_, random()).WillRepeatedly(Return(0)); + + // We should see 2:1 ratio for hosts[1] to hosts[0], regardless of the active request count. + hostSet().healthy_hosts_[1]->stats().rq_active_.set(1); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[0], lb_2.chooseHost(nullptr)); + EXPECT_EQ(hostSet().healthy_hosts_[1], lb_2.chooseHost(nullptr)); +} + TEST_P(LeastRequestLoadBalancerTest, WeightImbalanceCallbacks) { hostSet().healthy_hosts_ = {makeTestHost(info_, "tcp://127.0.0.1:80", 1), makeTestHost(info_, "tcp://127.0.0.1:81", 2)}; diff --git a/test/integration/stats_integration_test.cc b/test/integration/stats_integration_test.cc index d1e19cb32ab1..904a7f94504d 100644 --- a/test/integration/stats_integration_test.cc +++ b/test/integration/stats_integration_test.cc @@ -282,6 +282,7 @@ TEST_P(ClusterMemoryTestRunner, MemoryLargeClusterSizeWithFakeSymbolTable) { // 2020/06/10 11561 44491 44811 Make upstreams pluggable // 2020/06/29 11751 44715 46000 Improve time complexity of removing callback handle // in callback manager. + // 2020/07/07 11252 44971 46000 Introduce Least Request LB active request bias config // Note: when adjusting this value: EXPECT_MEMORY_EQ is active only in CI // 'release' builds, where we control the platform and tool-chain. So you @@ -299,7 +300,7 @@ TEST_P(ClusterMemoryTestRunner, MemoryLargeClusterSizeWithFakeSymbolTable) { // We only run the exact test for ipv6 because ipv4 in some cases may allocate a // different number of bytes. We still run the approximate test. if (ip_version_ != Network::Address::IpVersion::v6) { - EXPECT_MEMORY_EQ(m_per_cluster, 44715); + EXPECT_MEMORY_EQ(m_per_cluster, 44971); } EXPECT_MEMORY_LE(m_per_cluster, 46000); // Round up to allow platform variations. } @@ -353,6 +354,7 @@ TEST_P(ClusterMemoryTestRunner, MemoryLargeClusterSizeWithRealSymbolTable) { // 2020/06/10 11561 36603 36923 Make upstreams pluggable // 2020/06/29 11751 36827 38000 Improve time complexity of removing callback handle. // in callback manager. + // 2020/07/07 11252 37083 38000 Introduce Least Request LB active request bias config // Note: when adjusting this value: EXPECT_MEMORY_EQ is active only in CI // 'release' builds, where we control the platform and tool-chain. So you @@ -370,7 +372,7 @@ TEST_P(ClusterMemoryTestRunner, MemoryLargeClusterSizeWithRealSymbolTable) { // We only run the exact test for ipv6 because ipv4 in some cases may allocate a // different number of bytes. We still run the approximate test. if (ip_version_ != Network::Address::IpVersion::v6) { - EXPECT_MEMORY_EQ(m_per_cluster, 36827); + EXPECT_MEMORY_EQ(m_per_cluster, 37083); } EXPECT_MEMORY_LE(m_per_cluster, 38000); // Round up to allow platform variations. }