~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

knotless.dev
1 collaborator

knotless 0.13.0 Latest 2 packages, 1 image

1
10

The bench reaches the PDS over https, and counts connecting

Merged chadtmiller.com asked to merge into main from chadtmiller.com/knotless:bench/as-the-network
crates/knotless/examples/bench.rs+277−170
447 lines changed: not loaded until asked for.
crates/knotless/tests/common/mod.rs+13−4
@@ -216,10 +216,11 @@ pub fn browser(account: &Account, extra: &str) -> String {
)
}
/// An https front for a server on `port`, at the harness's gateway
/// hostname, until it is dropped.
/// An https front for a server, at the port and URL it has until it is
/// dropped.
pub struct TlsProxy {
pub url: String,
pub port: u16,
child: Child,
}
@@ -232,9 +233,15 @@ impl Drop for TlsProxy {
pub fn tls_proxy(port: u16) -> TlsProxy {
let tls = &net().gateway;
tls_front(&tls.cert, &tls.key, &tls.host, port)
}
/// An https front for a server on `port`, at `host`, with the certificate
/// and key in the files named, until it is dropped.
pub fn tls_front(cert: &str, key: &str, host: &str, port: u16) -> TlsProxy {
let mut child = Command::new("node")
.arg(root().join("harness/tls-proxy.mjs"))
.args([&tls.cert, &tls.key, &port.to_string()])
.args([cert, key, &port.to_string()])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()
@@ -243,8 +250,10 @@ pub fn tls_proxy(port: u16) -> TlsProxy {
BufReader::new(child.stdout.take().unwrap())
.read_line(&mut line)
.unwrap();
let port = line.trim().parse().expect("the front prints its port");
TlsProxy {
url: format!("https://{}:{}", tls.host, line.trim()),
url: format!("https://{host}:{port}"),
port,
child,
}
}
docs/reference/performance.md+64−12
@@ -11,39 +11,91 @@ to the PDS, so every operation is planned around them.
| `git fetch` | 1 when the new packs are among the newest 4 and under 192 KiB, as they arrive beside the refs (three reads in parallel); a client further behind adds one for the packs its refs name; larger packs add parallel blob reads |
| `knotless repo commit`, no checkout | 2, plus 3 per lost race |
| A ref's compare-and-swap | 0 extra: its claim record goes in the same `applyWrites` |
| `git push` to a branch, with an appview | 2 more, to the appview, one after the other: who may push, and the pulls the push may have landed |
| Connecting | 2 for each server a command reaches over https: TCP's handshake, then TLS's |
"Warm" means after the first call: the identity, session and repository key
are cached on disk, and every request in a process shares one connection.
Each command is a process of its own, so each connects again.
[Storage](../design/storage.md) explains each count.
## Benchmarks
Measured with `cargo run --release --example bench -- --rtt 50` (`just
bench 50`): the npm reference PDS (`@atproto/pds` 0.5.43, SQLite) on the
same machine, behind a proxy adding 50 ms of round-trip time, on an
Apple-silicon laptop.
same machine, an Apple-silicon laptop, reached as a PDS on the network is:
over https, through a proxy adding 50 ms to every round trip, those a
command spends connecting among them. Four rounds of 15 samples, each
round on a repository of its own, with 5 clones a round.
| | p50 | p95 |
| --- | --- | --- |
| `git push`, one small commit | 205 ms | 228 ms |
| `git fetch`, one new commit | 170 ms | 272 ms |
| `knotless repo commit`, no checkout | 423 ms | 610 ms |
| `git clone`, 31 packs | 310 ms | 378 ms |
| `git clone`, compacted | 191 ms | 344 ms |
| `git clone --depth 1` via `knotless-serve` | 208 ms | 299 ms |
| One file via the `knotless-serve` API, warm | 45 ms | 57 ms |
| 16 agents pushing 16 branches at once | 591 ms total | |
| 16 agents committing to one branch at once | 11.9 s total, 96 pushes | |
| `git push`, one small commit | 296 ms | 320 ms |
| `git fetch`, one new commit | 259 ms | 309 ms |
| `git push` to a branch, with an appview | 507 ms | 516 ms |
| `knotless repo commit`, no checkout | 435 ms | 469 ms |
| `git clone`, 31 packs | 379 ms | 412 ms |
| `git clone`, compacted | 263 ms | 299 ms |
| `git clone --depth 1` via `knotless-serve` | 115 ms | 123 ms |
| One file via the `knotless-serve` API, warm | 30 ms | 32 ms |
| 16 agents pushing 16 branches at once | 561 ms total | |
| 16 agents committing to one branch at once | 8.9 s total, 91 pushes | |
Every row but the third runs with no appview. A client set up as the
installer leaves it has one, and a push of a branch asks it two things
before git hears the push landed: on a connection of its own, four round
trips more. The appview here is as far away as the PDS.
Three things are kinder than a PDS on the network. Compaction is off. The
harness's PDS does not wait for its writes to reach the disk. And the two
rows read through `knotless-serve` reach it with no latency added, since
its mirror is beside the reader.
## Many branches at once
Agents each pushing a new branch of its own at the same moment, in the same
bench at 50 ms:
| Agents | All pushed in | Pushes a second |
| --- | --- | --- |
| 1 | 318 ms | 3.1 |
| 4 | 354 ms | 11.3 |
| 16 | 561 ms | 28.5 |
| 64 | 1.31 s | 48.9 |
No branch waits for another on the network: sixty-four pushes wait for the
round trips of one. What grows is this machine's work, sixty-four `git`s
and a PDS that writes one account's records in turn: with no latency added
at all, the sixty-four take 1.5 s.
## Many writers on one branch
A branch is one compare-and-swap, so of the writers pushing straight to one
branch, one lands per round. The reference PDS also serializes an account's
writes. That is why the last row above is slow. Give each agent its own
writes. That is why the sixteen committing to one branch take seconds,
where sixteen pushing a branch each take half of one. Give each agent its own
branch and merge, or send commits through a
[gateway](../design/gateway.md#commit), which queues them per branch and
lands each queue as one push.
## Other round-trip times
The same bench at 0, 100 and 200 ms separates what an operation costs on
this machine from what it waits for on the network. Each time is close to
the first column plus the round-trip time for each round trip, which is the
slope measured from 0 to 200 ms. `--plain` reaches the PDS over plain http
and charges nothing for connecting, which leaves the requests: the last
column, measured the same way.
| | 0 ms | 50 ms | 100 ms | 200 ms | Round trips | Of them requests |
| --- | --- | --- | --- | --- | --- | --- |
| `git push`, one small commit | 92 ms | 296 ms | 496 ms | 898 ms | 4.0 | 2.0 |
| `git fetch`, one new commit | 105 ms | 259 ms | 406 ms | 710 ms | 3.0 | 1.0 |
| `git push` to a branch, with an appview | 108 ms | 507 ms | 911 ms | 1.71 s | 8.0 | 4.0 |
| `knotless repo commit`, no checkout | 242 ms | 435 ms | 640 ms | 1.05 s | 4.1 | 2.0 |
| `git clone`, 31 packs | 237 ms | 379 ms | 533 ms | 842 ms | 3.0 | 1.0 |
| `git clone`, compacted | 114 ms | 263 ms | 414 ms | 716 ms | 3.0 | 1.0 |
## Large repositories
Measured by pushing three real repositories into the npm reference PDS