For the purpose of implementing has_tracked_dir (which means "has tracked
descendants) without an expensive sub-tree traversal, we maintaing a counter
of tracked descendants on each "directory" node of the tree-shaped dirstate.
Before this changeset, mutating or inserting a node at a given path would
involve:
- Walking the tree from root through ancestors to find the node or the spot where to insert it
- Looking at the previous node if any to decide what counter update is needed
- Performing any node mutation
- Walking the tree *again* to update counters in ancestor nodes
When profiling hg status on a large repo, this second walk takes times
while loading a the dirstate from disk.
It turns out we have enough information to decide before he first tree walk
what counter update is needed. This changeset merges the two walks, gaining
~10% of the total time for hg update (in the same hyperfine benchmark as
the previous changeset).
Profiling was done by compiling with this .cargo/config:
[profile.release] debug = true
then running with:
py-spy record -r 500 -n -o /tmp/hg.json --format speedscope -- \ ./hg status -R $REPO --config experimental.dirstate-tree.in-memory=1
then visualizing the recorded JSON file in https://www.speedscope.app/