view src/testdir/test_memory_usage.vim @ 32721:94f4a488412e v9.0.1683

Updated runtime files Commit: https://github.com/vim/vim/commit/6efb1980336ff324e9c57a4e282530b952fca816 Author: Christian Brabandt <cb@256bit.org> Date: Thu Aug 10 05:44:25 2023 +0200 Updated runtime files This is a collection of various PRs from github that all require a minor patch number: 1) https://github.com/vim/vim/pull/12612 Do not conflate dictionary key with end of block 2) https://github.com/vim/vim/pull/12729: When saving and restoring 'undolevels', the constructs `&undolevels` and `:set undolevels` are problematic. The construct `&undolevels` reads an unpredictable value; it will be the local option value (if one has been set), or the global option value (otherwise), making it unsuitable for saving a value for later restoration. Similarly, if a local option value has been set for 'undolevels', temporarily modifying the option via `:set undolevels` changes the local value as well as the global value, requiring extra work to restore both values. Saving and restoring the option value in one step via the construct `:let &undolevels = &undolevels` appears to make no changes to the 'undolevels' option, but if a local option has been set to a different value than the global option, it has the unintended effect of changing the global 'undolevels' value to the local value. Update the documentation to explain these issues and recommend explicit use of global and local option values when saving and restoring. Update some unit tests to use `g:undolevels`. 3) https://github.com/vim/vim/pull/12702: Problem: Pip requirements files are not recognized. Solution: Add a pattern to match pip requirements files. 4) https://github.com/vim/vim/pull/12688: Add indent file and tests for ABB Rapid 5) https://github.com/vim/vim/pull/12668: Use Lua 5.1 numeric escapes in tests and add to CI Only Lua 5.2+ and LuaJIT understand hexadecimal escapes in strings. Lua 5.1 only supports decimal escapes: > A character in a string can also be specified by its numerical value > using the escape sequence \ddd, where ddd is a sequence of up to three > decimal digits. (Note that if a numerical escape is to be followed by a > digit, it must be expressed using exactly three digits.) Strings in Lua > can contain any 8-bit value, including embedded zeros, which can be > specified as '\0'. To make sure this works with Lua 5.4 and Lua 5.1 change the Vim CI to run with Lua 5.1 as well as Lua 5.4 6) https://github.com/vim/vim/pull/12631: Add hurl filetype detection 7) https://github.com/vim/vim/pull/12573: Problem: Files for haskell persistent library are not recognized Solution: Add pattern persistentmodels for haskell persistent library closes: #12612 closes: #12729 closes: #12702 closes: #12688 closes: #12668 closes: #12631 closes: #12573 Co-authored-by: lacygoill <lacygoill@lacygoill.me> Co-authored-by: Michael Henry <drmikehenry@drmikehenry.com> Co-authored-by: ObserverOfTime <chronobserver@disroot.org> Co-authored-by: KnoP-01 <knosowski@graeffrobotics.de> Co-authored-by: James McCoy <jamessan@jamessan.com> Co-authored-by: Jacob Pfeifer <jacob@pfeifer.dev> Co-authored-by: Borys Lykah <lykahb@fastmail.com>
author Christian Brabandt <cb@256bit.org>
date Thu, 10 Aug 2023 06:30:06 +0200
parents 72245f9c9405
children
line wrap: on
line source

" Tests for memory usage.

source check.vim
CheckFeature terminal
CheckNotGui

" Skip tests on Travis CI ASAN build because it's difficult to estimate memory
" usage.
CheckNotAsan

source shared.vim

func s:pick_nr(str) abort
  return substitute(a:str, '[^0-9]', '', 'g') * 1
endfunc

if has('win32')
  if !executable('wmic')
    throw 'Skipped: wmic program missing'
  endif
  func s:memory_usage(pid) abort
    let cmd = printf('wmic process where processid=%d get WorkingSetSize', a:pid)
    return s:pick_nr(system(cmd)) / 1024
  endfunc
elseif has('unix')
  if !executable('ps')
    throw 'Skipped: ps program missing'
  endif
  func s:memory_usage(pid) abort
    return s:pick_nr(system('ps -o rss= -p ' . a:pid))
  endfunc
else
  throw 'Skipped: not win32 or unix'
endif

