Skip to content

Commit 02d3b2e

Browse files
committed
Change data model in references tracer
Avoid querying ETS on every trace Fixes #772
1 parent f02c97a commit 02d3b2e

File tree

2 files changed

+27
-115
lines changed

2 files changed

+27
-115
lines changed

apps/language_server/lib/language_server/tracer.ex

Lines changed: 18 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ defmodule ElixirLS.LanguageServer.Tracer do
44
use GenServer
55
require Logger
66

7-
@version 1
7+
@version 2
88

99
@tables ~w(modules calls)a
1010

@@ -180,12 +180,14 @@ defmodule ElixirLS.LanguageServer.Tracer do
180180
def trace(:start, %Macro.Env{} = env) do
181181
delete_modules_by_file(env.file)
182182
delete_calls_by_file(env.file)
183+
183184
:ok
184185
end
185186

186187
def trace({:on_module, _, _}, %Macro.Env{} = env) do
187188
info = build_module_info(env.module, env.file, env.line)
188189
:ets.insert(table_name(:modules), {env.module, info})
190+
189191
:ok
190192
end
191193

@@ -256,37 +258,24 @@ defmodule ElixirLS.LanguageServer.Tracer do
256258
defp do_register_call(meta, module, name, arity, env) do
257259
callee = {module, name, arity}
258260

259-
call = %{
260-
callee: callee,
261-
file: env.file,
262-
line: meta[:line],
263-
column: meta[:column]
264-
}
265-
266-
updated_calls =
267-
case :ets.lookup(table_name(:calls), callee) do
268-
[{_callee, callee_calls}] when is_map(callee_calls) ->
269-
file_calle_calls =
270-
case callee_calls[env.file] do
271-
nil -> [call]
272-
file_calle_calls -> [call | file_calle_calls]
273-
end
274-
275-
Map.put(callee_calls, env.file, file_calle_calls)
261+
line = meta[:line]
262+
column = meta[:column]
276263

277-
[] ->
278-
%{env.file => [call]}
279-
end
280-
281-
:ets.insert(table_name(:calls), {callee, updated_calls})
264+
:ets.insert(table_name(:calls), {{callee, env.file, line, column}, :ok})
282265
end
283266

284267
def get_trace do
268+
# TODO get by calee
285269
:ets.tab2list(table_name(:calls))
286-
|> Map.new(fn {callee, calls_by_file} ->
287-
calls = calls_by_file |> Map.values() |> List.flatten()
288-
{callee, calls}
270+
|> Enum.map(fn {{callee, file, line, column}, _} ->
271+
%{
272+
callee: callee,
273+
file: file,
274+
line: line,
275+
column: column
276+
}
289277
end)
278+
|> Enum.group_by(fn %{callee: callee} -> callee end)
290279
end
291280

292281
defp sync(table_name) do
@@ -317,13 +306,7 @@ defmodule ElixirLS.LanguageServer.Tracer do
317306

318307
defp calls_by_file_matchspec(file, return) do
319308
[
320-
{{:"$1", :"$2"},
321-
[
322-
{
323-
:andalso,
324-
{:andalso, {:is_list, {:map_get, file, :"$2"}}}
325-
}
326-
], [return]}
309+
{{{:_, :"$1", :_, :_}, :_}, [{:==, :"$1", file}], [return]}
327310
]
328311
end
329312

@@ -334,18 +317,9 @@ defmodule ElixirLS.LanguageServer.Tracer do
334317
end
335318

336319
def delete_calls_by_file(file) do
337-
ms = calls_by_file_matchspec(file, :"$_")
338-
table_name = table_name(:calls)
320+
ms = calls_by_file_matchspec(file, true)
339321

340-
for {callee, calls_by_file} <- :ets.select(table_name(:calls), ms) do
341-
calls_by_file = calls_by_file |> Map.delete(file)
342-
343-
if calls_by_file == %{} do
344-
:ets.delete(table_name, callee)
345-
else
346-
:ets.insert(table_name, {callee, calls_by_file})
347-
end
348-
end
322+
:ets.select_delete(table_name(:calls), ms)
349323
end
350324

351325
defp manifest_path(project_dir) do

apps/language_server/test/tracer_test.exs

Lines changed: 9 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ defmodule ElixirLS.LanguageServer.TracerTest do
4141
end
4242

4343
defp sorted_calls() do
44-
:ets.tab2list(:"#{Tracer}:calls") |> Enum.sort()
44+
:ets.tab2list(:"#{Tracer}:calls") |> Enum.map(&(&1 |> elem(0))) |> Enum.sort()
4545
end
4646

4747
test "trace is empty" do
@@ -66,25 +66,8 @@ defmodule ElixirLS.LanguageServer.TracerTest do
6666
)
6767

