Skip to content

Commit 62948a4

Browse files
authored
Merge pull request #8 from rafaqz/rs/performance
type stability and alloc reduction
2 parents 985f9e0 + a86dd7a commit 62948a4

File tree

3 files changed

+37
-22
lines changed

3 files changed

+37
-22
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
matrix:
2323
version:
2424
- '1.10'
25-
- '1.6'
25+
- '1'
2626
- 'nightly'
2727
os:
2828
- ubuntu-latest

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Extents = "411431e0-e8b7-467b-b5e0-f676ba4f2910"
88
GeoInterface = "cf35fbd7-0cd7-5166-be24-54bfbe79505f"
99

1010
[compat]
11-
julia = "1.6"
11+
julia = "1.10"
1212
Extents = "0.1.0"
1313
GeoInterface = "1"
1414

src/SortTileRecursiveTree.jl

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,27 @@ end
4545

4646

4747
function leafnodes(geoms; nodecapacity=10)
48-
extents_indices = [(GI.extent(geoms[i]), i) for i in eachindex(geoms)]
49-
perm = sortperm(extents_indices; by=(v -> ((v[1][1][1] + v[1][1][2]) / 2))) # [extent/index][dim][min/max] sort by x
50-
sorted_extents = extents_indices[perm]
51-
r = length(sorted_extents)
48+
ext1 = GI.extent(first(geoms))
49+
extents_indices = Tuple{typeof(ext1),Int}[(GI.extent(geoms[i]), i) for i in eachindex(geoms)]
50+
# Use the same scratch space for all sorts
51+
scratch = similar(extents_indices)
52+
sort!(extents_indices; by=v -> (v[1][1][1] + v[1][1][2]) / 2, scratch) # [extent/index][dim][min/max] sort by x
53+
r = length(extents_indices)
5254
P = ceil(Int, r / nodecapacity)
5355
S = ceil(Int, sqrt(P))
54-
x_splits = Iterators.partition(sorted_extents, S * nodecapacity)
56+
x_splits = Iterators.partition(extents_indices, S * nodecapacity)
5557

5658
nodes = STRLeafNode{Vector{typeof(extents_indices[1][1])}}[]
5759
for x_split in x_splits
58-
perm = sortperm(x_split; by=(v -> ((v[1][2][1] + v[1][2][2]) / 2))) # [extent/index][dim][min/max] sort by y
59-
sorted_split = x_split[perm]
60-
y_splits = Iterators.partition(sorted_split, nodecapacity)
60+
sort!(x_split;
61+
by=v -> (v[1][2][1] + v[1][2][2]) / 2, # [extent/index][dim][min/max] sort by y
62+
scratch=resize!(scratch, length(x_split)),
63+
)
64+
y_splits = Iterators.partition(x_split, nodecapacity)
6165
for y_split in y_splits
62-
push!(nodes, STRLeafNode(getindex.(y_split,1), getindex.(y_split,2)))
66+
exts = first.(y_split)::Vector{typeof(ext1)}
67+
inds = last.(y_split)::Vector{Int}
68+
push!(nodes, STRLeafNode(exts, inds))
6369
end
6470
end
6571
return nodes
@@ -68,26 +74,35 @@ end
6874

6975
# a bit of duplication...
7076
function parentnodes(nodes; nodecapacity=10)
71-
extents_indices = [(GI.extent(node), node) for node in nodes]
72-
perm = sortperm(extents_indices; by=(v -> ((v[1][1][1] + v[1][1][2]) / 2))) # [extent/node][dim][min/max] sort by x
73-
sorted_extents = extents_indices[perm]
74-
r = length(sorted_extents)
77+
n1 = first(nodes)
78+
ext1 = GI.extent(n1)
79+
extents_indices = Tuple{typeof(ext1),typeof(n1)}[(GI.extent(node), node) for node in nodes]
80+
scratch = similar(extents_indices)
81+
sort!(extents_indices; by=v -> (v[1][1][1] + v[1][1][2]) / 2, scratch) # [extent/node][dim][min/max] sort by x
82+
r = length(extents_indices)
7583
P = ceil(Int, r / nodecapacity)
7684
S = ceil(Int, sqrt(P))
77-
x_splits = Iterators.partition(sorted_extents, S * nodecapacity)
85+
x_splits = Iterators.partition(extents_indices, S * nodecapacity)
7886

7987
T = typeof(extents_indices[1][1])
8088
N = Vector{typeof(extents_indices[1][2])}
81-
nodes = STRNode{T, N}[]
89+
outnodes = STRNode{T, N}[]
8290
for x_split in x_splits
83-
perm = sortperm(x_split; by=(v -> ((v[1][2][1] + v[1][2][2]) / 2))) # [extent/index][dim][min/max] sort by y
84-
sorted_split = x_split[perm]
85-
y_splits = Iterators.partition(sorted_split, nodecapacity)
91+
sort!(x_split;
92+
by=v -> (v[1][2][1] + v[1][2][2]) / 2, # [extent/index][dim][min/max] sort by y
93+
scratch=resize!(scratch, length(x_split)),
94+
)
95+
y_splits = Iterators.partition(x_split, nodecapacity)
8696
for y_split in y_splits
87-
push!(nodes, STRNode(foldl(Extents.union, getindex.(y_split,1)), getindex.(y_split,2)))
97+
# Alloc free union over the extents
98+
ext = foldl(y_split; init=y_split[1][1]) do u, (ext, _)
99+
Extents.union(u, ext)
100+
end
101+
y_splitnodes = last.(y_split)::Vector{eltype(nodes)}
102+
push!(outnodes, STRNode(ext, y_splitnodes))
88103
end
89104
end
90-
return nodes
105+
return outnodes
91106
end
92107

93108

0 commit comments

Comments
 (0)