" Wait for memory usage to level off.
func s:monitor_memory_usage(pid) abort
  let proc = {}
  let proc.pid = a:pid
  let proc.hist = []
  let proc.max = 0

  func proc.op() abort
    " Check the last 200ms.
    let val = s:memory_usage(self.pid)
    if self.max < val
      let self.max = val
    endif
    call add(self.hist, val)
    if len(self.hist) < 20
      return 0
    endif
    let sample = remove(self.hist, 0)
    return len(uniq([sample] + self.hist)) == 1
  endfunc

  call WaitFor({-> proc.op()}, 10000)
  return {'last': get(proc.hist, -1), 'max': proc.max}
endfunc

let s:term_vim = {}

func s:term_vim.start(...) abort
  let self.buf = term_start([GetVimProg()] + a:000)
  let self.job = term_getjob(self.buf)
  call WaitFor({-> job_status(self.job) ==# 'run'})
  let self.pid = job_info(self.job).process

  " running an external command may fail once in a while
  let g:test_is_flaky = 1
endfunc

func s:term_vim.stop() abort
  call term_sendkeys(self.buf, ":qall!\<CR>")
  call WaitFor({-> job_status(self.job) ==# 'dead'})
  exe self.buf . 'bwipe!'
endfunc

func s:vim_new() abort
  return copy(s:term_vim)
endfunc

func Test_memory_func_capture_vargs()
  " Case: if a local variable captures a:000, funccall object will be free
  " just after it finishes.
  let testfile = 'Xtest.vim'
  let lines =<< trim END
        func s:f(...)
          let x = a:000
        endfunc
        for _ in range(10000)
          call s:f(0)
        endfor
  END
  call writefile(lines, testfile, 'D')

  let vim = s:vim_new()
  call vim.start('--clean', '-c', 'set noswapfile', testfile)
  let before = s:monitor_memory_usage(vim.pid).last

  call term_sendkeys(vim.buf, ":so %\<CR>")
  call WaitFor({-> term_getcursor(vim.buf)[0] == 1})
  let after = s:monitor_memory_usage(vim.pid)

  " Estimate the limit of max usage as 2x initial usage.
  " The lower limit can fluctuate a bit, use 97%.
  call assert_inrange(before * 97 / 100, 2 * before, after.max)

  " In this case, garbage collecting is not needed.
  " The value might fluctuate a bit, allow for 3% tolerance below and 5% above.
  " Based on various test runs.
  let lower = after.last * 97 / 100
  let upper = after.last * 105 / 100
  call assert_inrange(lower, upper, after.max)

  call vim.stop()
endfunc

func Test_memory_func_capture_lvars()
  " Case: if a local variable captures l: dict, funccall object will not be
  " free until garbage collector runs, but after that memory usage doesn't
  " increase so much even when rerun Xtest.vim since system memory caches.
  let testfile = 'Xtest.vim'
  let lines =<< trim END
        func s:f()
          let x = l:
        endfunc
        for _ in range(10000)
          call s:f()
        endfor
  END
  call writefile(lines, testfile, 'D')

  let vim = s:vim_new()
  call vim.start('--clean', '-c', 'set noswapfile', testfile)
  let before = s:monitor_memory_usage(vim.pid).last

  call term_sendkeys(vim.buf, ":so %\<CR>")
  call WaitFor({-> term_getcursor(vim.buf)[0] == 1})
  let after = s:monitor_memory_usage(vim.pid)

  " Rerun Xtest.vim.
  for _ in range(3)
    call term_sendkeys(vim.buf, ":so %\<CR>")
    call WaitFor({-> term_getcursor(vim.buf)[0] == 1})
    let last = s:monitor_memory_usage(vim.pid).last
  endfor

  " The usage may be a bit less than the last value, use 80%.
  " Allow for 20% tolerance at the upper limit.  That's very permissive, but
  " otherwise the test fails sometimes.  On Cirrus CI with FreeBSD we need to
  " be even much more permissive.
  if has('bsd')
    let multiplier = 19
  else
    let multiplier = 12
  endif
  let lower = before * 8 / 10
  let upper = (after.max + (after.last - before)) * multiplier / 10
  call assert_inrange(lower, upper, last)

  call vim.stop()
endfunc

" vim: shiftwidth=2 sts=2 expandtab