Skip to content

Commit

Permalink
syntax (simple-word/eval): support opts=single for a better cache per…
Browse files Browse the repository at this point in the history
…formance
  • Loading branch information
akinomyoga committed Feb 20, 2021
1 parent 6ebec48 commit 10caaa4
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 30 deletions.
20 changes: 10 additions & 10 deletions lib/core-complete.sh
Expand Up @@ -1343,7 +1343,7 @@ function ble/complete/source/eval-simple-word {
function ble/complete/source/evaluate-path-spec {
local word=$1 sep=$2 opts=$3
if [[ :$comp_type: != *:sync:* && :$opts: != *:noglob:* ]]; then
opts=$opts:stopcheck:cached
opts=$opts:stopcheck:cached:single
[[ :$comp_type: == *:auto:* && $bleopt_complete_timeout_auto ]] &&
opts=$opts:timeout=$((bleopt_complete_timeout_auto))
fi
Expand Down Expand Up @@ -1976,7 +1976,7 @@ function ble/complete/progcomp/.compvar-perform-wordbreaks {
ble/array#push ret "$word"
}
function ble/complete/progcomp/.compvar-eval-word {
local opts=$2
local opts=$2:single
if [[ :$opts: == *:noglob:* ]]; then
ble/syntax:bash/simple-word/eval "$1" "$opts"
else
Expand Down Expand Up @@ -3287,7 +3287,7 @@ function ble/complete/candidates/.pick-nearest-sources {
comps_flags=$comps_flags${simple_flags}v

if ((${simple_ibrace%:*})); then
ble/complete/source/eval-simple-word "${reconstructed::${simple_ibrace#*:}}"; (($?==148)) && return 148
ble/complete/source/eval-simple-word "${reconstructed::${simple_ibrace#*:}}" single; (($?==148)) && return 148
comps_fixed=${simple_ibrace%:*}:$ret
comps_flags=${comps_flags}x
fi
Expand Down Expand Up @@ -3763,7 +3763,7 @@ function ble/complete/candidates/determine-common-prefix {
esac

local is_processed=
ble/complete/source/eval-simple-word "$common_reconstructed"; local ext=$?
ble/complete/source/eval-simple-word "$common_reconstructed" single; local ext=$?
((ext==148)) && return 148
if ((ext==0)) && ble/complete/candidates/filter:"$filter_type"/count-match-chars "$ret"; then
if [[ $filter_type == head ]] && ((ret<${#COMPV})); then
Expand Down Expand Up @@ -3823,7 +3823,7 @@ function ble/complete/candidates/determine-common-prefix {
else
local simple_flags simple_ibrace
ble/syntax:bash/simple-word/reconstruct-incomplete-word "$common0" &&
ble/complete/source/eval-simple-word "$ret" &&
ble/complete/source/eval-simple-word "$ret" single &&
[[ $ret == "$COMPV"* ]] &&
flag_reduction=1
(($?==148)) && return 148
Expand Down Expand Up @@ -4271,7 +4271,7 @@ function ble/complete/insert-common {
local menu_common_part=$COMPV
local ret simple_flags simple_ibrace
if ble/syntax:bash/simple-word/reconstruct-incomplete-word "$insert"; then
ble/complete/source/eval-simple-word "$ret"
ble/complete/source/eval-simple-word "$ret" single
(($?==148)) && return 148
menu_common_part=$ret
fi
Expand Down Expand Up @@ -4772,7 +4772,7 @@ function ble/complete/insert-braces {
local ret simple_flags simple_ibrace
ble/complete/candidates/determine-common-prefix/.apply-partial-comps # var[in,out] common
if ble/syntax:bash/simple-word/reconstruct-incomplete-word "$common"; then
ble/complete/source/eval-simple-word "$ret"
ble/complete/source/eval-simple-word "$ret" single
(($?==148)) && return 148
fixed=$common fixval=$ret
fi
Expand Down Expand Up @@ -4997,7 +4997,7 @@ function ble/complete/menu-filter {
return 0
fi
[[ $simple_ibrace ]] && ((${simple_ibrace%%:*}>10#0${_ble_complete_menu0_comp[6]%%:*})) && return 1 # 別のブレース展開要素に入った時
ble/syntax:bash/simple-word/eval "$ret"; (($?==148)) && return 148
ble/syntax:bash/simple-word/eval "$ret" single; (($?==148)) && return 148
local COMPV=$ret

local comp_type=${_ble_complete_menu0_comp[4]} cand_pack
Expand Down Expand Up @@ -5640,7 +5640,7 @@ function ble/widget/auto_complete/self-insert {
fi
elif [[ $_ble_complete_ac_type == [rmaA] && $ins != [{,}] ]]; then
if local ret simple_flags simple_ibrace; ble/syntax:bash/simple-word/reconstruct-incomplete-word "$comps_new"; then
if ble/complete/source/eval-simple-word "$ret" && local compv_new=$ret; then
if ble/complete/source/eval-simple-word "$ret" single && local compv_new=$ret; then
# r: 遡って書き換わる時
# 挿入しても展開後に一致する時、そのまま挿入。
# 元から展開後に一致していない場合もあるが、その場合は一旦候補を消してやり直し。
Expand Down Expand Up @@ -6033,7 +6033,7 @@ function ble/complete/source:sabbrev {
# filter で除外されない為に cand には評価後の値を入れる必要がある。
local ret simple_flags simple_ibrace
ble/syntax:bash/simple-word/reconstruct-incomplete-word "$cand" &&
ble/complete/source/eval-simple-word "$ret" || continue
ble/complete/source/eval-simple-word "$ret" single || continue

local value=$ret # referenced in "ble/complete/action:sabbrev/initialize"
local flag_source_filter=1
Expand Down
1 change: 1 addition & 0 deletions lib/core-syntax-def.sh
Expand Up @@ -113,3 +113,4 @@ if ((_ble_bash>=40300||_ble_bash>=40000&&!_ble_bash_loaded_in_function)); then
fi

builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_syntax_bash_simple_eval}"
builtin eval -- "${_ble_util_gdict_declare//NAME/_ble_syntax_bash_simple_eval_full}"
70 changes: 51 additions & 19 deletions lib/core-syntax.sh
Expand Up @@ -1413,6 +1413,7 @@ _ble_syntax_bash_simple_eval_hash=
## @var[in,out] _ble_syntax_bash_simple_eval
function ble/syntax:bash/simple-word/eval/.cache-clear {
ble/gdict#clear _ble_syntax_bash_simple_eval
ble/gdict#clear _ble_syntax_bash_simple_eval_full
}
## @fn ble/syntax:bash/simple-word/eval/.cache-update
## @var[in,out] _ble_syntax_bash_simple_eval
Expand All @@ -1429,45 +1430,73 @@ function ble/syntax:bash/simple-word/eval/.cache-update {
## @var[in,out] _ble_syntax_bash_simple_eval
function ble/syntax:bash/simple-word/eval/.cache-save {
((ext==148||ext==142)) && return 0
local ret; ble/string#quote-words "$3"
ble/gdict#set _ble_syntax_bash_simple_eval "$1" "ext=$2 count=$(($#-2)) ret=$ret"
local ret; ble/string#quote-words "${@:3}"
ble/gdict#set _ble_syntax_bash_simple_eval "$1" "ext=$2 ret=($ret)"
ble/gdict#set _ble_syntax_bash_simple_eval_full "$1" "ext=$2 count=$(($#-2)) ret=($ret)"
}
## @fn ble/syntax:bash/simple-word/eval/.cache-load word opts
function ble/syntax:bash/simple-word/eval/.cache-load {
ext= ret=
ble/gdict#get _ble_syntax_bash_simple_eval "$1" || return 1
if [[ :$2: == *:single:* ]]; then
ble/gdict#get _ble_syntax_bash_simple_eval "$1" || return 1
else
ble/gdict#get _ble_syntax_bash_simple_eval_full "$1" || return 1
fi
builtin eval -- "$ret"
return 0
}

## @fn ble/syntax:bash/simple-word/eval word opts
## @param[in] word
## @param[in,opt] opts
## noglob
## コロン区切りのオプション指定です。
##
## cached
## stopcheck
## noglob
## パス名展開を抑制します。
##
## timeout=NUM
## stopcheck を指定している時に有効です。timeout を指定します。
## timeout-highlight
## bleopt highlight_timeout_{sync,async} を参照して timeout します。
## retry-noglob-on-timeout
## timeout した時に noglob で改めて展開を試行します。
## 以下は (成功時の) 評価結果に影響を与えないオプションです。
##
## single
## 最初の展開結果のみを ret に設定します。
## count
## 変数 count に展開結果の単語数を返します。
## cached
## 展開結果をキャッシュします。
##
## 以下はパス名展開の起こる可能性にある単語に大して有効です。
##
## stopcheck
## ユーザー入力があった場合に中断します。
## timeout=NUM
## stopcheck を指定している時に有効です。timeout を指定します。
## timeout-highlight
## bleopt highlight_timeout_{sync,async} を参照して timeout します。
## retry-noglob-on-timeout
## timeout した時に noglob で改めて展開を試行します。
##
## @arr[out] ret
## 展開結果を返します。複数の単語に評価される場合にはそれを全て返します。
## opts に single が指定されている時、最初の展開結果のみを返します。
## @var[out] count
## opts に count が指定されている時に展開結果の数を返します。
##
## @var[out] ret
## @exit
## shopt -q failglob の時、パス名展開に失敗すると
## 0 以外の終了ステータスを返します。
##
function ble/syntax:bash/simple-word/eval {
[[ :$2: != *:count:* ]] && local count
if [[ :$2: == *:cached:* && :$2: != *:noglob:* ]]; then
ble/syntax:bash/simple-word/eval/.cache-update
local ext; ble/syntax:bash/simple-word/eval/.cache-load "$1" && return "$ext"
local ext; ble/syntax:bash/simple-word/eval/.cache-load "$1" "$2" && return "$ext"
fi

local __ble_ret
ble/syntax:bash/simple-word/eval/.impl "$1" "$2"; local ext=$?
ret=("${__ble_ret[@]}")
count=${#ret[@]}

if [[ :$2: == *:cached:* && :$2: != *:noglob:* ]]; then
ble/syntax:bash/simple-word/eval/.cache-save "$1" "$ext" "${ret[@]}"
Expand Down Expand Up @@ -6453,7 +6482,7 @@ function ble/syntax/progcolor/word:default/.detect-separated-path {
local word=$1
((wtype==CTX_ARGI||wtype==CTX_ARGEI||wtype==CTX_VALI||wtype==ATTR_VAR||wtype==CTX_RDRS)) || return 1

local detect_opts=stopcheck:timeout-highlight:cached:url
local detect_opts=url:$highlight_eval_opts
((wtype==CTX_RDRS)) && detect_opts=$detect_opts:noglob
[[ $word == '~'* ]] && ((_ble_syntax_attr[p0]!=ATTR_TILDE)) && detect_opts=$detect_opts:notilde
ble/syntax:bash/simple-word/detect-separated-path "$word" :, "$detect_opts"
Expand Down Expand Up @@ -6575,13 +6604,13 @@ function ble/syntax/progcolor/word:default/.highlight-filename {
local p0=${1%%:*} p1=${1#*:}
local wtxt=${text:p0:p1-p0}

local path_opts=stopcheck:timeout-highlight:cached:after-sep
local path_opts=after-sep:$highlight_eval_opts
# チルダ展開の文脈でない時には抑制
[[ $wtxt == '~'* ]] && ((_ble_syntax_attr[p0]!=ATTR_TILDE)) && path_opts=$path_opts:notilde
((wtype==CTX_RDRS||wtype==ATTR_VAR||wtype==CTX_VALI&&wbeg<p0)) && path_opts=$path_opts:noglob

local ret path spec ext value
ble/syntax:bash/simple-word/evaluate-path-spec "$wtxt" / "$path_opts"; ext=$? value=("${ret[@]}")
local ret path spec ext value count
ble/syntax:bash/simple-word/evaluate-path-spec "$wtxt" / "count:$path_opts"; ext=$? value=("${ret[@]}")
((ext==148)) && return 148
if ((ext==142)); then
if [[ $ble_textarea_render_defer_running ]]; then
Expand All @@ -6594,7 +6623,7 @@ function ble/syntax/progcolor/word:default/.highlight-filename {
elif ((ext&&(wtype==CTX_CMDI||wtype==CTX_ARGI||wtype==CTX_ARGEI||wtype==CTX_RDRF||wtype==CTX_RDRS||wtype==CTX_VALI))); then
# failglob 等の理由で展開に失敗した場合
ble/syntax/progcolor/word:default/.highlight-pathspec-with-attr "$ATTR_ERR"
elif (((wtype==CTX_RDRF||wtype==CTX_RDRD)&&${#value[@]}>=2)); then
elif (((wtype==CTX_RDRF||wtype==CTX_RDRD)&&count>=2)); then
# 複数語に展開されたら駄目
ble/syntax/progcolor/wattr#setattr "$p0" "$ATTR_ERR"
elif ((wtype==CTX_CMDI)); then
Expand All @@ -6619,7 +6648,7 @@ function ble/syntax/progcolor/word:default/.is-option-context {

local iword ret
for ((iword=1;iword<progcolor_iword;iword++)); do
ble/syntax/progcolor/eval-word "$iword" stopcheck:timeout-highlight:cached
ble/syntax/progcolor/eval-word "$iword" "$highlight_eval_opts"
[[ $ret == -- ]] && return 1
done
return 0
Expand Down Expand Up @@ -6669,7 +6698,7 @@ function ble/syntax/progcolor/word:default/.impl {
((ext==148)) && return 148
if ((ext==0)); then
local sep=$ret ranges i
ble/syntax:bash/simple-word/locate-filename "$wtxt" "$sep" stopcheck:timeout-highlight:cached:url
ble/syntax:bash/simple-word/locate-filename "$wtxt" "$sep" "url:$highlight_eval_opts"
(($?==148)) && return 148; ranges=("${ret[@]}")
for ((i=0;i<${#ranges[@]};i+=2)); do
ble/syntax/progcolor/word:default/.highlight-filename $((p0+ranges[i])):$((p0+ranges[i+1]))
Expand Down Expand Up @@ -6843,6 +6872,9 @@ function ble/highlight/layer:syntax/word/.update-attributes/.proc {
## @var[in,out] color_umin color_umax
function ble/highlight/layer:syntax/word/.update-attributes {
((_ble_syntax_word_umin>=0)) || return 1

local highlight_eval_opts=stopcheck:timeout-highlight:cached:single

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 @@ -23,7 +23,7 @@
- edit: change default behavior of <kbd>C-w</kbd> and <kbd>M-w</kbd> to operate on backward words `#D1448` 47a3301
- 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` 000000
- syntax (`simple-word/eval`): fix unperformed tilde expansions in the background (reported by 3ximus) `#D1463` 6ebec48
- 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,6 +51,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
- 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
31 changes: 31 additions & 0 deletions note.txt
Expand Up @@ -3813,6 +3813,37 @@ bash_tips

2021-02-04

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

* 以前大量の入力を与えた時に遅いという事を解決した時に似たような事があった
気がする。パス名展開がなかったとしても大量の単語を含む配列をコピーすると
遅いという話。

前に経験した時にはどの様な事が原因でどのように対策したのだったか。記録を
漁ってみると #D1302 に関連しそうな内容が書かれている。

> chars=("${...[@]}" "$@") が 13 秒もかかっている。何故?

うーん。改めて試してみたがそんなに遅くない。関数経由で代入して改善したと
いう事が書かれているが、実際に試してみても関数経由で代入すると却って遅く
なる。またパス名展開の影響かとも思ったが set -f しても大して変化しない。
結局再現はできない。

再現ができないので現在発生している問題が具体的にどういう物なのか調べる事
もできない。取り敢えずまた計測をお願いするしかないのだという気がする。予
想では cache が巨大である為に起こっている事ではないか。

* reject: そういう意味では既に議論した様に、単語ごとに展開済みの単純な情報
を記録する事にして必要になった時は eval まで取りに行くのではなくて一部だ
け記録する事にするという手もある。

→今は其処までしなくても良いという気がする。

取り敢えず simple-word/eval のキャッシュとして完全な情報を記録する物と、最
初の単語だけ記録する物を用意して、highlighting の内部では主に最初の単語だけ
を参照する様に変更した。

* syntax: tilde で始まる単語の着色がされない? (reported by 3ximus) [#D1463]
https://github.com/akinomyoga/ble.sh/issues/82#issuecomment-772529714

Expand Down

0 comments on commit 10caaa4

Please sign in to comment.