Skip to content

Commit 2faa6e1

Browse files
speed up serialize_testset_result_file
1 parent a901f67 commit 2faa6e1

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

test/buildkitetestjson.jl

+44-23
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ function generalize_file_paths(path::AbstractString)
104104
end
105105
end
106106

107+
# raw_file_path,line => file,location
108+
const location_cache = Dict{Tuple{Symbol,Int},Tuple{String,String}}()
109+
function get_location(file::Symbol, line::Int)
110+
return get!(location_cache, (file, line)) do
111+
_file = generalize_file_paths(string(file))
112+
_location = string(_file, ":", line)
113+
return _file, _location
114+
end
115+
end
116+
107117
# passed, failed, skipped, or unknown
108118
function get_status(result)
109119
if result isa Test.Pass && result.test_type === :skipped
@@ -140,24 +150,31 @@ end
140150

141151
get_rid(rdata) = (rdata["location"], rdata["result"], haskey(rdata, "failure_expanded") ? hash(rdata["failure_expanded"]) : UInt64(0))
142152

143-
function result_dict(result::Test.Result, result_counts::Dict{Tuple{String,String,UInt64},Int})
153+
const ResultCountDict = Dict{Tuple{String,String,UInt64},Int}
154+
155+
function is_duplicate_pass(result::Test.Pass, location, status, result_counts::ResultCountDict)
156+
rid = (location, status, UInt64(0))
157+
count = get(result_counts, rid, nothing)
158+
if count !== nothing
159+
result_counts[rid] = count + 1
160+
return true
161+
end
162+
return false
163+
end
164+
is_duplicate_pass(result::Test.Result, location, status, result_counts::ResultCountDict) = false
165+
166+
function result_dict(result::Test.Result, result_counts::ResultCountDict)
144167
file, line = if !hasproperty(result, :source) || isnothing(result.source)
145-
"unknown", 0
168+
:unknown, 0
146169
else
147-
something(result.source.file, "unknown"), result.source.line
170+
something(result.source.file, :unknown), result.source.line
148171
end
149-
file = generalize_file_paths(string(file))
150-
location = string(file, ':', line)
172+
file, location = get_location(file, line)
151173
status = get_status(result)
152174

153175
# Early exit for passed tests before more expensive operations
154-
if result isa Test.Pass
155-
rid = (location, status, UInt64(0))
156-
duplicate = haskey(result_counts, rid)
157-
if duplicate
158-
result_counts[rid] += 1
159-
return nothing
160-
end
176+
if is_duplicate_pass(result, location, status, result_counts)
177+
return nothing
161178
end
162179

163180
data = Dict{String,Any}(
@@ -193,23 +210,27 @@ function result_dict(result::Test.Result, result_counts::Dict{Tuple{String,Strin
193210
end
194211
end
195212

213+
function collect_results!(results::Vector{Dict{String,Any}}, result::Test.Result, common_data::Dict{String,Any}, result_counts::ResultCountDict)
214+
rdata = result_dict(result, result_counts)
215+
if rdata !== nothing # nothing if it's a duplicate that's been counted
216+
push!(results, merge(common_data, rdata))
217+
end
218+
end
219+
220+
function collect_results!(results::Vector{Dict{String,Any}}, result::Test.DefaultTestSet, common_data::Dict{String,Any}, result_counts::ResultCountDict)
221+
collect_results!(results, result, common_data["scope"])
222+
end
223+
196224
function collect_results!(results::Vector{Dict{String,Any}}, testset::Test.DefaultTestSet, prefix::String="")
197225
common_data = result_dict(testset, prefix)
198226
# testset duration is not relevant for individual test results
199227
common_data["history"]["duration"] = 0.0 # required field
200228
delete!(common_data["history"], "end_at")
201229
result_offset = length(results) + 1
202-
result_counts = Dict{Tuple{String,String,UInt64},Int}()
230+
result_counts = ResultCountDict()
203231

204-
for (i, result) in enumerate(testset.results)
205-
if result isa Test.Result
206-
rdata = result_dict(result, result_counts)
207-
if rdata !== nothing # nothing if it's a duplicate that's been counted
208-
push!(results, merge(common_data, rdata))
209-
end
210-
elseif result isa Test.DefaultTestSet
211-
collect_results!(results, result, common_data["scope"])
212-
end
232+
for result in testset.results
233+
collect_results!(results, result, common_data, result_counts)
213234
end
214235
# Add a tag for count of each result
215236
for result in results[result_offset:end]
@@ -229,7 +250,7 @@ function serialize_testset_result_file(dir::String, testset::Test.DefaultTestSet
229250
res_file = joinpath(dir, "results_$(name).dat")
230251
t = @elapsed Serialization.serialize(res_file, data)
231252
if t > 10
232-
@warn "Serializing test result data was slow: $t seconds" file=res_file size=Base.format_bytes(filesize(res_file))
253+
@warn "Serializing test result data was slow: $t seconds" file = res_file size = Base.format_bytes(filesize(res_file))
233254
end
234255
return res_file
235256
end

0 commit comments

Comments
 (0)