Skip to content

Commit

Permalink
highlight: propagate pathname-expansion timeouts in sync highlighting
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Feb 20, 2021
1 parent 10caaa4 commit c2555e2
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 30 deletions.
13 changes: 8 additions & 5 deletions blerc
Expand Up @@ -524,20 +524,23 @@
# bleopt highlight_variable=


## The following settings control the timeout for the pathname expansions
## performed in the syntax highlighting. When the word contains a glob pattern
## that takes a long time to evaluate the pathname expansion, the syntax
## highlighting based on the filename is canceled based on the timeouts
## specified by these settings. "highlight_timeout_sync" /
## The following settings control the timeout and user-input cancellation of
## the pathname expansions performed in the syntax highlighting. When the word
## contains a glob pattern that takes a long time to evaluate the pathname
## expansion, the syntax highlighting based on the filename is canceled based
## on the timeouts specified by these settings. "highlight_timeout_sync" /
## "highlight_timeout_async" specify the timeout durations in milliseconds to
## be used for the foreground / background syntax highlighting, respectively.
## When the timeout occurred in the foreground, the syntax highlighting will be
## deferred to the background syntax highlighting. When the timeout occurred
## in the background, the syntax highlighting for the filename is canceled.
## When the value is empty, the corresponding timeout is disabled.
## "syntax_eval_polling_interval" specifies the maximal interval between the
## user-input checking.

# bleopt highlight_timeout_sync=500
# bleopt highlight_timeout_async=5000
# bleopt syntax_eval_polling_interval=50


## The following settings specify graphic styles of each faces.
Expand Down
1 change: 1 addition & 0 deletions lib/core-syntax-def.sh
Expand Up @@ -99,6 +99,7 @@ bleopt/declare -v highlight_filename 1
bleopt/declare -v highlight_variable 1
bleopt/declare -v highlight_timeout_sync 50
bleopt/declare -v highlight_timeout_async 5000
bleopt/declare -v syntax_eval_polling_interval 50

