Skip to content

Commit 459f1da

Browse files
committed
Make the traversal cache lazy (no need to create an empty Dict every time)
1 parent b8462ce commit 459f1da

3 files changed

Lines changed: 23 additions & 11 deletions

File tree

src/compute_MTG/caching.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,19 @@ function cache_nodes!(node; scale=nothing, symbol=nothing, link=nothing, filter_
5757
symbol = normalize_symbol_filter(symbol)
5858
link = normalize_link_filter(link)
5959
# The cache is already present:
60-
if length(node_traversal_cache(node)) != 0 && haskey(node_traversal_cache(node), cache_name(scale, symbol, link, all, filter_fun))
60+
cache_key = cache_name(scale, symbol, link, all, filter_fun)
61+
cache = _maybe_traversal_cache(node)
62+
if cache !== nothing && !isempty(cache) && haskey(cache, cache_key)
6163
if !overwrite
6264
error("The node already has a cache for this combination of filters. Hint: use `overwrite=true` if needed.")
6365
else
6466
# We have to delete the cache first because else it would be used in the traversal below:
65-
delete!(node_traversal_cache(node), cache_name(scale, symbol, link, all, filter_fun))
67+
delete!(cache, cache_key)
6668
end
6769
end
6870

69-
node_traversal_cache(node)[cache_name(scale, symbol, link, all, filter_fun)] = traverse(
71+
cache = node_traversal_cache(node)
72+
cache[cache_key] = traverse(
7073
node,
7174
node -> node,
7275
scale=scale, symbol=symbol, link=link, filter_fun=filter_fun, all=all

src/compute_MTG/traverse.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ function traverse!(node::Node, f::Function, args...; scale=nothing, symbol=nothi
113113
link = normalize_link_filter(link)
114114

115115
# If the node has already a cache of the traversal, we use it instead of traversing the mtg:
116-
cache = node_traversal_cache(node)
117-
if !isempty(cache)
116+
cache = _maybe_traversal_cache(node)
117+
if cache !== nothing && !isempty(cache)
118118
cache_key = cache_name(scale, symbol, link, all, filter_fun)
119119
cached_nodes = get(cache, cache_key, nothing)
120120
if cached_nodes !== nothing
@@ -172,8 +172,8 @@ function traverse(node::Node, f::Function, args...; scale=nothing, symbol=nothin
172172
# NB: f has to return someting here, if its a mutating function, use traverse!
173173

174174
# If the node has already a cache of the traversal, we use it instead of traversing the mtg:
175-
cache = node_traversal_cache(node)
176-
if !isempty(cache)
175+
cache = _maybe_traversal_cache(node)
176+
if cache !== nothing && !isempty(cache)
177177
cache_key = cache_name(scale, symbol, link, all, filter_fun)
178178
cached_nodes = get(cache, cache_key, nothing)
179179

src/types/Node.jl

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ mutable struct Node{N<:AbstractNodeMTG,A}
5555
"Node attributes. Can be anything really"
5656
attributes::A
5757
"Cache for mtg nodes traversal"
58-
traversal_cache::Dict{String,Vector{Node{N,A}}}
58+
traversal_cache::Union{Nothing,Dict{String,Vector{Node{N,A}}}}
5959
end
6060

6161
# All deprecated methods (the ones with a node name) :
@@ -68,7 +68,7 @@ end
6868

6969
function Node(id::Int, MTG::T, attributes::ColumnarAttrs) where {T<:AbstractNodeMTG}
7070
node = Node{T,ColumnarAttrs}(
71-
id, nothing, Vector{Node{T,ColumnarAttrs}}(), MTG, attributes, Dict{String,Vector{Node{T,ColumnarAttrs}}}()
71+
id, nothing, Vector{Node{T,ColumnarAttrs}}(), MTG, attributes, nothing
7272
)
7373
init_columnar_root!(attributes, id, getfield(MTG, :symbol))
7474
return node
@@ -101,7 +101,7 @@ end
101101

102102
function Node(id::Int, parent::Node{M,ColumnarAttrs}, MTG::M, attributes::ColumnarAttrs) where {M<:AbstractNodeMTG}
103103
node = Node{M,ColumnarAttrs}(
104-
id, parent, Vector{Node{M,ColumnarAttrs}}(), MTG, attributes, Dict{String,Vector{Node{M,ColumnarAttrs}}}()
104+
id, parent, Vector{Node{M,ColumnarAttrs}}(), MTG, attributes, nothing
105105
)
106106
addchild!(parent, node)
107107
bind_columnar_child!(node_attributes(parent), attributes, id, getfield(MTG, :symbol))
@@ -517,7 +517,16 @@ Base.names(mtg::T) where {T<:MultiScaleTreeGraph.Node} = get_attributes(mtg)
517517
518518
Get the traversal cache of the node if any.
519519
"""
520-
node_traversal_cache(node::Node) = getfield(node, :traversal_cache)
520+
@inline _maybe_traversal_cache(node::Node) = getfield(node, :traversal_cache)
521+
522+
function node_traversal_cache(node::Node{T,A}) where {T,A}
523+
cache = getfield(node, :traversal_cache)
524+
if cache === nothing
525+
cache = Dict{String,Vector{Node{T,A}}}()
526+
setfield!(node, :traversal_cache, cache)
527+
end
528+
return cache
529+
end
521530

522531
Base.getproperty(node::Node, key::Symbol) = unsafe_getindex(node, key)
523532
Base.hasproperty(node::Node, key::Symbol) = haskey(node_attributes(node), key)

0 commit comments

Comments
 (0)