martinvonz / jj

A Git-compatible VCS that is both simple and powerful
https://martinvonz.github.io/jj/
Apache License 2.0
8.32k stars 284 forks source link

working_copy: Only serialise clock if only clock changed #3928

Closed mlcui-corp closed 3 months ago

mlcui-corp commented 3 months ago

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:

mlcui-corp commented 3 months ago

Closing this PR as discussed in https://github.com/martinvonz/jj/pull/3928#discussion_r1646829743 - we will move watchman_clock out into a separate proto.