Codel.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  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. #pragma once
  17. #include <atomic>
  18. #include <chrono>
  19. #include <folly/portability/GFlags.h>
  20. DECLARE_int32(codel_interval);
  21. DECLARE_int32(codel_target_delay);
  22. namespace folly {
  23. /// CoDel (controlled delay) is an active queue management algorithm from
  24. /// networking for battling bufferbloat.
  25. ///
  26. /// Services also have queues (of requests, not packets) and suffer from
  27. /// queueing delay when overloaded. This class adapts the codel algorithm for
  28. /// services.
  29. ///
  30. /// Codel is discussed in depth on the web [1,2], but a basic sketch of the
  31. /// algorithm is this: if every request has experienced queueing delay greater
  32. /// than the target (5ms) during the past interval (100ms), then we shed load.
  33. ///
  34. /// We have adapted the codel algorithm. TCP sheds load by changing windows in
  35. /// reaction to dropped packets. Codel in a network setting drops packets at
  36. /// increasingly shorter intervals (100 / sqrt(n)) to achieve a linear change
  37. /// in throughput. In our experience a different scheme works better for
  38. /// services: when overloaded slough off requests that we dequeue which have
  39. /// exceeded an alternate timeout (2 * target_delay).
  40. ///
  41. /// So in summary, to use this class, calculate the time each request spent in
  42. /// the queue and feed that delay to overloaded(), which will tell you whether
  43. /// to expire this request.
  44. ///
  45. /// You can also ask for an instantaneous load estimate and the minimum delay
  46. /// observed during this interval.
  47. ///
  48. ///
  49. /// 1. http://queue.acm.org/detail.cfm?id=2209336
  50. /// 2. https://en.wikipedia.org/wiki/CoDel
  51. class Codel {
  52. public:
  53. Codel();
  54. /// Returns true if this request should be expired to reduce overload.
  55. /// In detail, this returns true if min_delay > target_delay for the
  56. /// interval, and this delay > 2 * target_delay.
  57. ///
  58. /// As you may guess, we observe the clock so this is time sensitive. Call
  59. /// it promptly after calculating queueing delay.
  60. bool overloaded(std::chrono::nanoseconds delay);
  61. /// Get the queue load, as seen by the codel algorithm
  62. /// Gives a rough guess at how bad the queue delay is.
  63. ///
  64. /// min(100%, min_delay / (2 * target_delay))
  65. ///
  66. /// Return: 0 = no delay, 100 = At the queueing limit
  67. int getLoad();
  68. std::chrono::nanoseconds getMinDelay();
  69. std::chrono::milliseconds getInterval();
  70. std::chrono::milliseconds getTargetDelay();
  71. std::chrono::milliseconds getSloughTimeout();
  72. private:
  73. std::atomic<uint64_t> codelMinDelayNs_;
  74. std::atomic<uint64_t> codelIntervalTimeNs_;
  75. // flag to make overloaded() thread-safe, since we only want
  76. // to reset the delay once per time period
  77. std::atomic<bool> codelResetDelay_;
  78. std::atomic<bool> overloaded_;
  79. };
  80. } // namespace folly