mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	 3734519e3b
			
		
	
	3734519e3b
	
	
	
		
			
			Problem: Currently `deepcopy` hashes every single tables it copies so it can be reused. For tables of mostly unique items that are non recursive, this hashing is unnecessarily expensive Solution: Port the `noref` argument from Vimscripts `deepcopy()`. The below benchmark demonstrates the results for two extreme cases of tables of different sizes. One table that uses the same table lots of times and one with all unique tables. | test | `noref=false` (ms) | `noref=true` (ms) | | -------------------- | ------------------ | ----------------- | | unique tables (50) | 6.59 | 2.62 | | shared tables (50) | 3.24 | 6.40 | | unique tables (2000) | 23381.48 | 2884.53 | | shared tables (2000) | 3505.54 | 14038.80 | The results are basically the inverse of each other where `noref` is much more performance on tables with unique fields, and `not noref` is more performant on tables that reuse fields.
		
			
				
	
	
		
			59 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			59 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local N = 20
 | |
| 
 | |
| local function tcall(f, ...)
 | |
|   local ts = vim.uv.hrtime()
 | |
|   for _ = 1, N do
 | |
|     f(...)
 | |
|   end
 | |
|   return ((vim.uv.hrtime() - ts) / 1000000) / N
 | |
| end
 | |
| 
 | |
| local function build_shared(n)
 | |
|   local t = {}
 | |
|   local a = {}
 | |
|   local b = {}
 | |
|   local c = {}
 | |
|   for _ = 1, n do
 | |
|     t[#t + 1] = {}
 | |
|     local tl = t[#t]
 | |
|     for _ = 1, n do
 | |
|       tl[#tl + 1] = a
 | |
|       tl[#tl + 1] = b
 | |
|       tl[#tl + 1] = c
 | |
|     end
 | |
|   end
 | |
|   return t
 | |
| end
 | |
| 
 | |
| local function build_unique(n)
 | |
|   local t = {}
 | |
|   for _ = 1, n do
 | |
|     t[#t + 1] = {}
 | |
|     local tl = t[#t]
 | |
|     for _ = 1, n do
 | |
|       tl[#tl + 1] = {}
 | |
|     end
 | |
|   end
 | |
|   return t
 | |
| end
 | |
| 
 | |
| describe('vim.deepcopy()', function()
 | |
|   local function run(name, n, noref)
 | |
|     it(string.format('%s entries=%d noref=%s', name, n, noref), function()
 | |
|       local t = name == 'shared' and build_shared(n) or build_unique(n)
 | |
|       local d = tcall(vim.deepcopy, t, noref)
 | |
|       print(string.format('%.2f ms', d))
 | |
|     end)
 | |
|   end
 | |
| 
 | |
|   run('unique', 50, false)
 | |
|   run('unique', 50, true)
 | |
|   run('unique', 2000, false)
 | |
|   run('unique', 2000, true)
 | |
| 
 | |
|   run('shared', 50, false)
 | |
|   run('shared', 50, true)
 | |
|   run('shared', 2000, false)
 | |
|   run('shared', 2000, true)
 | |
| end)
 |