akinomyoga / ble.sh

Bash Line Editor―a line editor written in pure Bash with syntax highlighting, auto suggestions, vim modes, etc. for Bash interactive sessions.
BSD 3-Clause "New" or "Revised" License
2.58k stars 82 forks source link

Source ble.sh each time when restart a console will increase the time cost. #422

Closed hongyi-zhao closed 6 months ago

hongyi-zhao commented 6 months ago

See below:

werner@X10DAi:~/Public/repo/github.com/akinomyoga/ble.sh.git$ time source out/ble.sh --noattach

real    0m0.378s
user    0m0.331s
sys 0m0.049s

Regards, Zhao

akinomyoga commented 6 months ago

Yes, I know that. It's impossible to load a configuration with zero cost. What would you expect specifically?

hongyi-zhao commented 6 months ago

I expect to minimize this time to a range that the user will hardly feel, such as less than 0.05 seconds.

akinomyoga commented 6 months ago

I've already made much effort to minimize the initialization time. The current time is the best effort. ble.sh already has diagnostics for the initialization time. For example, for the source time, you can rewrite the script file ble.pp in the following way

diff --git a/ble.pp b/ble.pp
index c4b6e527..c9259192 100644
--- a/ble.pp
+++ b/ble.pp
@@ -1,7 +1,7 @@
 #!/bin/bash
 #%$> out/ble.sh
 #%[release = 0]
-#%[measure_load_time = 0]
+#%[measure_load_time = 1]
 #%[debug_keylogger = 1]
 #%[leakvar = ""]
 #%#----------------------------------------------------------------------------

and rebuild ble.sh by running make, and then start a ble.sh session. This is the result in my environment.

$ bash --norc
$ source out/ble.sh --norc --noattach
ble.sh: 1709970550.553626 load start
ble.sh: 1709970550.600419 parsed
[Elapsed 0.008s; CPU U:0.004s S:0.003s (100.80%)] ble.pp/prologue (3 forks)
[Elapsed 0.002s; CPU U:0.002s S:0.000s (101.57%)] src/def.sh (0 forks)
[Elapsed 0.031s; CPU U:0.022s S:0.009s (99.81%)] src/util.sh (2 forks)
[Elapsed 0.008s; CPU U:0.008s S:0.000s (99.66%)] src/decode.sh (0 forks)
[Elapsed 0.005s; CPU U:0.004s S:0.001s (99.78%)] src/color.sh (0 forks)
[Elapsed 0.016s; CPU U:0.013s S:0.003s (99.88%)] src/canvas.sh (0 forks)
[Elapsed 0.007s; CPU U:0.006s S:0.001s (100.09%)] src/history.sh (0 forks)
[Elapsed 0.017s; CPU U:0.014s S:0.004s (99.69%)] src/edit.sh (0 forks)
[Elapsed 0.002s; CPU U:0.001s S:0.001s (101.49%)] lib/core-cmdspec-def.sh (0 forks)
[Elapsed 0.004s; CPU U:0.003s S:0.001s (100.20%)] lib/core-syntax-def.sh (0 forks)
[Elapsed 0.008s; CPU U:0.006s S:0.002s (99.95%)] lib/core-complete-def.sh (0 forks)
[Elapsed 0.002s; CPU U:0.001s S:0.001s (100.45%)] lib/core-debug-def.sh (0 forks)
[Elapsed 0.003s; CPU U:0.002s S:0.001s (99.93%)] contrib/integration/bash-preexec-def.sh (0 forks)
[Elapsed 0.002s; CPU U:0.001s S:0.001s (100.12%)] ble.pp/epilogue (0 forks)
[Elapsed 0.001s; CPU U:0.000s S:0.001s (100.27%)] blerc: '/dev/null' (0 forks)
[Elapsed 0.138s; CPU U:0.107s S:0.030s (99.90%)] Total
ble.sh: 1709970550.744142 load end
[Elapsed 0.200s; CPU U:0.163s S:0.037s (99.88%)] Total

The time is bounded from below by the parser speed of Bash. (edit: it seems the execution speed.)

edit: After checking the result, you can revert the change to ble.pp and re-run make.

akinomyoga commented 6 months ago

Do you have an idea to further reduce the initialization time? How can I reduce the time?

hongyi-zhao commented 6 months ago

IMHO, the only possible way is to implement the logic using pure compiled languages such as go, rust, etc., instead of shell, as it is:

image

akinomyoga commented 6 months ago

That's not the goal of the project.

One of the reasons that I wrote the Bash configuration in pure Bash is that I need to log in to different shared systems such as HPC systems, front-end servers, and gateway servers. Some of them do not provide compilers, some are under proprietary operating systems, and some of them are the ones that I only log in to several times. To use a consistent shell experience in all of these systems, I needed to write a configuration in pure Bash. Bash is the shell that can be used in maximally many systems. If I could use compiler languages, I wouldn't have written this software in the first place.

If you are just interested in the performance, you could just switch to fish or zsh. There are also many other modern shells. Another related reason that I wrote ble.sh is that I got used to Bash and also have to use Bash in those systems. If we forget about the systems without compilers, I might still have modified the source code of Bash. I thought about that possibility, but I finally gave up the idea because it becomes harder to track the upstream Bash because the binary interface is more unstable, and also, the code tends to become more tightly bound to the implementation details of Bash. It would become a pain to maintain the compatibility after several years. But if you are interested in writing a new line editor for Bash in C or another compiler language, and you continue to support tracking the upstream Bash, that would be great.

akinomyoga commented 6 months ago

Another possibility is to develop a new Bash-compatible shell faster than Bash. I've been contributing to Bash for small fixes and performance improvements, but Bash's implementation is basically inefficient. If I had time, maybe I could consider re-implementing the entire shell from scratch in an efficient way so that I can use ble.sh with the new shell in systems with a compiler while continuing to use ble.sh with Bash in systems where the new shell cannot be compiled for. However, clearly, I don't have such a time.

hongyi-zhao commented 6 months ago

Thank you for your explanations and feedback. My objective is to discover an improved bash shell history tool, which led me to atuin that in turn requires ble.sh. This requirement prompted my question. Due to the relatively high time performance cost associated with the solution mentioned above, I am currently using hishtory.

akinomyoga commented 6 months ago

which led me to atuin that in turn requires ble.sh.

Atuin can be combined with bash-preexec. Although bash-preexec has some problems of missing commands for certain conditions, it should work better than hishtory as far as I look at the shell configuration provided by hishtory. The hishtory configuration uses the same (incomplete) approach as bash-preexec but doesn't seem to care about details that bash-preexec cares about. If the reason that you use hishtory is only for the performance, I think you can use Atuin with bash-preexec, which has (more problems than ble.sh but) less problems than hishtory.

But if you'd like hishtory for reasons other than the performance, that's fine of course.

hongyi-zhao commented 6 months ago

Although bash-preexec has some problems of missing commands for certain conditions, I think you can use Atuin with bash-preexec, which has (more problems than ble.sh but) less problems than history.

What exactly are the problems you talking about? Will they have a very serious impact on usage?

But if you'd like hishtory for reasons other than the performance, that's fine of course.

At the moment, the only problem I find is this one.

akinomyoga commented 6 months ago

I'm not sure if it would be very serious or not because it would depend on the user, but I suspect there are several issues in the implementation of hishtory.

I haven't actually tried hishtory, so these are just my guess: I think if you use C-r, the duration of the next command will not be correctly measured. Also, if you attempt completion, the duration of the next command will not be correctly measured. The duration of a subshell command (command) and a function definition funcname() { ...; } is also not correctly measured. If HISTIGNORE is set, the duration of the previous or next command could be overwritten by the execution of a command that matches HISTIGNORE, etc.

There seems to be a report that I guess is related:

If there is an existing configuration in PROMPT_COMMAND that references the exit code of the previous command, hishtory configuration overwrites the exit status that the other configuration references, etc.

hongyi-zhao commented 6 months ago

Indeed, I have also noticed that the running time can be overestimated.

hongyi-zhao commented 6 months ago

Another feature given by hishtory is select an entry and cd into that directory, as discussed here. It seems that this feature doesn't exist in atuin.

akinomyoga commented 6 months ago

Yeah, if you want to use hishtory for a reason other than the performance, you can use hishtory. Only if you wanted to actually use Atuin but were forced to use hishtory for the performance problem of ble.sh, you could better use Atuin with bash-preexec.

akinomyoga commented 6 months ago

Are you satisfied with the answer and discussion above?