Commit Graph

2810 Commits

Author SHA1 Message Date
Matthias Einwag fc950da8aa Avoid allocations for CIDs
When reading CIDs from packets the current code makes some short-lived
allocations due to the use of `copy_to_bytes`, which allocate for 1.5% of
CPU samples. This change avoids this.

**Before:**
```
Sent 1073741824 bytes on 1 streams in 1.72s (594.74 MiB/s)
```

**After:**
```
Sent 1073741824 bytes on 1 streams in 1.70s (602.78 MiB/s)
```
2021-05-14 08:31:01 +02:00
Matthias Einwag ce66efc045 Use an ArrayRangeSet to store new ACKs
This seems slightly more efficient than extending a `Vec`.
Would probably be even more efficient if there would be an intersection
method on `SentMap` insert of returning packet numbers one by one.

Peak perf before:
```
Sent 1073741824 bytes on 1 streams in 1.77s (577.02 MiB/s)
```

After:
```
Sent 1073741824 bytes on 1 streams in 1.75s (584.25 MiB/s)
```
2021-05-08 16:27:12 -07:00
Matthias Einwag a2af4c03b5 Rust 1.52 lint fix
Fix the new clippy finding
2021-05-08 20:26:23 +02:00
Matthias Einwag eb89e468ef Ack frame Debug implementation
This adds a manual `Debug` implementation for Ack frames, to make them understandable
in logs.

Old:
```
got frame Ack(Ack { largest: 11, delay: 0, additional: b"\x02", ecn: None })
```

New:
```
got frame Ack(Ack { largest: 9, delay: 0, ecn: None, ranges: "[8..=9]" }
```
2021-05-07 14:42:54 -07:00
Matthias Einwag c70763d040 Maximize CRYPTO data
This change increases the amount of `CRYPTO` data sent in packets during handshakes.

Instead of reserving a fixed amount of 17 bytes for frame overhead,
we reserve the exactly required amount of bytes to encode frame type
and offset, and only 2 bytes for the frame length. This leads to an
additional 12-13 bytes of payload data being used.
2021-05-04 21:49:34 +02:00
David Craven 6671d14032 Allow overriding supported versions in EndpointConfig (#1106) 2021-05-03 10:04:59 +02:00
Matthias Einwag 7d2e07f86f Reserve the maximum transmit buffer capacity upfront
The current implementation continously resizes the datagram buffer if
GSO is enabled and further datagrams are appended. Some benchmarking
and profiling showed that this doesn't have too much of an impact with
the glibc allocator, the strategy proved rather inefficient with pooling
memory allocators like jemalloc and mimalloc. For those, the cost of
calling `realloc` is rather high.

I benchmarked a bunch of strategies to determine the most efficient way forward:
1. Continously resize output buffer (Current approach)
2. Reserve maximum buffer size upfront
3. Reserve space for a single datagram to minimize over-allocation for
  tiny transmits. If this is not enough, reallocate once for maximum size

Based on the results of those, I am proposing to go for approach 2) and
simply allocate the maximum buffer size upfront, which yields maximum
efficiency for mimalloc + jemalloc.

## Benchmark results

### Glibc:

Baseline:

> Sent 1073741824 bytes on 1 streams in 1.79s (572.62 MiB/s)

Allocate for 1 MTU, then for `max_datagrams`:

> Sent 1073741824 bytes on 1 streams in 1.78s (576.31 MiB/s)

Allocate for `max_datagrams` upfront:

> Sent 1073741824 bytes on 1 streams in 1.79s (572.28 MiB/s)

### Mimalloc:

Baseline:

> Sent 1073741824 bytes on 1 streams in 1.84s (557.34 MiB/s)

Allocate for 1 MTU, then for `max_datagrams`:

> Sent 1073741824 bytes on 1 streams in 1.74s (587.76 MiB/s)

Allocate for `max_datagrams` upfront:

> Sent 1073741824 bytes on 1 streams in 1.71s (600.06 MiB/s)

### Jemalloc:

Baseline:

> Sent 1073741824 bytes on 1 streams in 1.86s (551.75 MiB/s)

