Leistung und Platzbedarf
Alle Zahlen auf dieser Seite stammen von serde 1.0.229: 339 Dateien, 4.573 Knoten, 9.427 Kanten, 2.443 eingebettete Definitionen. Die Messungen liefen mit greppy 0.4.1 auf einem Apple M5 (10 Kerne, 32 GB RAM, macOS 26.2). Zeiten sind Wandzeit inklusive Prozessstart; greppy --version allein braucht 33 ms.
$ sysctl -n machdep.cpu.brand_string
Apple M5
$ greppy doctor
status: ok
…
inference: preference=auto explicit=false selected=metal device=metal:0000000100000471
…
device metal:0000000100000471 Apple M5 memory_free=26800144384 memory_total=26800603136
…
stats: files=339 nodes=4573 edges=9427
…
Index und Embeddings
| Lauf (serde, Apple M5, Metal) | Zeit |
|---|---|
| Erster Index mit leerem Cache: Graph plus 2.443 Embeddings | 59 s (Median aus 3 Läufen: 58,3 / 58,9 / 60,2 s) |
| Index einer weiteren Kopie (neuer Store), Embeddings aus dem geteilten Cache | 2,8 s (Median aus 3 Läufen: 2,3 / 2,8 / 2,8 s) |
Erste Graph-Antwort auf einem nicht indexierten Repository (who-calls) |
2,6 s |
Graph-Abfragen arbeiten, sobald der Graph steht; die Embeddings entstehen im Hintergrund. Eine semantische Suche in dieser Phase meldet Fortschritt und ETA auf stderr und antwortet, sobald die Embeddings fertig sind; auf serde nach 64 s.
greppy bettet nur ein, was noch nicht im Cache liegt. Treffer für dasselbe Modell, denselben Prompt und denselben Inhalt gelten benutzerweit, also auch in einem anderen Worktree oder Repository. greppy index zeigt die Aufteilung:
$ greppy index .
indexed 219 files (120 unsupported, 0 unreadable, 0 oversize, 0 file-limit, 0 time-budget); 4571 nodes extracted; generation 1 (project: serde)
embedded 2443 code spans (0 local-store reused, 0 global-cache hits, 2443 inference misses, 4573 considered, 2150 non-definition skipped, 0 missing-file, 0 invalid-span, 0 oversize, 0 failed, 0 stale pruned)
$ greppy index .
indexed 219 files (120 unsupported, 0 unreadable, 0 oversize, 0 file-limit, 0 time-budget); 4571 nodes extracted; generation 1 (project: serde)
embedded 2443 code spans (0 local-store reused, 2443 global-cache hits, 0 inference misses, 4573 considered, 2150 non-definition skipped, 0 missing-file, 0 invalid-span, 0 oversize, 0 failed, 0 stale pruned)
Abfragen
Das sind warme Zeiten, mit Index und laufenden Inferenz-Daemons, jeweils der Median aus 5 Läufen:
| Befehl (serde, Apple M5) | Median |
|---|---|
greppy who-calls visit_content_map |
60 ms |
greppy callees visit_content_map |
70 ms |
greppy read visit_content_map |
73 ms |
greppy brief visit_content_map |
108 ms |
greppy search "deserialize a map from buffered content" |
108 ms |
greppy impact visit_content_map |
109 ms |
Eine neue Suchfrage bettet die Frage ein und erzeugt die Navigationshinweise für Treffer, die noch keinen haben. Fünf neue Fragen an serde, je einmal gestellt, brauchten 0,53 bis 2,57 s, im Median 2,16 s. Bei derselben Frage ein zweites Mal liegen Embedding und Hinweise schon im Cache: 108 ms.
CUDA und Metal im Vergleich
Das Footprint-Harness misst beide Plattformen mit demselben Ablauf und demselben serde-Commit, aufgezeichnet mit einem Build vor 0.4.1:
| Erster Index mit Embeddings | brief, warm |
search, warm |
|
|---|---|---|---|
| CUDA (RTX A4500) | 14,5 s | 0,09–0,12 s | 0,20 s |
| Metal (Apple M5) | 63,2 s | 0,58–0,74 s | 0,91–1,04 s |
Die aufgezeichneten Läufe findest du in diesen Belegdateien:
Platzbedarf
Diese Größen stammen von greppy 0.4.1 auf macOS arm64:
| Installiertes Binary | 974 MB |
| Store pro Repository (serde) | 29 MB |
| Entpackte Modelle | 814 MB: EmbeddingGemma 272 MB, Qwen3.5 542 MB |
| Cache-Quote | 10 GiB, mit Garbage Collection |
| Arbeitsspeicher der Inferenz-Daemons (RSS) | Embedding 328 MB, Hinweise 673 MB |
Das Binary enthält beide Modelle, ihre Tokenizer, die tree-sitter-Parser und SQLite. Zur Laufzeit lädt greppy nichts herunter. Das Linux-Binary mit CUDA misst im Footprint-Harness (Build vor 0.4.1) 1,11 GB.
Residente Modelle und Daemons
| Vorgabe | Wert |
|---|---|
| Ein geladenes Modell bleibt im Speicher | 300 Sekunden im Leerlauf |
| Ein Inferenz-Daemon beendet sich | nach 1.800 Sekunden im Leerlauf |
| Einträge im Workspace-Cache verfallen | nach 14 Tagen (GREPPY_STORE_TTL_DAYS), dazu eine unabhängige Größenquote (GREPPY_STORE_MAX_GIB) |
greppy cache status --json zeigt die Altersgrenze (ttl_secs) und die Quote (quota_bytes) auf deinem Rechner. Die beiden Daemons teilt sich jeder greppy-Prozess desselben Benutzers.
Verlinkte Worktrees und Agents (0.4.1)
Zwei Messungen aus dem CHANGELOG von 0.4.1 zeigen, was der geteilte Base-Index und der geteilte Inferenz-Cache bringen:
- Ein verlinkter Worktree eines Repositorys mit 41.012 Spans, die der Haupt-Checkout schon eingebettet hatte, brauchte auf einem Mac der M-Serie 1.520 s. Mit dem geteilten Inferenz-Cache braucht derselbe Worktree 161 s und berührt keine Modelldatei.
- Navigation über Base und Delta nutzt indizierte Abfragen:
pathging von mehr als 120 s auf unter 6 s.
Zeitverhalten, auf das du dich verlassen kannst
| Situation | Verhalten |
|---|---|
| Erste Graph-Abfrage auf einem nicht indexierten Repository | startet einen Index im Hintergrund und wartet höchstens 2 s auf den Graphen; bei großen Repositories endet die Abfrage danach mit Exit-Code 75 und der Bedingung für den nächsten Versuch |
| Ein anderer verlinkter Worktree hält den Base-Builder-Lock | index wartet höchstens 5 s, dann Exit-Code 75 mit dem Pfad des Locks |
| Zwei Minuten ohne Fortschritt | index status markiert den Job als möglicherweise hängend |
Das Kind von bash-smart ist 15 s still |
ein Lebenszeichen mit PID und Laufzeit, danach eines pro Minute |
$ greppy bash-smart -- sleep 20
bash-smart: command still running — pid=19344, elapsed=15s; child output is being captured and will be summarized on exit
ok — exit 0
Auf deinem Repository messen
greppy trial vergleicht auf deinem eigenen Repository einen Lauf ohne und einen mit greppy, ausgeführt mit Pi, und druckt einen JSON-Datensatz greppy.project-trial.v1. Siehe greppy trial --help und Benchmarks und Paper.