1 /* 2 * 3 * Copyright 2016 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 #include <grpc/support/port_platform.h> 20 21 #include "src/core/lib/transport/bdp_estimator.h" 22 23 #include <inttypes.h> 24 #include <stdlib.h> 25 26 #include "src/core/lib/gpr/useful.h" 27 28 grpc_core::TraceFlag grpc_bdp_estimator_trace(false, "bdp_estimator"); 29 30 namespace grpc_core { 31 32 BdpEstimator::BdpEstimator(const char* name) 33 : ping_state_(PingState::UNSCHEDULED), 34 accumulator_(0), 35 estimate_(65536), 36 ping_start_time_(gpr_time_0(GPR_CLOCK_MONOTONIC)), 37 inter_ping_delay_(100.0), // start at 100ms 38 stable_estimate_count_(0), 39 bw_est_(0), 40 name_(name) {} 41 42 grpc_millis BdpEstimator::CompletePing() { 43 gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC); 44 gpr_timespec dt_ts = gpr_time_sub(now, ping_start_time_); 45 double dt = static_cast<double>(dt_ts.tv_sec) + 46 1e-9 * static_cast<double>(dt_ts.tv_nsec); 47 double bw = dt > 0 ? (static_cast<double>(accumulator_) / dt) : 0; 48 int start_inter_ping_delay = inter_ping_delay_; 49 if (grpc_bdp_estimator_trace.enabled()) { 50 gpr_log(GPR_INFO, 51 "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64 52 " dt=%lf bw=%lfMbs bw_est=%lfMbs", 53 name_, accumulator_, estimate_, dt, bw / 125000.0, 54 bw_est_ / 125000.0); 55 } 56 GPR_ASSERT(ping_state_ == PingState::STARTED); 57 if (accumulator_ > 2 * estimate_ / 3 && bw > bw_est_) { 58 estimate_ = GPR_MAX(accumulator_, estimate_ * 2); 59 bw_est_ = bw; 60 if (grpc_bdp_estimator_trace.enabled()) { 61 gpr_log(GPR_INFO, "bdp[%s]: estimate increased to %" PRId64, name_, 62 estimate_); 63 } 64 inter_ping_delay_ /= 2; // if the ping estimate changes, 65 // exponentially get faster at probing 66 } else if (inter_ping_delay_ < 10000) { 67 stable_estimate_count_++; 68 if (stable_estimate_count_ >= 2) { 69 inter_ping_delay_ += 70 100 + static_cast<int>(rand() * 100.0 / 71 RAND_MAX); // if the ping estimate is steady, 72 // slowly ramp down the probe time 73 } 74 } 75 if (start_inter_ping_delay != inter_ping_delay_) { 76 stable_estimate_count_ = 0; 77 if (grpc_bdp_estimator_trace.enabled()) { 78 gpr_log(GPR_INFO, "bdp[%s]:update_inter_time to %dms", name_, 79 inter_ping_delay_); 80 } 81 } 82 ping_state_ = PingState::UNSCHEDULED; 83 accumulator_ = 0; 84 return grpc_core::ExecCtx::Get()->Now() + inter_ping_delay_; 85 } 86 87 } // namespace grpc_core 88