.gitbay/wiki/Performance.org

e6cd75b5f28bacf51620bb531320c30fd4e66bfd
gitbay/.gitbay/wiki/Performance.org rendered · source · history · blame · raw

68 lines · 3482 bytes

4 symbols in this file
 1#+title: Performance
 2
 3Results from a stress test of gitbay.org (2026-08-25): a server-side
 4import of the Git project's own repository — 82,056 commits, 1,016
 5refs, 167MB packed — followed by timed requests against every page
 6type. The instance is a single 1 vCPU / 1GB VPS that was concurrently
 7running the CI runner, the mirror worker, and the scheduler.
 8
 9* Summary
10
11The import took 41.5 seconds end to end. Every core page rendered in
12under a second against the full history; the heaviest operations —
13blame on a 7,000-line file and full-clone pack generation — cost what
14git itself costs, and nothing else. Load peaked at 0.42 and memory
15held near 190MB through the entire run. A full anonymous HTTPS clone
16of all 82,056 commits completed in 17 seconds and round-tripped with
17an identical commit count.
18
19* Numbers
20
21| operation                                      |  time |
22|------------------------------------------------+-------|
23| server-side import (=repo import=)             | 41.5s |
24| repo tree + README render                      | 0.56s |
25| log page (50 commits, signature checks)        | 0.68s |
26| per-file history (=?path=diff.c=)              | 0.61s |
27| directory history (=?path=Documentation=)      | 0.55s |
28| refs page (1,016 refs)                         | 0.61s |
29| blob of diff.c (7k lines, 3MB highlighted)     | 1.57s |
30| blame on diff.c across the full history        | 2.20s |
31| content grep                                   | 0.70s |
32| archive tar.gz (12MB)                          | 2.46s |
33| signed-tag commit page (unknown-key path)      | 0.29s |
34| shallow HTTPS clone                            |  3.8s |
35| full HTTPS clone (82,056 commits)              | 17.2s |
36
37* Why it holds
38
39gitbay keeps no object database of its own: transports stream through
40=git upload-pack=, object reads go through =git cat-file --batch=, and
41blame, grep, and archives are the git binary doing what it already does
42well. The forge's own work — auth, policy, rendering — is milliseconds
43around that. Metadata lives in one SQLite file in WAL mode, which at
44this scale never appears in a profile.
45
46The practical ceiling on this hardware is concurrent pack generation:
47full clones of large repositories are CPU-bound in git itself (the 17s
48clone ran git at ~156% CPU). =limits.pack_concurrency= bounds how many
49run at once across SSH, HTTP and git://, with a queue behind it (see
50[[Admin]], =[limits]=). Pushes are the other git-bound load: receive-pack
51indexes the pack it is sent, about a core for a large one, and then runs
52its hooks. =limits.push_concurrency= (2) bounds those on a separate
53budget, one per account or deploy key by default, so a clone storm and
54a push storm each leave the other its slots.
55
56* Concurrent clones
57
58The defaults (=pack_concurrency= 3, =pack_per_principal= 2,
59=pack_queue= 32, =pack_queue_wait= 60s) are set for a four-core host
60from the single-clone figure above; no concurrent-clone measurement
61backs them yet. =deploy/clonebench.sh <clone-url> <n>= starts n full
62clones at once from a machine other than the server. Anonymous clones
63together hold at most =pack_concurrency= − 1 slots, and clones from one
64address or account count against one principal, so an anonymous run
65measures those caps rather than the global one. Run it as signed-in
66clients (SSH keys, or HTTP with bearer tokens) from more than one
67account, or against an instance with =pack_per_principal = -1= and
68read the result as the anonymous class cap.