proxygen
Codel.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <folly/executors/Codel.h>
18 
20 #include <algorithm>
21 
22 DEFINE_int32(codel_interval, 100, "Codel default interval time in ms");
23 DEFINE_int32(codel_target_delay, 5, "Target codel queueing delay in ms");
24 
25 using namespace std::chrono;
26 
27 namespace folly {
28 
29 Codel::Codel()
30  : codelMinDelayNs_(0),
31  codelIntervalTimeNs_(
32  duration_cast<nanoseconds>(steady_clock::now().time_since_epoch())
33  .count()),
34  codelResetDelay_(true),
35  overloaded_(false) {}
36 
37 bool Codel::overloaded(nanoseconds delay) {
38  bool ret = false;
39  auto now = steady_clock::now();
40 
41  // Avoid another thread updating the value at the same time we are using it
42  // to calculate the overloaded state
43  auto minDelay = nanoseconds(codelMinDelayNs_);
44 
45  if (now > steady_clock::time_point(nanoseconds(codelIntervalTimeNs_)) &&
46  // testing before exchanging is more cacheline-friendly
47  (!codelResetDelay_.load(std::memory_order_acquire) &&
48  !codelResetDelay_.exchange(true))) {
50  duration_cast<nanoseconds>((now + getInterval()).time_since_epoch())
51  .count();
52 
53  if (minDelay > getTargetDelay()) {
54  overloaded_ = true;
55  } else {
56  overloaded_ = false;
57  }
58  }
59  // Care must be taken that only a single thread resets codelMinDelay_,
60  // and that it happens after the interval reset above
61  if (codelResetDelay_.load(std::memory_order_acquire) &&
62  codelResetDelay_.exchange(false)) {
63  codelMinDelayNs_ = delay.count();
64  // More than one request must come in during an interval before codel
65  // starts dropping requests
66  return false;
67  } else if (delay < nanoseconds(codelMinDelayNs_)) {
68  codelMinDelayNs_ = delay.count();
69  }
70 
71  // Here is where we apply different logic than codel proper. Instead of
72  // adapting the interval until the next drop, we slough off requests with
73  // queueing delay > 2*target_delay while in the overloaded regime. This
74  // empirically works better for our services than the codel approach of
75  // increasingly often dropping packets.
76  if (overloaded_ && delay > getSloughTimeout()) {
77  ret = true;
78  }
79 
80  return ret;
81 }
82 
84  // it might be better to use the average delay instead of minDelay, but we'd
85  // have to track it. aspiring bootcamper?
86  return std::min<int>(100, 100 * getMinDelay() / getSloughTimeout());
87 }
88 
89 nanoseconds Codel::getMinDelay() {
90  return nanoseconds(codelMinDelayNs_);
91 }
92 
93 milliseconds Codel::getInterval() {
94  return milliseconds(FLAGS_codel_interval);
95 }
96 
97 milliseconds Codel::getTargetDelay() {
98  return milliseconds(FLAGS_codel_target_delay);
99 }
100 
101 milliseconds Codel::getSloughTimeout() {
102  return getTargetDelay() * 2;
103 }
104 
105 } // namespace folly
std::atomic< bool > overloaded_
Definition: Codel.h:90
std::chrono::milliseconds getTargetDelay()
Definition: Codel.cpp:97
std::chrono::steady_clock::time_point now()
int getLoad()
Definition: Codel.cpp:83
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
DEFINE_int32(codel_interval, 100,"Codel default interval time in ms")
std::atomic< uint64_t > codelIntervalTimeNs_
Definition: Codel.h:84
std::atomic< bool > codelResetDelay_
Definition: Codel.h:88
std::chrono::nanoseconds getMinDelay()
Definition: Codel.cpp:89
bool overloaded(std::chrono::nanoseconds delay)
Definition: Codel.cpp:37
std::chrono::milliseconds getInterval()
Definition: Codel.cpp:93
int * count
std::atomic< uint64_t > codelMinDelayNs_
Definition: Codel.h:83
std::chrono::milliseconds getSloughTimeout()
Definition: Codel.cpp:101