Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

A free and open-source forge that lives in your Git repo.

Measure every read route, not just the clone

1dfa8cbdeda03c48ba58c2a48ea8b7157f8f9468 · Keenan Nemetz · 9d ago · parent 0448a978

Measure every read route, not just the clone

#100 asks for numbers per route. The harness now seeds three repositories —
a small one for a quick clone, a large one for a slow clone, and the demo
repository with files at both ends of the configured max_blob_bytes, a
change with a 4000-line diff, a release artifact and a hosted site — and
runs one scenario per route: clone, clone-large, blob-small, blob-limit,
raw-small, raw-limit, raw-range, overview, tree, commits, compare,
change, issue, search-code, search-find, artifact, artifact-range, site.

The clone scenario gives each worker its own forwarded address, so the
global git_http_max_concurrent is what refuses rather than the per-client
limit; the fixture trusts the header on loopback.

`VOLE_LOAD_SCENARIO=all` runs the set in order and prints a block per
route, which is what produced the numbers recorded on #100. The doc
describes the seeded shape and the limit behaviour.

docs/load-testing.md +31−11

@@ -10,8 +10,17 @@ chosen from reasoning first; a run here is what replaces that with measurement.
10 10
11 11 ## One command
12 12
13 Every route:
14
13 15 ```sh
14 VOLE_LOAD_SCENARIO=clone VOLE_LOAD_CONCURRENCY=8 VOLE_LOAD_DURATION=30s \
16 VOLE_LOAD_SCENARIO=all VOLE_LOAD_CONCURRENCY=4 VOLE_LOAD_DURATION=5s \
17 go test -tags load,sqlite_fts5 -run '^TestLoad$' -v ./server
18 ```
19
20 One route, or clones past the limit:
21
22 ```sh
23 VOLE_LOAD_SCENARIO=clone VOLE_LOAD_CONCURRENCY=16 VOLE_LOAD_DURATION=30s \
15 24 go test -tags load,sqlite_fts5 -run '^TestLoad$' -v ./server
16 25 ```
17 26
@@ -23,23 +32,31 @@ The build needs `sqlite_fts5` beside `libsqlite3` (see
23 32
24 33 | Variable | Default | What it does |
25 34 |---|---|---|
26 | `VOLE_LOAD_SCENARIO` | `clone` | The scenario to run. Currently `clone`: anonymous shallow clones over HTTP. |
35 | `VOLE_LOAD_SCENARIO` | `clone` | `all`, or one of `clone`, `clone-large`, `blob-small`, `blob-limit`, `raw-small`, `raw-limit`, `raw-range`, `overview`, `tree`, `commits`, `compare`, `change`, `issue`, `search-code`, `search-find`, `artifact`, `artifact-range`, `site`. |
27 36 | `VOLE_LOAD_CONCURRENCY` | `4` | Workers driving the scenario in parallel. |
28 37 | `VOLE_LOAD_DURATION` | `10s` | How long the workers keep going. |
29 38
30 39 ## What it seeds
31 40
32 One repository with a shape worth measuring:
41 Three repositories and a site:
42
43 - `demo`: 300 commits; files at several sizes including one at the configured
44 `max_blob_bytes` (the harness sets 8 MiB, so the file is one a push could
45 deliver); an issue with five comments; a change request whose branch carries a
46 4000-line diff, with five review comments and an approval by a second account;
47 a release tag with one artifact in the LFS store; and a `pages` branch served
48 at `demo.pages.test`.
49 - `small`: 50 commits and small files, so a clone is quick.
50 - `large`: 3000 commits and one 16 MiB incompressible blob, so a clone is not.
33 51
34 - 300 commits, so history walks and the commit count cost something;
35 - files at several sizes: a small readme, a 1 KB text file, a 100 KB source
36 file, and a 1 MiB binary;
37 - an issue with five comments, and a change request with five review comments
38 and an approval by a second account;
39 - a release tag with one artifact in the LFS store.
52 `demo` and `large` are read once before the run so their indexes are built
53 outside the measurement.
40 54
41 The repository is read once before the run so its index is built outside the
42 measurement.
55 The clone scenario gives every worker a distinct `X-Forwarded-For` address (the
56 fixture trusts the header on loopback), so the global `git_http_max_concurrent`
57 is the limit that refuses rather than the per-client one. At the configured
58 `git_http_max_concurrent` the run stays at `200`; above it, refusals arrive as
59 `503` with `Retry-After`, and a clone caught by one reports the curl failure.
43 60
44 61 ## What it reports
45 62
@@ -57,6 +74,9 @@ and git child processes during the run.
57 74 compare changes, not a prediction of a real deployment.
58 75 - A warm cache is not simulated beyond the index build: the first run after a
59 76 restart will be slower.
77 - The `raw-range` scenario sends a `Range` header to a route that does not
78 implement it. It is there to measure that the server sends the whole file
79 anyway; the artifact route does answer `206`.
60 80
61 81 ## Adding a scenario
62 82