Skip to content

Commit 0b35247

Browse files
Dan Schatzbergmeta-codesync[bot]
authored andcommitted
Add FOLLY_AVAILABLE_CONCURRENCY_MAX env var
Summary: Allow overriding folly::available_concurrency() via the FOLLY_AVAILABLE_CONCURRENCY_MAX environment variable. When set to a valid positive integer, the returned value is capped to the minimum of the env var and the OS-reported count (sched_getaffinity on Linux). This ensures the value is never higher than either signal. This is needed to support removing CPU pinning for overcommitted Tupperware tasks. Without pinning, sched_getaffinity returns all host CPUs, causing massive over-threading in Thrift servers, GlobalExecutor, ServiceRouter, etc. The env var lets TW Agent set the correct concurrency for unpinned containers. Reviewed By: yfeldblum Differential Revision: D94916141 fbshipit-source-id: fa1c916a9a06a9dcc71cc04271d83d00b15fdc66
1 parent 0d43647 commit 0b35247

4 files changed

Lines changed: 56 additions & 2 deletions

File tree

third-party/folly/src/folly/system/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ folly_add_library(
6262
HEADERS
6363
HardwareConcurrency.h
6464
DEPS
65+
folly_conv
6566
folly_lang_safe_assert
6667
folly_portability_sched
6768
folly_utility
69+
EXPORTED_DEPS
70+
folly_lang_cstring_view
6871
)
6972

7073
folly_add_library(

third-party/folly/src/folly/system/HardwareConcurrency.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@
1616

1717
#include <folly/system/HardwareConcurrency.h>
1818

19+
#include <algorithm>
1920
#include <atomic>
21+
#include <cstdlib>
2022
#include <thread>
2123

24+
#include <folly/Conv.h>
2225
#include <folly/Utility.h>
2326
#include <folly/lang/SafeAssert.h>
2427
#include <folly/portability/Sched.h>
@@ -124,12 +127,24 @@ cpu_set_state::~cpu_set_state() {
124127
#endif
125128

126129
unsigned int available_concurrency() noexcept {
130+
unsigned int count;
127131
#if defined(__linux__) && !defined(__ANDROID__)
128132
cpu_set_t stackset;
129-
return to_narrow(cpu_set_state::ask(&stackset).cpu_count());
133+
count = to_narrow(cpu_set_state::ask(&stackset).cpu_count());
134+
#else
135+
count = std::thread::hardware_concurrency();
130136
#endif
131137

132-
return std::thread::hardware_concurrency();
138+
// Allow overriding via environment variable. The returned value is capped to
139+
// the smaller of the env var and the OS-reported count.
140+
if (auto const* env = std::getenv(available_concurrency_max_env.c_str())) {
141+
auto val = folly::tryTo<unsigned int>(env).value_or(0);
142+
if (val > 0) {
143+
count = std::min(count, val);
144+
}
145+
}
146+
147+
return count;
133148
}
134149

135150
} // namespace folly

third-party/folly/src/folly/system/HardwareConcurrency.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,14 @@
1818

1919
#include <utility>
2020

21+
#include <folly/lang/cstring_view.h>
22+
2123
namespace folly {
2224

25+
/// The environment variable name used to cap available_concurrency().
26+
inline constexpr cstring_view available_concurrency_max_env =
27+
"FOLLY_AVAILABLE_CONCURRENCY_MAX";
28+
2329
/// available_concurrency
2430
///
2531
/// Returns a number suitable for use as a size for thread-pools or as a size
@@ -50,6 +56,9 @@ namespace folly {
5056
/// * The result of std::thread::hardware_concurrency (all).
5157
/// * The result of get_nprocs, get_nprocs_conf, or sysconf as noted above.
5258
/// * The result of sched_getaffinity (linux but not android).
59+
/// * The FOLLY_AVAILABLE_CONCURRENCY_MAX environment variable, if set to a
60+
/// valid positive integer. The returned value is capped to the minimum of
61+
/// this and the OS-reported count.
5362
/// * Unspecified others....
5463
///
5564
/// mimic: std::thread::hardware_concurrency

third-party/folly/src/folly/system/test/HardwareConcurrencyTest.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,36 @@
1616

1717
#include <folly/system/HardwareConcurrency.h>
1818

19+
#include <cstdlib>
20+
1921
#include <folly/portability/GTest.h>
22+
#include <folly/system/EnvUtil.h>
2023

2124
TEST(HardwareConcurrency, ReturnsNonzero) {
2225
auto concurrency = folly::available_concurrency();
2326
EXPECT_GT(concurrency, 0u);
2427
}
28+
29+
TEST(HardwareConcurrency, EnvVarOverride) {
30+
folly::test::EnvVarSaver saver;
31+
::setenv(folly::available_concurrency_max_env.c_str(), "1", 1);
32+
EXPECT_EQ(folly::available_concurrency(), 1u);
33+
}
34+
35+
TEST(HardwareConcurrency, EnvVarInvalidIgnored) {
36+
folly::test::EnvVarSaver saver;
37+
::setenv(folly::available_concurrency_max_env.c_str(), "garbage", 1);
38+
EXPECT_GT(folly::available_concurrency(), 0u);
39+
}
40+
41+
TEST(HardwareConcurrency, EnvVarZeroIgnored) {
42+
folly::test::EnvVarSaver saver;
43+
::setenv(folly::available_concurrency_max_env.c_str(), "0", 1);
44+
EXPECT_GT(folly::available_concurrency(), 0u);
45+
}
46+
47+
TEST(HardwareConcurrency, EnvVarUnsetNormalBehavior) {
48+
folly::test::EnvVarSaver saver;
49+
::unsetenv(folly::available_concurrency_max_env.c_str());
50+
EXPECT_GT(folly::available_concurrency(), 0u);
51+
}

0 commit comments

Comments
 (0)