Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions lib/reach/project.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,20 @@ defmodule Reach.Project do
nodes: %{IR.Node.id() => IR.Node.t()},
call_graph: Graph.t(),
summaries: %{{module(), atom(), non_neg_integer()} => map()},
plugins: [module()]
plugins: [module()],
cache_key: reference() | nil
}

@enforce_keys [:modules, :graph, :nodes, :call_graph]
defstruct [:modules, :graph, :nodes, :call_graph, summaries: %{}, plugins: []]
defstruct [
:modules,
:graph,
:nodes,
:call_graph,
summaries: %{},
plugins: [],
cache_key: nil
]

@doc """
Builds a project graph from source file paths.
Expand Down Expand Up @@ -312,7 +321,8 @@ defmodule Reach.Project do
graph: Graph.new(type: :directed),
nodes: nodes,
call_graph: Graph.new(type: :directed),
plugins: plugins
plugins: plugins,
cache_key: make_ref()
}
end

Expand Down Expand Up @@ -403,7 +413,8 @@ defmodule Reach.Project do
nodes: merged_nodes,
call_graph: merged_call_graph,
summaries: summaries,
plugins: plugins
plugins: plugins,
cache_key: make_ref()
}
end

Expand Down
19 changes: 17 additions & 2 deletions lib/reach/project/query.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,24 @@ defmodule Reach.Project.Query do

alias Reach.IR.Helpers, as: IRHelpers

def function_index(project), do: build_function_index(project)
@function_index_cache_key {__MODULE__, :function_index}

def reset_cache, do: :ok
def function_index(%{cache_key: key} = project) do
case Process.get(@function_index_cache_key) do
{^key, index} ->
index

_miss ->
index = build_function_index(project)
Process.put(@function_index_cache_key, {key, index})
index
end
end

def reset_cache do
Process.delete(@function_index_cache_key)
:ok
end

def find_function(project, target) do
index = function_index(project)
Expand Down
19 changes: 19 additions & 0 deletions test/reach/project/query_cache_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@ defmodule Reach.Project.QueryCacheTest do
refute Query.find_function(second, {FirstOnly, :run, 0})
end

test "function_index is memoized within a process for the same project" do
project = project_with("Memoized", "go")

first = Query.function_index(project)
second = Query.function_index(project)

assert :erts_debug.same(first, second)
end

test "reset_cache invalidates the cached function index" do
project = project_with("Resettable", "do_thing")

first = Query.function_index(project)
Query.reset_cache()
second = Query.function_index(project)

refute :erts_debug.same(first, second)
end

defp project_with(module, function) do
source = """
defmodule #{module} do
Expand Down