From 4a246ea74cc0ec2a20e8b14ccb7bb8219f3a54a1 Mon Sep 17 00:00:00 2001 From: glepnir Date: Mon, 26 Aug 2024 17:37:02 +0800 Subject: [PATCH] perf: add benchmarkk --- bench/get_line.lua | 49 +++++++++++++++++++++++++++++++++++++++++ bench/space_or_tab.lua | 8 +++---- lua/indentmini/init.lua | 4 ++-- 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 bench/get_line.lua diff --git a/bench/get_line.lua b/bench/get_line.lua new file mode 100644 index 0000000..bf74e91 --- /dev/null +++ b/bench/get_line.lua @@ -0,0 +1,49 @@ +local ffi = require('ffi') +local api = vim.api + +-- FFI definition for ml_get +ffi.cdef([[ + typedef int32_t linenr_T; + char *ml_get(linenr_T lnum); +]]) + +local C = ffi.C + +-- Function to get line using ml_get +local function get_line_with_ml_get(lnum) + return ffi.string(C.ml_get(lnum)) +end + +-- Function to get line using api.nvim_buf_get_lines +local function get_line_with_api(bufnr, lnum) + return api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1] +end + +-- Benchmark function +local function benchmark(func, bufnr, lnum, iterations) + local start_time = vim.uv.hrtime() + for _ = 1, iterations do + func(bufnr, lnum) + end + local end_time = vim.uv.hrtime() + return (end_time - start_time) / iterations +end + +-- Example usage +local bufnr = api.nvim_get_current_buf() +vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, { ('text '):rep(100) }) +local lnum = 1 +local iterations = 10000 + +-- Warm up +get_line_with_ml_get(lnum) +get_line_with_api(bufnr, lnum) + +-- Run benchmarks +local time_ml_get = benchmark(function(_, lnum) + return get_line_with_ml_get(lnum) +end, bufnr, lnum, iterations) +local time_api = benchmark(get_line_with_api, bufnr, lnum, iterations) + +print(string.format('ml_get: %.3f ns per call', time_ml_get)) +print(string.format('api.nvim_buf_get_lines: %.3f ns per call', time_api)) diff --git a/bench/space_or_tab.lua b/bench/space_or_tab.lua index b23351c..de791d2 100644 --- a/bench/space_or_tab.lua +++ b/bench/space_or_tab.lua @@ -1,7 +1,7 @@ local function only_spaces_or_tabs(text) for i = 1, #text do - local c = text:sub(i, i) - if c ~= ' ' and c ~= '\t' then + local byte = string.byte(text, i) + if byte ~= 32 and byte ~= 9 then -- 32 is space, 9 is tab return false end end @@ -30,5 +30,5 @@ local time2 = benchmark(only_spaces_or_tabs_regex, text, iterations) print('Time for only_spaces_or_tabs:', time1) print('Time for only_spaces_or_tabs_regex:', time2) --- Time for only_spaces_or_tabs: 0.07258 --- Time for only_spaces_or_tabs_regex: 0.093389 +-- Time for only_spaces_or_tabs: 0.027799 +-- Time for only_spaces_or_tabs_regex: 0.093943 diff --git a/lua/indentmini/init.lua b/lua/indentmini/init.lua index 8f13b90..6f049b1 100644 --- a/lua/indentmini/init.lua +++ b/lua/indentmini/init.lua @@ -43,8 +43,8 @@ local context = { snapshot = {} } --- @return boolean true only have space or tab local function only_spaces_or_tabs(text) for i = 1, #text do - local c = text:sub(i, i) - if c ~= ' ' and c ~= '\t' then + local byte = string.byte(text, i) + if byte ~= 32 and byte ~= 9 then -- 32 is space, 9 is tab return false end end