runtime(indent-tests): Instrument timed "search*()" calls Commit: https://github.com/vim/vim/commit/fe8508eda002196bd9095c35ea7892bce06bb6d2 Author: Aliaksei Budavei <0x000...@gmail.com> Date: Sat Apr 19 11:35:02 2025 +0200
runtime(indent-tests): Instrument timed "search*()" calls The offered "tracer.vim" script can be used to measure and record elapsed time for explicitly annotated "search*()"es, set off with "VIM_INDENT_TEST_TRACE_(START|END)" comment markers, in indent plugins. related: #17116 Signed-off-by: Aliaksei Budavei <0x000...@gmail.com> Signed-off-by: Christian Brabandt <c...@256bit.org> diff --git a/Filelist b/Filelist index 4067df508..c5b3c4fdd 100644 --- a/Filelist +++ b/Filelist @@ -863,6 +863,7 @@ RT_SCRIPTS = \ runtime/indent/testdir/*.vim \ runtime/indent/testdir/*.in \ runtime/indent/testdir/*.ok \ + runtime/indent/testdir/tools/* \ runtime/ftplugin/*.vim \ runtime/ftplugin/logtalk.dict \ runtime/ftplugin/README.txt \ diff --git a/runtime/indent/testdir/tools/tracer.vim b/runtime/indent/testdir/tools/tracer.vim new file mode 100644 index 000000000..d87315401 --- /dev/null +++ b/runtime/indent/testdir/tools/tracer.vim @@ -0,0 +1,166 @@ +vim9script + +# Whenever indent plugins contain "search*()" lines explicitly annotated with +# "VIM_INDENT_TEST_TRACE_(START|END)" comment markers; this script can then be +# used as shown to measure and record elapsed time for such decorated calls. +# +# Usage: +# cd runtime/indent +# vim -u NONE -S testdir/tools/tracer.vim \ +# html.vim javascript.vim \ +# ../autoload/python.vim ../autoload/dist/vimindent.vim +# git diff +# make clean test +# vim testdir/00-TRACE_LOG.fail + +def GenerateTempletForTracing(fname: string, vname: string): list<string> + #### ONLY INSTRUMENT "search*()"es FOR INDENT TESTS. + + const templet: list<string> =<< trim eval END + + if getcwd() =~# '\<runtime/indent$' + + def! g:IndentTestTrace(id: string, start: list<number>, result: any): any + const end: list<number> = reltime(start) + + if !has_key(g:indent_test_trace_times, id) + g:indent_test_trace_times[id] = [] + endif + + g:indent_test_trace_times[id] + ->add(reltimefloat(end)) + return result + enddef + + def! g:IndentTestInitTracing() + # Possibly use a later "{fname}", cf. ":runtime indent/foo.vim". + autocmd_add([{{ + replace: true, + group: 'tracing', + event: 'QuitPre', + bufnr: bufnr(), + cmd: 'g:IndentTestWriteTraceTimes()', + }}]) + g:indent_test_trace_times = {{}} + enddef + + def! g:IndentTestWriteTraceTimes() + # Anticipate usage by multiple languages. + const token: string = printf('%02x', (rand() % 26)) + writefile(['" {fname}:', + "let {vname}_" .. token .. " = " .. string(g:indent_test_trace_times), + "let {vname}_" .. token .. "_summary = " .. string(g:indent_test_trace_times + ->items() + ->reduce((outer: dict<dict<any>>, times: list<any>) => + extend({{[times[0]]: times[1] + ->copy() + ->reduce((inner: dict<any>, v: float) => + extend({{ + min: inner.min < v ? inner.min : v, + max: inner.max > v ? inner.max : v, + sum: (inner.sum + v), + avg: ((inner.sum + v) / inner.count), + }}, + inner, + "keep"), + {{ + min: v:numbermax - 0.0, + max: v:numbermin + 0.0, + sum: 0.0, + avg: 0.0, + count: len(times[1]), + }})}}, + outer), + {{}}))], + (!empty($VIM_INDENT_TEST_LOG) && filewritable($VIM_INDENT_TEST_LOG)) + ? $VIM_INDENT_TEST_LOG + : "testdir/00-TRACE_LOG.fail", + "a") + enddef + + call g:IndentTestInitTracing() + + else + + def! g:IndentTestTrace(_: string, _: list<number>, result: any): any + return result + enddef + + endif + + END + return templet +enddef + +def InstrumentMarkedEntry(): bool + const marker_start: string = 'VIM_INDENT_TEST_TRACE_START' + const start: number = search('\C\<' .. marker_start .. '\>', 'ceW') + + if start == 0 + return false + endif + + const marker_end: string = 'VIM_INDENT_TEST_TRACE_END' + const end: number = search('\C\<' .. marker_end .. '\>', 'ceW') + + if end == 0 + return false + endif + + const tracee: list<string> = matchlist( + getline(start + 1), + '\(^.\+\)\(\<search\%(pair\)\=\%(pos\)\=\s*(.*$\)') + + if empty(get(tracee, 1, '')) || empty(get(tracee, 2, '')) + return false + endif + + const end_line: string = getline(end) + const tracer: string = printf('%sg:IndentTestTrace("%s", reltime(), %s', + tracee[1], + strpart(end_line, (stridx(end_line, marker_end) + strlen(marker_end) + 1)), + tracee[2]) + + if (end - start) > 1 + setline((start + 1), tracer) + setline((end - 1), getline(end - 1) .. ')') + else + setline((start + 1), tracer .. ')') + endif + + return true +enddef + +def ProcessIndentPluginCmdlineArgs() + const names: list<string> = range(char2nr('a'), char2nr('z')) + ->map((_: number, n: number) => nr2char(n, true)) + var entries: number = 0 + var next: number = 0 + + for fname: string in argv(-1) + if filereadable(fname) && filewritable(fname) + execute 'new ' .. fname + call cursor(1, 1) + + while InstrumentMarkedEntry() + entries += 1 + endwhile + + if entries > 0 + append(1, GenerateTempletForTracing(fname, get(names, next, names[-1]))) + wq + endif + + entries = 0 + next += 1 + endif + endfor +enddef + +if empty(system('git status --porcelain=v1')) + ProcessIndentPluginCmdlineArgs() +endif + +quitall + +# vim:fdm=syntax:sw=2:ts=8:noet:nosta: -- -- You received this message from the "vim_dev" maillist. Do not top-post! Type your reply below the text you are replying to. For more information, visit http://www.vim.org/maillist.php --- You received this message because you are subscribed to the Google Groups "vim_dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to vim_dev+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/vim_dev/E1u64kz-00CJkT-E2%40256bit.org.