Skip to content

Commit 605fce9

Browse files
authored
cache: Make the cache cloneable with RwLock (#743)
Caches are typically wrapped with buffers so that they can be shared across connections. These buffers can be eliminated if the cache itself becomes cloneable; and this is easily achieved with a `std::sync::RwLock`: the cache first obtains a read lock to clone the inner service and a write lock is only obtained when the service is not in the cache. It turns out that the buffers have an important side effect, though: the buffers hide the inner service type, which drastically reduces the amount of memory needed to compile the linkerd2-proxy crate. To replicate this, this change introduces a `stack::BoxNewService` which can be used to hide the type signature of a `NewService`. Benchmarks indicate that this improves p50 latency by 2ms for HTTP/2 traffic at 100 concurrent requests.
1 parent 90ba66e commit 605fce9

File tree

10 files changed

+224
-63
lines changed

10 files changed

+224
-63
lines changed

Cargo.lock

Lines changed: 92 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
105105
checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130"
106106
dependencies = [
107107
"addr2line",
108-
"cfg-if",
108+
"cfg-if 0.1.10",
109109
"libc",
110110
"object",
111111
"rustc-demangle",
@@ -128,9 +128,9 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
128128

129129
[[package]]
130130
name = "bitflags"
131-
version = "1.0.1"
131+
version = "1.2.1"
132132
source = "registry+https://github.com/rust-lang/crates.io-index"
133-
checksum = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
133+
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
134134

135135
[[package]]
136136
name = "build_const"
@@ -187,6 +187,12 @@ version = "0.1.10"
187187
source = "registry+https://github.com/rust-lang/crates.io-index"
188188
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
189189

190+
[[package]]
191+
name = "cfg-if"
192+
version = "1.0.0"
193+
source = "registry+https://github.com/rust-lang/crates.io-index"
194+
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
195+
190196
[[package]]
191197
name = "chrono"
192198
version = "0.4.10"
@@ -207,6 +213,15 @@ dependencies = [
207213
"bitflags",
208214
]
209215

216+
[[package]]
217+
name = "cloudabi"
218+
version = "0.1.0"
219+
source = "registry+https://github.com/rust-lang/crates.io-index"
220+
checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
221+
dependencies = [
222+
"bitflags",
223+
]
224+
210225
[[package]]
211226
name = "cmake"
212227
version = "0.1.41"
@@ -232,7 +247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
232247
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
233248
dependencies = [
234249
"autocfg 1.0.0",
235-
"cfg-if",
250+
"cfg-if 0.1.10",
236251
"lazy_static",
237252
]
238253

@@ -247,6 +262,12 @@ dependencies = [
247262
"gzip-header",
248263
]
249264

265+
[[package]]
266+
name = "dyn-clone"
267+
version = "1.0.3"
268+
source = "registry+https://github.com/rust-lang/crates.io-index"
269+
checksum = "d55796afa1b20c2945ca8eabfc421839f2b766619209f1ede813cf2484f31804"
270+
250271
[[package]]
251272
name = "either"
252273
version = "1.5.1"
@@ -439,7 +460,7 @@ version = "0.1.13"
439460
source = "registry+https://github.com/rust-lang/crates.io-index"
440461
checksum = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
441462
dependencies = [
442-
"cfg-if",
463+
"cfg-if 0.1.10",
443464
"libc",
444465
"wasi",
445466
]
@@ -633,6 +654,15 @@ version = "1.0.2"
633654
source = "registry+https://github.com/rust-lang/crates.io-index"
634655
checksum = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
635656

657+
[[package]]
658+
name = "instant"
659+
version = "0.1.8"
660+
source = "registry+https://github.com/rust-lang/crates.io-index"
661+
checksum = "cb1fc4429a33e1f80d41dc9fea4d108a88bec1de8053878898ae448a0b52f613"
662+
dependencies = [
663+
"cfg-if 1.0.0",
664+
]
665+
636666
[[package]]
637667
name = "iovec"
638668
version = "0.1.4"
@@ -949,6 +979,7 @@ dependencies = [
949979
"futures 0.3.5",
950980
"linkerd2-error",
951981
"linkerd2-stack",
982+
"parking_lot 0.11.0",
952983
"tokio",
953984
"tower",
954985
"tracing",
@@ -1433,6 +1464,7 @@ dependencies = [
14331464
name = "linkerd2-stack"
14341465
version = "0.1.0"
14351466
dependencies = [
1467+
"dyn-clone",
14361468
"futures 0.3.5",
14371469
"linkerd2-error",
14381470
"pin-project",
@@ -1525,13 +1557,22 @@ dependencies = [
15251557
"scopeguard",
15261558
]
15271559

1560+
[[package]]
1561+
name = "lock_api"
1562+
version = "0.4.1"
1563+
source = "registry+https://github.com/rust-lang/crates.io-index"
1564+
checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
1565+
dependencies = [
1566+
"scopeguard",
1567+
]
1568+
15281569
[[package]]
15291570
name = "log"
15301571
version = "0.4.6"
15311572
source = "registry+https://github.com/rust-lang/crates.io-index"
15321573
checksum = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
15331574
dependencies = [
1534-
"cfg-if",
1575+
"cfg-if 0.1.10",
15351576
]
15361577

15371578
[[package]]
@@ -1540,7 +1581,7 @@ version = "0.3.6"
15401581
source = "registry+https://github.com/rust-lang/crates.io-index"
15411582
checksum = "a0e8460f2f2121162705187214720353c517b97bdfb3494c0b1e33d83ebe4bed"
15421583
dependencies = [
1543-
"cfg-if",
1584+
"cfg-if 0.1.10",
15441585
"generator",
15451586
"scoped-tls",
15461587
"serde",
@@ -1629,7 +1670,7 @@ version = "0.6.21"
16291670
source = "registry+https://github.com/rust-lang/crates.io-index"
16301671
checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f"
16311672
dependencies = [
1632-
"cfg-if",
1673+
"cfg-if 0.1.10",
16331674
"fuchsia-zircon",
16341675
"fuchsia-zircon-sys",
16351676
"iovec",
@@ -1699,7 +1740,7 @@ version = "0.2.32"
16991740
source = "registry+https://github.com/rust-lang/crates.io-index"
17001741
checksum = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0"
17011742
dependencies = [
1702-
"cfg-if",
1743+
"cfg-if 0.1.10",
17031744
"libc",
17041745
"winapi 0.3.8",
17051746
]
@@ -1773,8 +1814,19 @@ version = "0.10.2"
17731814
source = "registry+https://github.com/rust-lang/crates.io-index"
17741815
checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
17751816
dependencies = [
1776-
"lock_api",
1777-
"parking_lot_core",
1817+
"lock_api 0.3.4",
1818+
"parking_lot_core 0.7.2",
1819+
]
1820+
1821+
[[package]]
1822+
name = "parking_lot"
1823+
version = "0.11.0"
1824+
source = "registry+https://github.com/rust-lang/crates.io-index"
1825+
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
1826+
dependencies = [
1827+
"instant",
1828+
"lock_api 0.4.1",
1829+
"parking_lot_core 0.8.0",
17781830
]
17791831

17801832
[[package]]
@@ -1783,8 +1835,23 @@ version = "0.7.2"
17831835
source = "registry+https://github.com/rust-lang/crates.io-index"
17841836
checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3"
17851837
dependencies = [
1786-
"cfg-if",
1787-
"cloudabi",
1838+
"cfg-if 0.1.10",
1839+
"cloudabi 0.0.3",
1840+
"libc",
1841+
"redox_syscall",
1842+
"smallvec",
1843+
"winapi 0.3.8",
1844+
]
1845+
1846+
[[package]]
1847+
name = "parking_lot_core"
1848+
version = "0.8.0"
1849+
source = "registry+https://github.com/rust-lang/crates.io-index"
1850+
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
1851+
dependencies = [
1852+
"cfg-if 0.1.10",
1853+
"cloudabi 0.1.0",
1854+
"instant",
17881855
"libc",
17891856
"redox_syscall",
17901857
"smallvec",
@@ -2075,7 +2142,7 @@ version = "0.1.3"
20752142
source = "registry+https://github.com/rust-lang/crates.io-index"
20762143
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
20772144
dependencies = [
2078-
"cloudabi",
2145+
"cloudabi 0.0.3",
20792146
"fuchsia-cprng",
20802147
"libc",
20812148
"rand_core 0.4.0",
@@ -2250,9 +2317,9 @@ checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
22502317

22512318
[[package]]
22522319
name = "scopeguard"
2253-
version = "1.0.0"
2320+
version = "1.1.0"
22542321
source = "registry+https://github.com/rust-lang/crates.io-index"
2255-
checksum = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
2322+
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
22562323

22572324
[[package]]
22582325
name = "sct"
@@ -2338,17 +2405,17 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
23382405

23392406
[[package]]
23402407
name = "smallvec"
2341-
version = "1.2.0"
2408+
version = "1.5.0"
23422409
source = "registry+https://github.com/rust-lang/crates.io-index"
2343-
checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc"
2410+
checksum = "7acad6f34eb9e8a259d3283d1e8c1d34d7415943d4895f65cc73813c7396fc85"
23442411

23452412
[[package]]
23462413
name = "socket2"
23472414
version = "0.3.12"
23482415
source = "registry+https://github.com/rust-lang/crates.io-index"
23492416
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
23502417
dependencies = [
2351-
"cfg-if",
2418+
"cfg-if 0.1.10",
23522419
"libc",
23532420
"redox_syscall",
23542421
"winapi 0.3.8",
@@ -2386,7 +2453,7 @@ version = "3.0.5"
23862453
source = "registry+https://github.com/rust-lang/crates.io-index"
23872454
checksum = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2"
23882455
dependencies = [
2389-
"cfg-if",
2456+
"cfg-if 0.1.10",
23902457
"libc",
23912458
"rand 0.6.5",
23922459
"redox_syscall",
@@ -2470,7 +2537,7 @@ dependencies = [
24702537
"mio-named-pipes",
24712538
"mio-uds",
24722539
"num_cpus",
2473-
"parking_lot",
2540+
"parking_lot 0.10.2",
24742541
"pin-project-lite",
24752542
"signal-hook-registry",
24762543
"slab",
@@ -2691,7 +2758,7 @@ version = "0.1.19"
26912758
source = "registry+https://github.com/rust-lang/crates.io-index"
26922759
checksum = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c"
26932760
dependencies = [
2694-
"cfg-if",
2761+
"cfg-if 0.1.10",
26952762
"log",
26962763
"tracing-attributes",
26972764
"tracing-core",
@@ -2758,7 +2825,7 @@ dependencies = [
27582825
"chrono",
27592826
"lazy_static",
27602827
"matchers",
2761-
"parking_lot",
2828+
"parking_lot 0.11.0",
27622829
"regex 1.3.9",
27632830
"serde",
27642831
"serde_json",
@@ -2798,7 +2865,7 @@ version = "0.20.0"
27982865
source = "git+https://github.com/bluejekyll/trust-dns.git?rev=97d3bf10ecb0711aebf523e930f5de873808eb33#97d3bf10ecb0711aebf523e930f5de873808eb33"
27992866
dependencies = [
28002867
"backtrace",
2801-
"cfg-if",
2868+
"cfg-if 0.1.10",
28022869
"futures-util",
28032870
"ipconfig",
28042871
"lazy_static",
@@ -2901,7 +2968,7 @@ version = "0.2.68"
29012968
source = "registry+https://github.com/rust-lang/crates.io-index"
29022969
checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42"
29032970
dependencies = [
2904-
"cfg-if",
2971+
"cfg-if 0.1.10",
29052972
"wasm-bindgen-macro",
29062973
]
29072974

linkerd/app/core/src/svc.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,14 @@ impl<S> Stack<S> {
284284
self.push(http::boxed::response::Layer::new())
285285
}
286286

287+
pub fn box_new_service<T>(self) -> Stack<stack::BoxNewService<T, S::Service>>
288+
where
289+
S: NewService<T> + Clone + Send + Sync + 'static,
290+
S::Service: Send + 'static,
291+
{
292+
self.push(layer::mk(stack::BoxNewService::new))
293+
}
294+
287295
/// Validates that this stack serves T-typed targets.
288296
pub fn check_new<T>(self) -> Self
289297
where

linkerd/app/inbound/src/lib.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,8 @@ impl Config {
7373
Future = impl Send + 'static,
7474
> + Send
7575
+ 'static,
76-
> + Send
76+
> + Clone
77+
+ Send
7778
+ 'static
7879
where
7980
L: svc::NewService<Target, Service = S> + Unpin + Clone + Send + Sync + 'static,
@@ -85,7 +86,7 @@ impl Config {
8586
+ 'static,
8687
S::Error: Into<Error>,
8788
S::Future: Unpin + Send,
88-
P: profiles::GetProfile<NameAddr> + Unpin + Clone + Send + 'static,
89+
P: profiles::GetProfile<NameAddr> + Unpin + Clone + Send + Sync + 'static,
8990
P::Future: Unpin + Send,
9091
P::Error: Send,
9192
{
@@ -173,11 +174,11 @@ impl Config {
173174
C::Error: Into<Error>,
174175
C::Response: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static,
175176
C::Future: Unpin + Send,
176-
P: profiles::GetProfile<NameAddr> + Unpin + Clone + Send + 'static,
177+
P: profiles::GetProfile<NameAddr> + Unpin + Clone + Send + Sync + 'static,
177178
P::Future: Unpin + Send,
178179
P::Error: Send,
179180
// The loopback router processes requests sent to the inbound port.
180-
L: svc::NewService<Target, Service = S> + Unpin + Send + Clone + 'static,
181+
L: svc::NewService<Target, Service = S> + Unpin + Send + Clone + Sync + 'static,
181182
S: tower::Service<
182183
http::Request<http::boxed::Payload>,
183184
Response = http::Response<http::boxed::Payload>,
@@ -282,9 +283,9 @@ impl Config {
282283
.box_http_response(),
283284
),
284285
)
285-
.into_make_service()
286-
.spawn_buffer(buffer_capacity)
287-
.into_new_service()
286+
// Boxing is necessary purely to limit the link-time overhead of
287+
// having enormous types.
288+
.box_new_service()
288289
.check_new_service::<Target, http::Request<http::boxed::Payload>>()
289290
.into_inner()
290291
}
@@ -406,7 +407,8 @@ impl Config {
406407
Future = impl Send + 'static,
407408
> + Send
408409
+ 'static,
409-
> + Send
410+
> + Clone
411+
+ Send
410412
+ 'static
411413
where
412414
D: svc::NewService<TcpAccept, Service = A> + Unpin + Clone + Send + Sync + 'static,

0 commit comments

Comments
 (0)