feat(bash): support high-resolution timing even without ble.sh (#1534)

* feat(bash): support high-resolution timing without blesh

For the integration using bash-preexec, this measures the execution
time of the command using EPOCHREALTIME without the support by ble.sh.
This is not as accurate as the measurement by ble.sh as it contains
also the processing time of the preexec and precmd hooks, but it is
still free from the fork cost.

* fix(shell): work around custom IFS for duration

When a custom IFS is set by the user, the word splitting of
${duration:+--duration "$duration"} does not work as expected.  We
instead use the form "--duration=$duration" with the word splitting
being disabled.
This commit is contained in:
Koichi Murase 2024-01-10 22:23:51 +09:00 committed by GitHub
parent a80ca27cc4
commit 99f76ced50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 8 deletions

View File

@ -15,23 +15,42 @@ __atuin_preexec() {
local id
id=$(atuin history start -- "$1")
export ATUIN_HISTORY_ID=$id
__atuin_preexec_time=${EPOCHREALTIME-}
}
__atuin_precmd() {
local EXIT=$?
local EXIT=$? __atuin_precmd_time=${EPOCHREALTIME-}
[[ ! $ATUIN_HISTORY_ID ]] && return
local duration=""
# shellcheck disable=SC2154,SC2309
if [[ ${BLE_ATTACHED-} && _ble_bash -ge 50000 && ${_ble_exec_time_ata-} ]]; then
if ((BASH_VERSINFO[0] >= 5)); then
# We use the high-resolution duration based on EPOCHREALTIME (bash >=
# 5.0) that is recorded by ble.sh. The shell variable
# `_ble_exec_time_ata` contains the execution time in microseconds.
duration=${_ble_exec_time_ata}000
# 5.0) if available.
# shellcheck disable=SC2154,SC2309
if [[ ${BLE_ATTACHED-} && ${_ble_exec_time_ata-} ]]; then
# With ble.sh, we utilize the shell variable `_ble_exec_time_ata`
# recorded by ble.sh.
duration=${_ble_exec_time_ata}000
else
# With bash-preexec, we calculate the time duration here, though it
# might not be as accurate as `_ble_exec_time_ata` because it also
# includes the time for precmd/preexec handling. Bash does not
# allow floating-point arithmetic, so we remove the non-digit
# characters and perform the integral arithmetic. The fraction
# part of EPOCHREALTIME is fixed to have 6 digits in Bash. We
# remove all the non-digit characters because the decimal point is
# not necessarily a period depending on the locale.
duration=$((${__atuin_precmd_time//[!0-9]} - ${__atuin_preexec_time//[!0-9]}))
if ((duration >= 0)); then
duration=${duration}000
else
duration="" # clear the result on overflow
fi
fi
fi
(ATUIN_LOG=error atuin history end --exit "$EXIT" ${duration:+--duration "$duration"} -- "$ATUIN_HISTORY_ID" &) >/dev/null 2>&1
(ATUIN_LOG=error atuin history end --exit "$EXIT" ${duration:+"--duration=$duration"} -- "$ATUIN_HISTORY_ID" &) >/dev/null 2>&1
export ATUIN_HISTORY_ID=""
}

View File

@ -44,7 +44,7 @@ _atuin_precmd() {
printf -v duration %.0f $(((__atuin_precmd_time - __atuin_preexec_time) * 1000000000))
fi
(ATUIN_LOG=error atuin history end --exit $EXIT ${=duration:+--duration $duration} -- $ATUIN_HISTORY_ID &) >/dev/null 2>&1
(ATUIN_LOG=error atuin history end --exit $EXIT ${duration:+--duration=$duration} -- $ATUIN_HISTORY_ID &) >/dev/null 2>&1
export ATUIN_HISTORY_ID=""
}