Skip to content

🐛 Hyperlinks make delta 55x slower when used as the pager for git log #1939

Open
@charlievieth

Description

@charlievieth

Issue

The hyperlinks option makes delta ~55x slower when used as the pager for git log because it calls GitConfig::get_remote_url for each commit hash, which is incredibly slow and essentially makes delta unusable for repos with many commits.

Possible Solution

If possible, delta should cache the Git remote URL and re-use it. I would create a PR that does this, but my Rust skills are extremely limited (though I may still try).

Performance tests

Both of these commands were ran from the root of a recent version of the Linux source tree. The below results are from an M4 Mac Pro, but were roughly equal to the results I got on my AMD Linux server. We limit the amount of git log data processed to 32MiB (head -c $((32 * 1024 * 1024))) since processing the full output of git log when hyperlinks are enabled takes an very very long time (when processing the full amount the slow down is 66x, which I would consider more accurate because it amortizes the startup time).

Note: A recent version of pv is required to run the below commands since the --stats option is a recent addition. Homebrew will install the latest version, but if you're on a Linux distro that does not have a recent version then it can easily be built from source (you'll need to run autoreconf --force --install --verbose -Wall to generate the configure file if building from the Git repo).

Hyperlinks Enabled

# cd to a repo with a large commit history then run:
$ DELTA_PAGER='bash -c "time head -c $((32 * 1024 * 1024)) | pv --stats --output=/dev/null"' \
    git -c 'pager.log=delta --hyperlinks' log
    
32.0MiB 0:00:43 [ 755KiB/s]
rate min/avg/max/mdev = 731516.382/773784.852/814642.291/16590.908 B/s

real	0m43.400s
user	0m0.183s
sys	0m1.367s

Hyperlinks Disabled

# cd to a repo with a large commit history then run:
$ DELTA_PAGER='bash -c "time head -c $((32 * 1024 * 1024)) | pv --stats --output=/dev/null"' \
    git -c 'pager.log=delta' log
    
32.0MiB 0:00:00 [40.1MiB/s]
rate min/avg/max/mdev = 42006890.474/42006890.474/42006890.474/nan B/s

real	0m0.802s
user	0m0.051s
sys	0m0.379s

CPU Profiles (macOS Instruments) with Hyperlinks

Call Tree

Screenshot 2025-01-10 at 6 51 55 PM

Flamegraph

Screenshot 2025-01-10 at 6 54 15 PM

CPU Profile without Hyperlinks

When hyperlinks are disabled we see that delta spends most of its time writing to stdout, which I'd expect since we're writing more data than we've read (since we're adding escape sequences and write(2) is pretty slow on macOS) and consuming input (processing ANSI input):

Screenshot 2025-01-10 at 7 59 10 PM

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions