When the working copy is identical to the last snapshot - which is quite often - only the watchman_clock changes. When this happens, the entirety of the working copy proto is reserialised, including the O(n) file_states field, which is slow.
As non-repeated proto fields always take the last field in the serialised message (1), we can skip the serialisation of the whole working copy by only serialising the fields that have changed and appending it to the last serialised proto.
This speeds up most jj commands by ~50ms on a large repository:
$ hyperfine --sort command --warmup 3 --runs 20 -L bin jj-before,jj-after \
"target/release/{bin} -R ~/chromiumjj/src show -s @"
Benchmark 1: target/release/jj-before -R ~/chromiumjj/src show -s @
Time (mean ± σ): 401.5 ms ± 4.5 ms [User: 227.2 ms, System: 172.9 ms]
Range (min … max): 394.3 ms … 414.2 ms 20 runs
Benchmark 2: target/release/jj-after -R ~/chromiumjj/src show -s @
Time (mean ± σ): 347.3 ms ± 4.6 ms [User: 179.3 ms, System: 166.4 ms]
Range (min … max): 340.7 ms … 358.0 ms 20 runs
Relative speed comparison
1.16 ± 0.02 target/release/jj-before -R ~/chromiumjj/src show -s @
1.00 target/release/jj-after -R ~/chromiumjj/src show -s @
Checklist
If applicable:
[ ] I have updated CHANGELOG.md
[ ] I have updated the documentation (README.md, docs/, demos/)
[ ] I have updated the config schema (cli/src/config-schema.json)
When the working copy is identical to the last snapshot - which is quite often - only the
watchman_clock
changes. When this happens, the entirety of the working copy proto is reserialised, including the O(n)file_states
field, which is slow.As non-repeated proto fields always take the last field in the serialised message (1), we can skip the serialisation of the whole working copy by only serialising the fields that have changed and appending it to the last serialised proto.
This speeds up most
jj
commands by ~50ms on a large repository:Checklist
If applicable:
CHANGELOG.md