Allocate for 1 MTU, then for `max_datagrams`:

> Sent 1073741824 bytes on 1 streams in 1.73s (592.50 MiB/s)

Allocate for `max_datagrams` upfront:

> Sent 1073741824 bytes on 1 streams in 1.72s (596.29 MiB/s)
2021-05-03 07:22:47 +02:00
David Craven f4903f5142 Allow upgrading keys before sending CRYPTO frames 2021-04-23 11:25:33 -07:00
Matthias Einwag d6d32b2ad0 Use an array-based RangeSet for tracking outgoing ACKs
This change introduces a second `RangeSet` type which is based on a
linear array/vector instead of a tree. For the purpose of tracking
ACK ranges we usually should not have a big number of disjoint ranges,
since those would only occur with severe fragmentation. Therefore the
main benefit of a tree which is able to find ranges in the middle is
rarely used.

The array-based RangeSet provides 2 benefits:
- There exists an inline representation, which avoids the need of heap
  allocating ACK ranges for `SentFrames` for small ranges.
- Iterating over ranges should usually be faster since there is only
  a single cache-friendly contiguous range.

Performance differences:

With the `BTreeMap` based `RangeSet`:
```
Sent 1073741824 bytes on 1 streams in 1.90s (538.89 MiB/s)
```

With the `TinyVec` based `RangeSet`:
```
Sent 1073741824 bytes on 1 streams in 1.78s (574.73 MiB/s)
```
2021-04-06 10:34:21 +02:00
Matthias Einwag e6f28e9d29 Fix insert and remove behavior for empty ranges
`RangeSet::insert` and `RangeSet::remove` returned `true` when
trying to insert an empty range.
2021-04-06 10:34:21 +02:00
Matthias Einwag 01b95116e9 Update the minimal required version to 1.47
This updates the minimum required Rust version to 1.47, which is
required for the `Default` implementation on `Range`.
2021-04-06 10:34:21 +02:00
Benjamin Saunders 1f59c3d0cf Report stream events after connection events
Allows applications which do not use 0-RTT to rely on `Connected`
being delivered before any application data.
2021-04-04 22:13:51 +02:00
Benjamin Saunders e3a1f0d456 Store connection errors separately from non-error events 2021-04-04 22:13:51 +02:00
Lachezar Lechev c25475039f fix Next up link of Connection Setup chapter 2021-04-03 17:07:51 +02:00
Dirkjan Ochtman e07835b954 crypto: return Option from next_1rtt_keys()
A crypto session cannot return 1-RTT keys before handshaking is finished.
Currently, rustls contains unwrap() calls to deal with this, but hoisting
out the unwrap to the `Connection` level here seems more sensible.

We can adjust the call into rustls once we update rustls for other reasons.
2021-04-02 23:46:35 +02:00
Matthias Einwag cb6598b694 Make echo tests parameterizable and add new stress tests
This change adds additional config arguments to the echo test.
We are then using those arguments to run a higher number of
streams while utilizing low flow control windows to test flow
control updates.
2021-04-01 11:08:59 +02:00
Matthias Einwag 45e802c2f4 Don't enable trace logging in the test by default
This makes the test really slow. For debugging purposes it can
still be enabled via CLI.
2021-04-01 11:08:59 +02:00
Matthias Einwag da81d081f2 Improve test behavior for multiple and longer streams
Stream all the data in the echo handler, and run send and receive
concurrently in the sender.