if ((_ble_bash>=40300||_ble_bash>=40000&&!_ble_bash_loaded_in_function)); then
builtin unset -v _ble_syntax_highlight_filetype
Expand Down
62 changes: 41 additions & 21 deletions lib/core-syntax.sh
Expand Up @@ -1383,21 +1383,20 @@ function ble/syntax:bash/simple-word/eval/.impl {
if [[ $__ble_flags == *s* ]]; then
local __ble_sync_command="ble/syntax:bash/simple-word/eval/.print-result $__ble_word"
local __ble_sync_opts=progressive-weight
local __ble_sync_weight=$bleopt_syntax_eval_polling_interval

# determine timeout
local __ble_sync_timeout=
if local __ble_rex=':timeout=([^:]*):'; [[ :$__ble_opts: =~ $__ble_rex ]]; then
local __ble_sync_timeout=$_ble_syntax_bash_simple_eval_timeout
if [[ $_ble_syntax_bash_simple_eval_timeout_carry ]]; then
__ble_sync_timeout=0
elif local __ble_rex=':timeout=([^:]*):'; [[ :$__ble_opts: =~ $__ble_rex ]]; then
__ble_sync_timeout=${BASH_REMATCH[1]}
elif [[ :$__ble_opts: == *:timeout-highlight:* ]]; then
__ble_sync_timeout=$bleopt_highlight_timeout_sync
[[ $ble_textarea_render_defer_running ]] &&
__ble_sync_timeout=$bleopt_highlight_timeout_async
fi
[[ $__ble_sync_timeout ]] &&
__ble_sync_opts=$__ble_sync_opts:timeout=$((__ble_sync_timeout))

local __ble_def
ble/util/assign __ble_def 'ble/util/conditional-sync "$__ble_sync_command" "" "" "$__ble_sync_opts"' &>/dev/null; local ext=$?
ble/util/assign __ble_def 'ble/util/conditional-sync "$__ble_sync_command" "" "$__ble_sync_weight" "$__ble_sync_opts"' &>/dev/null; local ext=$?
builtin eval -- "$__ble_def"
else
builtin eval "ble/syntax:bash/simple-word/eval/.set-result $__ble_word" &>/dev/null; local ext=$?
Expand Down Expand Up @@ -1470,22 +1469,31 @@ function ble/syntax:bash/simple-word/eval/.cache-load {
## ユーザー入力があった場合に中断します。
## timeout=NUM
## stopcheck を指定している時に有効です。timeout を指定します。
## timeout-highlight
## bleopt highlight_timeout_{sync,async} を参照して timeout します。
## retry-noglob-on-timeout
## timeout した時に noglob で改めて展開を試行します。
## timeout-carry
## timeout が発生した場合に後続の eval にタイムアウトを伝播します。
##
## @var[in] _ble_syntax_bash_simple_eval_timeout
## パス名展開のタイムアウトの既定値を指定します。空文字列が指定さ
## れている時、既定でタイムアウトは起こりません。
## @var[in,out] _ble_syntax_bash_simple_eval_timeout_carry
## この値が設定されている時、パス名展開に対して強制的にタイムアウ
## トが起こります。opts に timeout-carry が指定されている時に値が設定されます。
##
## @arr[out] ret
## 展開結果を返します。複数の単語に評価される場合にはそれを全て返します。
## opts に single が指定されている時、最初の展開結果のみを返します。
## @var[out] count
## opts に count が指定されている時に展開結果の数を返します。
##
## @var[out] ret
## @exit
## shopt -q failglob の時、パス名展開に失敗すると
## 0 以外の終了ステータスを返します。
## ユーザー入力により中断した場合は 148 を返します。timeout を起こ
## した場合 142 を返します。例えば failglob など、その他の理由でパ
## ス名展開に失敗した時 0 以外の終了ステータスを返します。
##
_ble_syntax_bash_simple_eval_timeout=
_ble_syntax_bash_simple_eval_timeout_carry=
function ble/syntax:bash/simple-word/eval {
[[ :$2: != *:count:* ]] && local count
if [[ :$2: == *:cached:* && :$2: != *:noglob:* ]]; then
Expand All @@ -1501,9 +1509,13 @@ function ble/syntax:bash/simple-word/eval {
if [[ :$2: == *:cached:* && :$2: != *:noglob:* ]]; then
ble/syntax:bash/simple-word/eval/.cache-save "$1" "$ext" "${ret[@]}"
fi
if ((ext==142)) && [[ :$2: == *:retry-noglob-on-timeout:* ]]; then
ble/syntax:bash/simple-word/eval "$1" "$2:noglob"
return "$?"
if ((ext==142)); then
[[ :$2: == *:timeout-carry:* ]] &&
_ble_syntax_bash_simple_eval_timeout_carry=1
if [[ :$2: == *:retry-noglob-on-timeout:* ]]; then
ble/syntax:bash/simple-word/eval "$1" "$2:noglob"
return "$?"
fi
fi
return "$ext"
}
Expand All @@ -1526,8 +1538,8 @@ function ble/syntax:bash/simple-word/.get-rex_element {
## @param[in,opt] opts
## noglob
## stopcheck
## timeout-highlight
## timeout=*
## timeout-carry
## cached
## notilde
## after-sep
Expand Down Expand Up @@ -1565,7 +1577,7 @@ function ble/syntax:bash/simple-word/evaluate-path-spec {
local rematch=$BASH_REMATCH
s=$s$rematch
ble/syntax:bash/simple-word/eval "$notilde$s" "$eval_opts"; ext=$?
((ext==148)) && return "$ext"
((ext==148||ext==142)) && return "$ext"
p=$ret
tail=${tail:${#rematch}}
ble/array#push spec "$s"
Expand All @@ -1583,8 +1595,8 @@ function ble/syntax:bash/simple-word/evaluate-path-spec {
## @param[in] opts
## noglob
## stopcheck
## timeout-highlight
## timeout=*
## timeout-carry
## cached
## url
## notilde
Expand Down Expand Up @@ -1656,10 +1668,10 @@ function ble/syntax:bash/simple-word/locate-filename/.exists {
## [a-z]+:// で始まるパスを無条件に有効なパスと判定します。
## stopcheck
## 時間のかかる可能性のあるパス名展開をユーザ入力により中断します。
## timeout-highlight
## stopcheck に際して timeout として highlight 用の設定を使用します。
## timeout=*
## stopcheck に際して timeout を指定します。
## timeout-carry
## タイムアウトを後続のパス名展開に伝播させます。
## cached
## 展開内容をキャッシュします。
##
Expand Down Expand Up @@ -6873,7 +6885,15 @@ function ble/highlight/layer:syntax/word/.update-attributes/.proc {
function ble/highlight/layer:syntax/word/.update-attributes {
((_ble_syntax_word_umin>=0)) || return 1

local highlight_eval_opts=stopcheck:timeout-highlight:cached:single
# Timeout setting for simple-word/eval
if [[ ! $ble_textarea_render_defer_running ]]; then
local _ble_syntax_bash_simple_eval_timeout=$bleopt_highlight_timeout_sync
local _ble_syntax_bash_simple_eval_timeout_carry=
local highlight_eval_opts=cached:single:stopcheck:timeout-carry
else
local _ble_syntax_bash_simple_eval_timeout=$bleopt_highlight_timeout_async
local highlight_eval_opts=cached:single:stopcheck
fi

ble/syntax/tree-enumerate-in-range "$_ble_syntax_word_umin" "$_ble_syntax_word_umax" \
ble/highlight/layer:syntax/word/.update-attributes/.proc
Expand Down
3 changes: 2 additions & 1 deletion memo/ChangeLog.md
Expand Up @@ -24,6 +24,7 @@
- syntax (`layer:syntax/word`): perform pathname expansions in background subshells (motivated by 3ximus) `#D1449` 13e7bdd
- syntax (`simple-word/is-simple-noglob`): suppress error messages on expansions `#D1461` a56873f
- syntax (`simple-word/eval`): fix unperformed tilde expansions in the background (reported by 3ximus) `#D1463` 6ebec48
- syntax (`simple-word/eval`): propagate timeouts in sync highlighting (reported by 3ximus) `#D1465` 0000000
- complete: perform pathname expansions in subshells (motivated by 3ximus) `#D1450` d511896
- complete: support `bleopt complete_timeout_compvar` to time out pathname expansions for `COMP_WORDS` / `COMP_LINE` `#D1457` cc2881a
- prompt: rename `bleopt prompt_{status_line => term_status}` `#D1462` cca1cbc
Expand Down Expand Up @@ -51,7 +52,7 @@
- global: update the style of document comments ff4c4e7
- util: add function `ble/string#quote-words` `#D1451` f03b87b
- syntax (`ble/syntax:bash/simple-word/eval`): cache `#D1453` 6d8311e
- syntax (`simple-word/eval`): support `opts=single` for a better cache performance (motivated by 3ximus) `#D1464` 0000000
- syntax (`simple-word/eval`): support `opts=single` for a better cache performance (motivated by 3ximus) `#D1464` 10caaa4
- global: refactor `setup => set up / set-up` `#D1456` c37a9dd
- global: clean up helps of user functions `#D1459` 33c283e
- benchmark (`ble-measure`): support `-T TIME` and `-B TIME` option `#D1460` 1aa471b
Expand Down
62 changes: 62 additions & 0 deletions note.txt
Expand Up @@ -3813,6 +3813,68 @@ bash_tips

2021-02-04

* 2021-02-01 highlight: highlight_timeout_sync=0 にしても遅い (reported by 3ximus) [#D1465]
https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-770390986

% OK. Sorry, I actually reproduce this level of delay at my side too, but I
% haven't regarded it as *terrible*. That's probably because I know what
% `ble.sh` is doing in the background. I felt that it's actually doing a good
% job considering how strange things `ble.sh` is doing in the background.
%
% →と思ったが、bleopt highlight_timeout_sync=0 を実行していなかった。これを
% 実行したら自分のところでは特に問題もなく動く様になった。当初は実装のバグか
% とも思ったが、一部の host の上でだけ動作しないという事があるだろうか。
%
% Do you think it is related to `ffmpeg` running in the background? I see in
% the `top` pane multiple instances of `ffmpeg` are running, but the load
% average is smaller than 2, which means that those `ffmpeg` instances are
% waiting for an interrupt in more than half of their running time. If those
% `ffmpeg` are encoding some video clips, they may be waiting for disk I/O.
%
% →と思ったが disk I/O 待ちだと status D になる筈である。画面を見る限りはそ
% うなっていない。更に -x11grab というオプションについて調べてみるとこれはス
% クリーンキャプチャである。つまり、これらの ffmpeg は単にこの説明を作るため
% に起動しているだけで、問題には関係してこない。

何れにしてもこれは background highlighting におけるユーザー入力による中断速
度に関係している。でもどの部分が悪さをしているのか分からない。

1. 入力検出?
2. 生存検出?
3. 或いは kill & wait だろうか。

どうも background highlighting のユーザー入力によるキャンセルの応答が遅い様
である。自分の手元では残念ながら再現しない。取り敢えず勘で可能性のある時間
のかかりそうな箇所に関連した時間計測を依頼したがぴんと来ない。多分、別の所
に原因があるのではないか。

2021-02-04 追加報告では遅い時もあるしそうでない時もあるそうだ。後、遅いとは
言っている割にそれ程遅い訳でもない気がする。単に複数のパス名展開が試みられ
るのでそれぞれについてタイムアウトが試みられて遅くなっているというだけなの
ではないか。という訳で、取り敢えずの修正として一度 timeout を起こしたら後続
の eval も即刻で timeout する様に修正した。

それから conditional-sync をチェックする頻度も変更する事にする。取り敢えず
これで改善するかどうか判断する事にする。

| 後、timeout は total でカウントするべきなのかもしれない。或いは一つ
| timeout したらそれ以降は timeout が必要になる物はもう処理しない様に変更す
| る。

2021-02-05 新しい報告で上記の cumulative timeout & shorter polling interval
で改善するという事が確かめられた。問題は現在の cumulative timeout によって
本来短時間で着色できる単語が着色されずに残ってしまう可能性について。

然し、そもそも cumulative timeout で本当に改善しているのかというのは謎であ
る。今 highlight_timeout_sync=0 にしている。とすると highlight_timeout_sync
が効いていないか、或いは highlight_timeout_async の側での cumulative
timeout が効いているか。highlight_timeout_async の側での timeout が効いてい
るとすると何故なのか。ユーザー入力がある場合には何れにしても has-input の
チェックによってキャンセルされるのではないか。うーん。手元で試してみたが余
り違いが分からない。

* done: syntax_eval_polling_interval について doc を記述する

* 展開済みであっても展開される単語の数に比例して遅い (reported by 3ximus) [#D1464]
https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-772529714

Expand Down
6 changes: 3 additions & 3 deletions src/util.sh
Expand Up @@ -2774,7 +2774,7 @@ function ble/util/sleep {
##
function ble/util/conditional-sync {
local __command=$1
local __cancel=${2:-'! ble/decode/has-input'}
local __continue=${2:-'! ble/decode/has-input'}
local __weight=$3; ((__weight<=0&&(__weight=100)))
local __opts=$4

Expand All @@ -2785,7 +2785,7 @@ function ble/util/conditional-sync {
local __weight_max=$__weight __weight=1

[[ $__timeout ]] && ((__timeout<=0)) && return 142
builtin eval -- "$__cancel" || return 148
builtin eval -- "$__continue" || return 148
(
builtin eval -- "$__command" & local __pid=$!
while
Expand All @@ -2804,7 +2804,7 @@ function ble/util/conditional-sync {
((__weight<<=1,__weight>__weight_max&&(__weight=__weight_max)))
builtin kill -0 "$__pid" &>/dev/null
do
if ! builtin eval -- "$__cancel"; then
if ! builtin eval -- "$__continue"; then
builtin kill "$__pid" &>/dev/null
return 148
fi
Expand Down

0 comments on commit c2555e2

Please sign in to comment.