6868
assert [
69-
{{CalledModule, :called, 1},
70-
%{
71-
"calling_module.ex" => [
72-
%{
73-
callee: {CalledModule, :called, 1},
74-
column: 2,
75-
file: "calling_module.ex",
76-
line: 12
77-
}
78-
],
79-
"other_calling_module.ex" => [
80-
%{
81-
callee: {CalledModule, :called, 1},
82-
column: 3,
83-
file: "other_calling_module.ex",
84-
line: 13
85-
}
86-
]
87-
}}
69+
{{CalledModule, :called, 1}, "calling_module.ex", 12, 2},
70+
{{CalledModule, :called, 1}, "other_calling_module.ex", 13, 3}
8871
] == sorted_calls()
8972
end
9073

@@ -106,23 +89,8 @@ defmodule ElixirLS.LanguageServer.TracerTest do
10689
)
10790

10891
assert [
109-
{{CalledModule, :called, 1},
110-
%{
111-
"calling_module.ex" => [
112-
%{
113-
callee: {CalledModule, :called, 1},
114-
column: 3,
115-
file: "calling_module.ex",
116-
line: 13
117-
},
118-
%{
119-
callee: {CalledModule, :called, 1},
120-
column: 2,
121-
file: "calling_module.ex",
122-
line: 12
123-
}
124-
]
125-
}}
92+
{{CalledModule, :called, 1}, "calling_module.ex", 12, 2},
93+
{{CalledModule, :called, 1}, "calling_module.ex", 13, 3}
12694
] == sorted_calls()
12795
end
12896

@@ -144,28 +112,8 @@ defmodule ElixirLS.LanguageServer.TracerTest do
144112
)
145113

146114
assert [
147-
{{CalledModule, :called, 1},
148-
%{
149-
"calling_module.ex" => [
150-
%{
151-
callee: {CalledModule, :called, 1},
152-
column: 2,
153-
file: "calling_module.ex",
154-
line: 12
155-
}
156-
]
157-
}},
158-
{{CalledModule, :other_called, 1},
159-
%{
160-
"other_calling_module.ex" => [
161-
%{
162-
callee: {CalledModule, :other_called, 1},
163-
column: 3,
164-
file: "other_calling_module.ex",
165-
line: 13
166-
}
167-
]
168-
}}
115+
{{CalledModule, :called, 1}, "calling_module.ex", 12, 2},
116+
{{CalledModule, :other_called, 1}, "other_calling_module.ex", 13, 3}
169117
] == sorted_calls()
170118
end
171119

@@ -189,17 +137,7 @@ defmodule ElixirLS.LanguageServer.TracerTest do
189137
Tracer.delete_calls_by_file("other_calling_module.ex")
190138

191139
assert [
192-
{{CalledModule, :called, 1},
193-
%{
194-
"calling_module.ex" => [
195-
%{
196-
callee: {CalledModule, :called, 1},
197-
column: 2,
198-
file: "calling_module.ex",
199-
line: 12
200-
}
201-
]
202-
}}
140+
{{CalledModule, :called, 1}, "calling_module.ex", 12, 2}
203141
] == sorted_calls()
204142

205143
Tracer.delete_calls_by_file("calling_module.ex")
@@ -218,7 +156,7 @@ defmodule ElixirLS.LanguageServer.TracerTest do
218156
project_path = FixtureHelpers.get_path("")
219157
Tracer.write_manifest(project_path)
220158

221-
assert 1 == Tracer.read_manifest(project_path)
159+
assert 2 == Tracer.read_manifest(project_path)
222160
end
223161
end
224162
end

0 commit comments

Comments
 (0)