diff options
author | Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> | 2024-08-14 15:26:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-14 22:26:21 +0000 |
commit | e92a05b5518e5fd30559c96c5990b08657bbc3e4 (patch) | |
tree | 037cad394db9097d8f695810426a2de9ba03d825 /runtime/worker_bootstrap.rs | |
parent | 875ee618d318ea748e38641108d906eff34a9f86 (diff) |
feat(serve): Opt-in parallelism for `deno serve` (#24920)
Adds a `parallel` flag to `deno serve`. When present, we spawn multiple
workers to parallelize serving requests.
```bash
deno serve --parallel main.ts
```
Currently on linux we use `SO_REUSEPORT` and rely on the fact that the
kernel will distribute connections in a round-robin manner.
On mac and windows, we sort of emulate this by cloning the underlying
file descriptor and passing a handle to each worker. The connections
will not be guaranteed to be fairly distributed (and in practice almost
certainly won't be), but the distribution is still spread enough to
provide a significant performance increase.
---
(Run on an Macbook Pro with an M3 Max, serving `deno.com`
baseline::
```
❯ wrk -d 30s -c 125 --latency http://127.0.0.1:8000
Running 30s test @ http://127.0.0.1:8000
2 threads and 125 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 239.78ms 13.56ms 330.54ms 79.12%
Req/Sec 258.58 35.56 360.00 70.64%
Latency Distribution
50% 236.72ms
75% 248.46ms
90% 256.84ms
99% 268.23ms
15458 requests in 30.02s, 2.47GB read
Requests/sec: 514.89
Transfer/sec: 84.33MB
```
this PR (`with --parallel` flag)
```
❯ wrk -d 30s -c 125 --latency http://127.0.0.1:8000
Running 30s test @ http://127.0.0.1:8000
2 threads and 125 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 117.40ms 142.84ms 590.45ms 79.07%
Req/Sec 1.33k 175.19 1.77k 69.00%
Latency Distribution
50% 22.34ms
75% 223.67ms
90% 357.32ms
99% 460.50ms
79636 requests in 30.07s, 12.74GB read
Requests/sec: 2647.96
Transfer/sec: 433.71MB
```
Diffstat (limited to 'runtime/worker_bootstrap.rs')
-rw-r--r-- | runtime/worker_bootstrap.rs | 40 |
1 files changed, 37 insertions, 3 deletions
diff --git a/runtime/worker_bootstrap.rs b/runtime/worker_bootstrap.rs index b13c3c428..afd3242e8 100644 --- a/runtime/worker_bootstrap.rs +++ b/runtime/worker_bootstrap.rs @@ -10,7 +10,6 @@ use deno_terminal::colors; /// The execution mode for this worker. Some modes may have implicit behaviour. #[derive(Copy, Clone)] -#[repr(u8)] pub enum WorkerExecutionMode { /// No special behaviour. None, @@ -28,11 +27,39 @@ pub enum WorkerExecutionMode { /// `deno bench` Bench, /// `deno serve` - Serve, + Serve { + is_main: bool, + worker_count: Option<usize>, + }, /// `deno jupyter` Jupyter, } +impl WorkerExecutionMode { + pub fn discriminant(&self) -> u8 { + match self { + WorkerExecutionMode::None => 0, + WorkerExecutionMode::Worker => 1, + WorkerExecutionMode::Run => 2, + WorkerExecutionMode::Repl => 3, + WorkerExecutionMode::Eval => 4, + WorkerExecutionMode::Test => 5, + WorkerExecutionMode::Bench => 6, + WorkerExecutionMode::Serve { .. } => 7, + WorkerExecutionMode::Jupyter => 8, + } + } + pub fn serve_info(&self) -> (Option<bool>, Option<usize>) { + match *self { + WorkerExecutionMode::Serve { + is_main, + worker_count, + } => (Some(is_main), worker_count), + _ => (None, None), + } + } +} + /// The log level to use when printing diagnostic log messages, warnings, /// or errors in the worker. /// @@ -175,6 +202,10 @@ struct BootstrapV8<'a>( u16, // serve host Option<&'a str>, + // serve is main + Option<bool>, + // serve worker count + Option<usize>, ); impl BootstrapOptions { @@ -186,6 +217,7 @@ impl BootstrapOptions { let scope = RefCell::new(scope); let ser = deno_core::serde_v8::Serializer::new(&scope); + let (serve_is_main, serve_worker_count) = self.mode.serve_info(); let bootstrap = BootstrapV8( self.location.as_ref().map(|l| l.as_str()), self.unstable, @@ -198,9 +230,11 @@ impl BootstrapOptions { self.disable_deprecated_api_warning, self.verbose_deprecated_api_warning, self.future, - self.mode as u8 as _, + self.mode.discriminant() as _, self.serve_port.unwrap_or_default(), self.serve_host.as_deref(), + serve_is_main, + serve_worker_count, ); bootstrap.serialize(ser).unwrap() |