Also spawn a separate task per stream.
2021-04-01 11:08:59 +02:00
Matthias Einwag 860273f559 Allow to send test data of an arbitrary size
This allows to generate a certain amount of test data in reproducible
fashion and echo it back.
2021-04-01 11:08:59 +02:00
Benjamin Saunders 5bd1ba570b Simplify state juggling 2021-03-31 09:00:26 +02:00
Benjamin Saunders 6616bc958a Don't unconditionally predict transmits on reset
The exact logic should handle this case just fine.
2021-03-31 09:00:26 +02:00
Benjamin Saunders 7ba3e3d3d3 Fix transmit prediction false negative regarding stream ID credit 2021-03-31 09:00:26 +02:00
Benjamin Saunders e4c3d9f89f Inline Retransmits::post_read 2021-03-31 09:00:26 +02:00
Benjamin Saunders 9d0d10ca6f Centralize post_read calls 2021-03-31 09:00:26 +02:00
Benjamin Saunders 08996a3676 Simplify state inspection 2021-03-31 09:00:26 +02:00
Benjamin Saunders 4b2909ac1a Decouple state from connection-level flow control issuing 2021-03-31 09:00:26 +02:00
Benjamin Saunders 3d3a0aa849 Deduplicate asserts 2021-03-31 09:00:26 +02:00
Benjamin Saunders ed6ddd46bd Inline Chunks::done 2021-03-31 09:00:26 +02:00
Benjamin Saunders 63b0586a2d Fold Blocked state into Readable
Because the only remaining possible error is Reset, we rename and
specialize the error state for clarity.
2021-03-31 09:00:26 +02:00
Benjamin Saunders 8538ff31c1 Improve test log readability 2021-03-31 09:00:26 +02:00
Benjamin Saunders e703d9d643 Fix missing flow control credit when reading a stream's tail 2021-03-31 09:00:26 +02:00
Benjamin Saunders 2cb44d06e4 Remove dead state
This field was always `true`.
2021-03-31 09:00:26 +02:00
daxpedda ed164fc458 Doc typo 2021-03-30 13:15:26 +02:00
daxpedda b3e7661911 Fix overflow in crypto_buffer_size 2021-03-29 19:59:09 +02:00
Matthias Einwag f8aac71171 Log max_data when write blocked
This can help to determine whether max_data limits are in sync
2021-03-27 08:40:33 +01:00
Matthias Einwag 20e9fbf545 Remove authenticated log
This pollutes the log a lot and doesn't help debugging.
All cases where a packet is not authenticated should already be
logged in different places, so just remove this.
2021-03-27 08:40:33 +01:00
Matthias Einwag 3162df74b7 Log all received frames
Before this change only stream frames had been logged.
Logging all frames helps debugging.
2021-03-27 08:40:33 +01:00
Benjamin Saunders 90f6168919 Update path validation timeout 2021-03-26 21:20:56 +01:00
Benjamin Saunders 1a3b613bde Define NO_VIABLE_PATH error
We don't need to generate this, but we might as well provide good
diagnostics if the peer generates it.
2021-03-26 21:20:56 +01:00
Benjamin Saunders 7c47c6e47c Don't issue MAX_STREAMS on locally-initiated stream completion 2021-03-26 20:13:33 +01:00
Benjamin Saunders e0f344fd99 Simplify 2021-03-26 20:13:33 +01:00
Benjamin Saunders cd7963221d Remove unnecessary reborrow 2021-03-26 20:13:33 +01:00
Benjamin Saunders 1082c13167 Idiomatic capitalization of CipherSuite variants 2021-03-26 20:13:33 +01:00
Benjamin Saunders 5315e6d4c7 Idiomatic capitalization of PseudoType variants 2021-03-26 20:13:33 +01:00
Benjamin Saunders fe5673bf20 Idiomatic capitalization of EcnCodepoint variants 2021-03-26 20:13:33 +01:00
Benjamin Saunders 5e68a8681e Replace Into impl with From 2021-03-26 20:13:33 +01:00
Benjamin Saunders 754106c2f8 Replace slicing with Deref 2021-03-26 20:13:33 +01:00
Benjamin Saunders a5667774f8 Import assert_matches explicitly
Fixes test build on rust beta.
2021-03-26 20:13:33 +01:00
Benjamin Saunders e801527c9b Lazily initialize Endpoint::default_client_config
Pure servers never need this. once_cell is already a transitive dep,
and is expected to eventually land in std, so it's free to add.
2021-03-21 14:51:19 -07:00
Benjamin Saunders 14813d33c2 Remove unintentional, obfuscatory use of Result::into_iter 2021-03-21 22:27:17 +01:00