summaryrefslogtreecommitdiff
path: root/tests/profile.lua
blob: 5546d88785372b8c79e490ee1f141a968aacd2da (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
local script = debug.getinfo(1, "S").source:sub(2)
local root = script:match("^(.*)/tests/profile%.lua$") or "."
package.path = table.concat({
  root .. "/lua/?.lua",
  root .. "/lua/?/init.lua",
  package.path,
}, ";")

local destination_engine = require("clever_f.destination_engine")
local direct_preview_planner = require("clever_f.direct_preview_planner")
local domain = require("clever_f.domain")
local migemo_catalog = require("clever_f.migemo_catalog")
local motion_plan = require("clever_f.motion_plan")
local sequence_state = require("clever_f.sequence_state")
local state_transitions = require("clever_f.state_transitions")
local target_plan = require("clever_f.target_plan")
local text_topology = require("clever_f.text_topology")

local assertions = dofile(root .. "/tests/assertions.lua")
local same = assertions.same
local truthy = assertions.truthy

local clock = vim.uv or vim.loop

local function measure(body)
  collectgarbage("collect")
  local started = clock.hrtime()
  local result = body()
  return (clock.hrtime() - started) / 1000000, result
end

local transitions = state_transitions.new()
transitions:ClearTemporaryOverlays()
transitions:DiagnosticFullReset()

local candidate_count = 10000
local candidate_view = text_topology.new({ string.rep("a", candidate_count) }, "utf-8")
local candidate_evaluations = 0
local missing_target = domain.TargetPlan.new({
  target = domain.TargetValue.character("z", string.byte("z")),
  kind = domain.TargetPlanKind.LITERAL,
  case_mode = domain.CaseMode.SENSITIVE,
  matcher = function()
    candidate_evaluations = candidate_evaluations + 1
    return false
  end,
})
local candidate_ms, candidate_outcome = measure(function()
  return destination_engine.calculate(
    candidate_view,
    domain.Position.new(1, 1),
    motion_plan.build(missing_target, "f"),
    1,
    true
  )
end)
same(domain.SearchStatus.BOUNDARY_BEFORE_ANY, candidate_outcome.status)
same(candidate_count - 1, candidate_evaluations)

local preview_view = text_topology.new({ string.rep("ab", 5000) }, "utf-8")
local preview_ms, preview_positions = measure(function()
  return direct_preview_planner.plan(
    preview_view,
    domain.Position.new(1, 1),
    "f",
    2,
    { ignore_case = false, smart_case = false }
  )
end)
same(2, #preview_positions)
same(domain.Position.new(1, 4), preview_positions[1])
same(domain.Position.new(1, 5), preview_positions[2])

local catalog = migemo_catalog.new()
same(0, catalog:load_count("utf-8"))
local factory = target_plan.new({ migemo_catalog = catalog })
factory:build(
  domain.TargetValue.character("a", string.byte("a")),
  {
    ignore_case = false,
    smart_case = false,
    use_migemo = false,
    chars_match_any_signs = "",
  }
)
same(0, catalog:load_count("utf-8"))

local load_ms, dictionary = measure(function()
  return catalog:get("utf-8")
end)
same(1, catalog:load_count("utf-8"))
same(dictionary, catalog:get("utf8"))
same(1, catalog:load_count("utf-8"))

local assertion = dictionary:predicate("a", domain.CaseMode.SENSITIVE)
local assertion_count = 500
local assertion_ms, accepted = measure(function()
  local count = 0
  for _ = 1, assertion_count do
    if assertion("a") then
      count = count + 1
    end
  end
  return count
end)
same(assertion_count, accepted)

for _, encoding in ipairs({ "cp932", "euc-jp" }) do
  local first = catalog:get(encoding)
  same(first, catalog:get(encoding))
  same(1, catalog:load_count(encoding))
end
same(3, #sequence_state.get():to_table().migemo_cache)

local cleanup = transitions:PublicReset("window-1")
same(nil, cleanup.highlight_timer)
same(0, #sequence_state.get():to_table().migemo_cache)
local reloaded = catalog:get("utf-8")
truthy(reloaded ~= dictionary)
same(2, catalog:load_count("utf-8"))

io.stdout:write(string.format(
  "Phase 16 profile: candidates=%d %.3fms, direct=%d %.3fms, "
    .. "migemo-load=%.3fms, migemo-assertions=%d %.3fms\n",
  candidate_evaluations,
  candidate_ms,
  #preview_positions,
  preview_ms,
  load_ms,
  assertion_count,
  assertion_ms
))