vim-patch:9.1.1622: Patch v9.1.1432 causes performance regressions (#35288)

Problem:  Patch v9.1.1432 causes performance regressions
Solution: Revert "patch 9.1.1432: GTK GUI: Buffer menu does not handle
          unicode correctly" (Yee Cheng Chin).

This reverts commit 08896dd330c6dc8324618fde482db968e6f71088.

The previous change to support Unicode characters properly in the
buffers menu resorted to removing all buffer menus and re-add the
buffers after doing a sort, per each buffer addition. This was quite
slow because if Vim is trying to load in multiple buffers at once (e.g.
when loading a session) this scales in O(n^2) and Vim can freeze for
dozens of seconds when adding a few hundred buffers.

related: vim/vim#17405
related: vim/vim#17928
fixes: vim/vim#17897

cda0d17f59

Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
This commit is contained in:
zeertzjq
2025-08-10 17:11:13 +08:00
committed by GitHub
parent 22d90217c6
commit 9d85f086d9
2 changed files with 42 additions and 37 deletions

View File

@@ -2,7 +2,7 @@
" You can also use this as a start for your own set of menus.
"
" Maintainer: The Vim Project <https://github.com/vim/vim>
" Last Change: 2025 Jun 04
" Last Change: 2023 Aug 10
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Note that ":an" (short for ":anoremenu") is often used to make a menu work
@@ -684,7 +684,12 @@ func s:BMAdd()
if s:bmenu_count == &menuitems && s:bmenu_short == 0
call s:BMShow()
else
call s:BMRedraw()
let name = expand("<afile>")
let num = expand("<abuf>") + 0 " add zero to convert to a number type
if s:BMCanAdd(name, num)
call <SID>BMFilename(name, num)
let s:bmenu_count += 1
endif
endif
endif
endfunc
@@ -726,16 +731,17 @@ func s:BMCanAdd(name, num)
endfunc
" Create the buffer menu (delete an existing one first).
func s:BMShow()
func s:BMShow(...)
let s:bmenu_wait = 1
let s:bmenu_short = 1
let s:bmenu_count = 0
let s:bmenu_items = {}
"
" get new priority, if exists
if a:0 == 1
let g:bmenu_priority = a:1
endif
call s:BMRedraw()
endfunc
func s:BMRedraw()
" Remove old menu, if it exists; keep one entry to avoid a torn off menu to
" disappear. Use try/catch to avoid setting v:errmsg
try | unmenu &Buffers | catch | endtry
@@ -755,30 +761,26 @@ func s:BMRedraw()
unmenu &Buffers.Dummy
" figure out how many buffers there are
let buffer_menu_items = []
let buf = 1
while buf <= bufnr('$')
let name = bufname(buf)
if s:BMCanAdd(name, buf)
call add(buffer_menu_items, [substitute(name, ".", '\L\0', ""), name, buf])
if s:BMCanAdd(bufname(buf), buf)
let s:bmenu_count = s:bmenu_count + 1
endif
let buf = buf + 1
endwhile
let s:bmenu_count = len(buffer_menu_items)
if s:bmenu_count <= &menuitems
let s:bmenu_short = 0
endif
" iterate through buffer list, adding each buffer to the menu:
call sort(buffer_menu_items)
let i = 0
for menu_item in buffer_menu_items
call s:BMFilename(menu_item[1], menu_item[2], i)
let i += 1
endfor
let buf = 1
while buf <= bufnr('$')
let name = bufname(buf)
if s:BMCanAdd(name, buf)
call <SID>BMFilename(name, buf)
endif
let buf = buf + 1
endwhile
let s:bmenu_wait = 0
aug buffer_list
au!
@@ -787,6 +789,21 @@ func s:BMRedraw()
aug END
endfunc
func s:BMHash(name)
" Make name all upper case, so that chars are between 32 and 96
let nm = substitute(a:name, ".*", '\U\0', "")
if has("ebcdic")
" HACK: Replace all non alphabetics with 'Z'
" Just to make it work for now.
let nm = substitute(nm, "[^A-Z]", 'Z', "g")
let sp = char2nr('A') - 1
else
let sp = char2nr(' ')
endif
" convert first six chars into a number for sorting:
return (char2nr(nm[0]) - sp) * 0x800000 + (char2nr(nm[1]) - sp) * 0x20000 + (char2nr(nm[2]) - sp) * 0x1000 + (char2nr(nm[3]) - sp) * 0x80 + (char2nr(nm[4]) - sp) * 0x20 + (char2nr(nm[5]) - sp)
endfunc
func s:BMHash2(name)
let nm = substitute(a:name, ".", '\L\0', "")
" Not exactly right for EBCDIC...
@@ -808,15 +825,16 @@ func s:BMHash2(name)
endfunc
" Insert a buffer name into the buffer menu.
func s:BMFilename(name, num, index)
func s:BMFilename(name, num)
let munge = <SID>BMMunge(a:name, a:num)
let hash = <SID>BMHash(munge)
if s:bmenu_short == 0
let s:bmenu_items[a:num] = munge
let cmd = 'an ' .. g:bmenu_priority .. '.9999.' .. a:index .. ' &Buffers.' .. munge
let cmd = 'an ' . g:bmenu_priority . '.' . hash . ' &Buffers.' . munge
else
let menu_name = <SID>BMHash2(munge) . munge
let s:bmenu_items[a:num] = menu_name
let cmd = 'an ' .. g:bmenu_priority .. '.9999.0.' .. a:index .. ' &Buffers.' .. menu_name
let cmd = 'an ' . g:bmenu_priority . '.' . hash . '.' . hash . ' &Buffers.' . menu_name
endif
" set 'cpo' to include the <CR>
let cpo_save = &cpo

View File

@@ -44,17 +44,4 @@ func Test_colorscheme()
redraw!
endfunc
" Test that buffer names are shown at the end in the :Buffers menu
func Test_Buffers_Menu()
doautocmd LoadBufferMenu VimEnter
let name = '天'
exe ':badd ' .. name
let nr = bufnr('$')
let cmd = printf(':amenu Buffers.%s\ (%d)', name, nr)
let menu = split(execute(cmd), '\n')[1]
call assert_match('^9999 '.. name, menu)
endfunc
" vim: shiftwidth=2 sts=2 expandtab