-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Avoid forks to improve performance (especially on Cygwin) #298
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
Conversation
By and large looks good.
I've merged the first commit. I have some specific review questions on the rest, but first: Why do you say it's a WIP/PoC? Other than not distinguishing hashed commands from commands? |
It's now 38c8fbe. |
That would be nicer, yes. But right now there the there is no api function for the individual highlighters called from
This was all done very quickly. But it seems to work a lot better and faster than I originally expected. |
Done. Review:
edited: Stroke out incorrect statement |
Shouldn't % alias -s foo.bar=deep bar=shallow
% type 1.foo.bar
bar is a suffix alias for shallow |
I'd like to merge this and #301 next. |
Done.
Done.
I'm not a 100% sure where we left off in the IRC discussion. Do you want to go forward with the future-proof approach of using
I think it's best to leave them in, to be on the safe side.
Right. Fixed. |
First of all, let me post here the patch I devised during our IRC discussion: --- a/highlighters/main/main-highlighter.zsh
+++ b/highlighters/main/main-highlighter.zsh
@@ -96,6 +96,7 @@ _zsh_highlight_main__type() {
if (( $#options_to_set )); then
setopt localoptions $options_to_set;
fi
+ unset REPLY
if zmodload -e zsh/parameter; then
if (( $+aliases[(e)$1] )); then
REPLY=alias
@@ -107,12 +108,11 @@ _zsh_highlight_main__type() {
REPLY=function
elif (( $+builtins[(e)$1] )); then
REPLY=builtin
- elif builtin type -w $1 >/dev/null 2>&1; then
+ elif (( $+commands[(e)$1] )); then
REPLY=command
- else
- REPLY=none
fi
- else
+ fi
+ if ! (( $+REPLY )); then
REPLY="${$(LC_ALL=C builtin type -w -- $1 2>/dev/null)#*: }"
fi
_zsh_highlight_command_type_cache[(e)$1]=$REPLY Now, "no forks ever" seems to me like spilling the baby with the bathwater: on most platforms, forks aren't expensive, so a single fork in a rare codepath would be preferable to giving an actively wrong answer (not just "I don't know" instead of "{new-in-5.3 thing}", but "{command}" instead of "{new-in-5.3 thing}"). The point about future-proofness is a legitimate one but it can be handled by changing the last assignment to Keep in mind that there is an open feature request to make the command word as it is being typed a different color than green and red if it is the prefix of a valid command word; that can be implemented without forks (just by iterating once over the zsh/parameter hashes) and should make the fork a rare codepath. So, while I would listen to an argument that the fork should be avoided on cygwin or made opt-outable, I think the default everywhere else should be to try
+1 |
@m0vie points out that current master doesn't map " diff --git a/highlighters/main/main-highlighter.zsh b/highlighters/main/main-highlighter.zsh
index a0f8dba..9247f68 100644
--- a/highlighters/main/main-highlighter.zsh
+++ b/highlighters/main/main-highlighter.zsh
@@ -330,7 +330,8 @@ _zsh_highlight_main_highlighter()
*': function') style=function;;
*': command') style=command;;
*': hashed') style=hashed-command;;
- *) if _zsh_highlight_main_highlighter_check_assign; then
+ *) if [[ $res != *': none' ]] ; then style=NEWTHING ; else
+ if _zsh_highlight_main_highlighter_check_assign; then
style=assign
if [[ $arg[-1] == '(' ]]; then
in_array_assignment=true
@@ -383,6 +384,7 @@ _zsh_highlight_main_highlighter()
style=unknown-token
fi
fi
+ fi
;;
esac
fi
But what should this case funnel to? What should NEWTHING be? [command], [unknown-token], [new-command-type-from-the-future]? edit: This is now tracked separately as #316. |
c0e9b2e
to
4918091
Compare
Found-by: m0viefreak (in #298)
2b628ec
to
cb99b23
Compare
Review of latest version (cb99b23):
I'm sorry for not realizing these command type cache questions earlier, but in any case, I think we can merge the first four commits (with the log message fixes), close this issue, and open two spin-off issues for (a) finalizing the fallback order, (b) adding the command cache. So, let me know once you've fixup'd the fourth? Or I can do that if you prefer. |
* commit '2f18ba': 'main': use zsh/parameter to resolve alias driver: load zsh/parameter if available
I've merged the first two commits in f146651. I haven't rebased them but I did change the "area:" leader of the log messages to match convention. |
Done.
Done.
The cache is actually quite an improvement. Consider long lines such as:
That would result in an execution of
every time you type a letter, each time calling
Even `zsh: correct 'foo' to 'fop' [nyae]?`` So IMHO that's not a big deal since it never worked before either.
Yes, sounds good to me. But I'd really like the get both commits merged first. The details we have to think about are very minor and it's probably easier to do built on top of master. |
Yes, I realized this was the use-case that would most benefit from the cache; I just wondered how often it occurred in practice.
Good point: there's no reason to clear the cache more often than every time
Okay, so let's merge it without any fallback now (just Thanks! |
Okay. changed. |
If possible, try to use the zsh/parameter module to get information about a shell words. This avoids subshells and is a huge speed improvement on systems such as cygwin. Note 1: $commands does not know about PATH_DIRS. So in case PATH_DIRS is set, 'type -w' is still used if nothing else matches. Note 2: zsh/parameter can't distinguish between 'command' and 'hashed'. Adjusted the test for that case to XFAIL. The ideal solution would be if whence had an option to put the result in REPLY instead of printing it to stdout.
Merged 12b879c and its parent. That left two outstanding questions:
|
command type cache is tracked in #320. |
I've compared speeds: ./parse.zsh parse_bash.zsh > 2 2,10s user 0,58s system 92% cpu 2,905 total vs ./parse.zsh parse_bash.zsh > 1 1,93s user 0,16s system 99% cpu 2,077 total So almost 0.2 sec. Seems not much, but everything feels to be much faster now. |
Shouldn't you include system time in your count? The whole purpose of the PR was to eliminate syscalls, and users care about wallclock time, not about userland time (despite the name of the latter).
:-) |
True, total time counts, so there is significant gain almost 0.9 sec PS. As for the why did I look at user time: it corresponds closely to what zprof reports. I once did vast amount of tests with zprof, and also with time ( ), and user time was closely the same as total running time of main function in zprof. |
This pull-request improves z-sy-h performance by avoiding all forks.
Especially on Cygwin the improvement is extreme.
The only drawback so far seems to be that "hashed" commands cannot be distinguished from normal "commands" anymore -- which I think is very minor.
Anyways, this is more of a proof-of-concept.