Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve complete.bash #113

Closed
wants to merge 5 commits into from
Closed

Conversation

lakshayrohila
Copy link

@lakshayrohila lakshayrohila commented Feb 15, 2024

What does it do?

Improves complete.bash by:

  • removing the redundant loop in _tldr_get_files(), which does nothing but re-echoes the same output.
  • removing the redundant | sort | uniq calls.
  • the _tldr_get_files() now only returns the matching results, instead of returning thousands of lines each time.
  • applies fix similar to Fix: prevent freezing of autocomplete in Zsh #105 for bash.
  • earlier version could not actually autocomplete on cases such as --vers, which it should autocomplete. This version would autocomplete in that case to tldr --version.
  • earlier not all command line options were present in this file (such as --verbose); this version adds them.

Why the change?

The autocomplete function almost freezes (on my system) for almost 20 secs (I am using it in bash). This is due to the above reasons. This version reduces that time to almost instantaneous.

How can this be tested?

Install the autocomplete file just as is described in this repo's README.md, and try to use completion (with tab key press) in bash.

Where to start code review?

I've already mentioned the major changes in the What does it do? section.

Questions?

N/A

Checklist

  • I have checked there aren't any existing PRs open to fix this issue/add this feature.
  • I have compiled the code with make and tested the change in an active installation with sudo make install.

Notes for (2) : Since this is not a change in the code for the actual tldr program, I have not run (2); but rather tested the change with the steps I mentioned in How can this be tested? section.

@kbdharun kbdharun requested a review from sbrl February 16, 2024 04:40
Comment on lines +7 to +9
# usage: _tldr_get_files [architecture] [semi-completed word to search]
_tldr_get_files() {
local ret
local files="$(find $HOME/.tldrc/tldr/pages/$1 -name '*.md' -exec basename {} .md \;)"

IFS=$'\n\t'
for f in $files; do
echo $f
done
find "$HOME"/.tldrc/tldr/pages/"$1" -name "$2"'*.md' -exec basename -s .md {} +
Copy link
Author

@lakshayrohila lakshayrohila Feb 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend the reviewers to test if find ... -name '*.md' ... is better, or is find ... -name "$2"'*.md' ....

Comparing the performance of _tldr_complete function using time command does not help, since both methods perform almost the same.

Using the following commands, I was able to determine that after applying this change, the bottleneck is the find command:

$ word="he"
$ cmpl=`find $HOME/.tldrc/tldr/pages/linux/ -name "$word"'*.md' -exec basename -s '.md' {} + && find $HOME/.tldrc/tldr/pages/common/ -name "$word"'*.md' -exec basename -s '.md' {} +`; cmpl_sorted_n_uniq=`printf "%s" "$cmpl" | sort | uniq`
$ compgen -W "$cmpl_sorted_n_uniq" -- "$word" | pv -lr > /dev/null
$ ( find $HOME/.tldrc/tldr/pages/linux/ -name "$word"'*.md' -exec basename -s '.md' {} + && find $HOME/.tldrc/tldr/pages/common/ -name "$word"'*.md' -exec basename -s '.md' {} + ) | pv -rl >/dev/null

The results will be in this form:

[compgen's speed]
[find's speed]

In the other case (using only -name '*.md' in find command), I found compgen was the bottleneck instead of find; using the following commands:

$ word="he"
$ cmpl=`find $HOME/.tldrc/tldr/pages/linux/ -name '*.md' -exec basename -s '.md' {} + && find $HOME/.tldrc/tldr/pages/common/ -name '*.md' -exec basename -s '.md' {} +`; cmpl_sorted_n_uniq=`printf "%s" "$cmpl" | sort | uniq`
$ compgen -W "$cmpl_sorted_n_uniq" -- "$word" | pv -lr > /dev/null
$ ( find $HOME/.tldrc/tldr/pages/linux/ -name '*.md' -exec basename -s '.md' {} + && find $HOME/.tldrc/tldr/pages/common/ -name '*.md' -exec basename -s '.md' {} + ) | pv -rl >/dev/null

The result will be in the same form as described above.


The results I got:

  1. with find ... -name '*.md' ...:
    • compgen's speed: 1.69k/s
    • find's speed: 241k/s
  2. with find ... -name "$2"'*.md' ...:
    • compgen's speed: 255k/s
    • find's speed: 1.48k/s

Both methods used about 0.05 secs on my system (using time _tldr_complete).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In theory find.... | xargs -P "$(nproc)" basename... hour potentially be faster. I wonder if using a pure-bash alternative to basename or an awk/sed solution there could help? The trouble is that you're spawning a new process for each line with the basename call there.

@elliotfontaine
Copy link

Thanks for the quick fix @lakshayrohila !

Copy link
Member

@sbrl sbrl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good improvement to me. Avoiding the basename subprocess would increase performance further - maybe by a significant margin.

So sorry it's taken until now for me to review this! Life has been hectic.

@lakshayrohila
Copy link
Author

@sbrl, @elliotfontaine thanks for all your replies! I have become a bit busy now, so won't be able to do anything further on the issue - so am closing the PR. I request you to take on this issue yourself, it will be just quick copy-n-paste of this PR's code and whatever further edits you want to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants