Closed hongyi-zhao closed 6 months ago
Yes, I know that. It's impossible to load a configuration with zero cost. What would you expect specifically?
I expect to minimize this time to a range that the user will hardly feel, such as less than 0.05 seconds.
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
.
Do you have an idea to further reduce the initialization time? How can I reduce the time?
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:
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.
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.
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.
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.
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.
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.
Indeed, I have also noticed that the running time can be overestimated.
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
.
Are you satisfied with the answer and discussion above?
See below:
Regards, Zhao