Skip to content

Commit

Permalink
Profile: make heap snapshots viewable in vscode viewer (JuliaLang#53833)
Browse files Browse the repository at this point in the history
  • Loading branch information
IanButterworth committed Apr 5, 2024
1 parent e64fa86 commit 57bbff6
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 13 deletions.
24 changes: 21 additions & 3 deletions src/gc-heap-snapshot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,9 @@ void _record_gc_just_edge(const char *edge_type, size_t from_idx, size_t to_idx,
void final_serialize_heap_snapshot(ios_t *json, ios_t *strings, HeapSnapshot &snapshot, char all_one)
{
// mimicking https://github.com/nodejs/node/blob/5fd7a72e1c4fbaf37d3723c4c81dce35c149dc84/deps/v8/src/profiler/heap-snapshot-generator.cc#L2567-L2567
// also https://github.com/microsoft/vscode-v8-heap-tools/blob/c5b34396392397925ecbb4ecb904a27a2754f2c1/v8-heap-parser/src/decoder.rs#L43-L51
ios_printf(json, "{\"snapshot\":{");

ios_printf(json, "\"meta\":{");
ios_printf(json, "\"node_fields\":[\"type\",\"name\",\"id\",\"self_size\",\"edge_count\",\"trace_node_id\",\"detachedness\"],");
ios_printf(json, "\"node_types\":[");
Expand All @@ -617,10 +619,26 @@ void final_serialize_heap_snapshot(ios_t *json, ios_t *strings, HeapSnapshot &sn
ios_printf(json, "\"edge_types\":[");
snapshot.edge_types.print_json_array(json, false);
ios_printf(json, ",");
ios_printf(json, "\"string_or_number\",\"from_node\"]");
ios_printf(json, "\"string_or_number\",\"from_node\"],");
// not used. Required by microsoft/vscode-v8-heap-tools
ios_printf(json, "\"trace_function_info_fields\":[\"function_id\",\"name\",\"script_name\",\"script_id\",\"line\",\"column\"],");
ios_printf(json, "\"trace_node_fields\":[\"id\",\"function_info_index\",\"count\",\"size\",\"children\"],");
ios_printf(json, "\"sample_fields\":[\"timestamp_us\",\"last_assigned_id\"],");
ios_printf(json, "\"location_fields\":[\"object_index\",\"script_id\",\"line\",\"column\"]");
// end not used
ios_printf(json, "},\n"); // end "meta"

ios_printf(json, "\"node_count\":%zu,", snapshot.num_nodes);
ios_printf(json, "\"edge_count\":%zu", snapshot.num_edges);
ios_printf(json, "}\n"); // end "snapshot"
ios_printf(json, "\"edge_count\":%zu,", snapshot.num_edges);
ios_printf(json, "\"trace_function_count\":0"); // not used. Required by microsoft/vscode-v8-heap-tools
ios_printf(json, "},\n"); // end "snapshot"

// not used. Required by microsoft/vscode-v8-heap-tools
ios_printf(json, "\"trace_function_infos\":[],");
ios_printf(json, "\"trace_tree\":[],");
ios_printf(json, "\"samples\":[],");
ios_printf(json, "\"locations\":[]");
// end not used

ios_printf(json, "}");
}
13 changes: 7 additions & 6 deletions stdlib/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

julia_version = "1.12.0-DEV"
manifest_format = "2.0"
project_hash = "13f2dd600364a1e8b659dc5796bf185b37d1c95d"
project_hash = "d3a1f6b706609fe0c59521e1d770be6e2b8c489d"

[[deps.ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
Expand All @@ -23,7 +23,7 @@ version = "1.11.0"
[[deps.CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
version = "1.1.0+0"
version = "1.1.1+0"

[[deps.Dates]]
deps = ["Printf"]
Expand Down Expand Up @@ -113,7 +113,7 @@ version = "1.11.0+1"
[[deps.LibUV_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "183b4373-6708-53ba-ad28-60e28bb38547"
version = "2.0.1+15"
version = "2.0.1+16"

[[deps.LibUnwind_jll]]
deps = ["Artifacts", "Libdl"]
Expand Down Expand Up @@ -155,7 +155,7 @@ version = "1.11.0"

[[deps.MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
version = "2023.12.12"
version = "2024.3.11"

[[deps.NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
Expand All @@ -177,9 +177,9 @@ uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15"
version = "10.43.0+0"

[[deps.Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
version = "1.11.0"
version = "1.12.0"
weakdeps = ["REPL"]

[deps.Pkg.extensions]
Expand All @@ -191,6 +191,7 @@ uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
version = "1.11.0"

[[deps.Profile]]
deps = ["Unicode"]
uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79"
version = "1.11.0"

Expand Down
6 changes: 6 additions & 0 deletions stdlib/Profile/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ name = "Profile"
uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79"
version = "1.11.0"

[deps]
Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"

[compat]
Unicode = "1.11.0"

[extras]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
Expand Down
1 change: 1 addition & 0 deletions stdlib/Profile/src/Profile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,7 @@ function take_heap_snapshot(filepath::AbstractString, all_one::Bool=false; strea
prefix = filepath
_stream_heap_snapshot(prefix, all_one)
Profile.HeapSnapshot.assemble_snapshot(prefix, filepath)
Profile.HeapSnapshot.cleanup_streamed_files(prefix)
end
return filepath
end
Expand Down
26 changes: 22 additions & 4 deletions stdlib/Profile/src/heapsnapshot_reassemble.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

module HeapSnapshot

using Unicode

"""
assemble_snapshot(filepath::AbstractString, out_file::AbstractString)
Expand Down Expand Up @@ -92,7 +94,7 @@ function assemble_snapshot(in_prefix, io::IO)
node_count = parse(Int, String(@view preamble[pos:endpos]))

pos = last(findnext("edge_count\":", preamble, endpos)) + 1
endpos = findnext(==('}'), preamble, pos) - 1
endpos = findnext(==(','), preamble, pos) - 1
edge_count = parse(Int, String(@view preamble[pos:endpos]))

nodes = Nodes(node_count, edge_count)
Expand Down Expand Up @@ -137,7 +139,8 @@ function assemble_snapshot(in_prefix, io::IO)
end

_digits_buf = zeros(UInt8, ndigits(typemax(UInt)))
println(io, @view(preamble[1:end-2]), ",") # remove trailing "}\n", we don't end the snapshot here
println(io, @view(preamble[1:end-1]), ",") # remove trailing "}" to reopen the object

println(io, "\"nodes\":[")
for i in 1:length(nodes)
i > 1 && println(io, ",")
Expand Down Expand Up @@ -182,12 +185,11 @@ function assemble_snapshot(in_prefix, io::IO)
str_bytes = read(strings_io, str_size)
str = String(str_bytes)
if first
print_str_escape_json(io, str)
first = false
else
print(io, ",\n")
print_str_escape_json(io, str)
end
print_str_escape_json(io, str)
end
end
print(io, "]}")
Expand All @@ -202,6 +204,19 @@ function assemble_snapshot(in_prefix, io::IO)
return nothing
end

"""
cleanup_streamed_files(prefix::AbstractString)
Remove files streamed during `take_heap_snapshot` in streaming mode.
"""
function cleanup_streamed_files(prefix::AbstractString)
rm(string(prefix, ".metadata.json"))
rm(string(prefix, ".nodes"))
rm(string(prefix, ".edges"))
rm(string(prefix, ".strings"))
return nothing
end

function print_str_escape_json(stream::IO, s::AbstractString)
print(stream, '"')
for c in s
Expand All @@ -221,6 +236,9 @@ function print_str_escape_json(stream::IO, s::AbstractString)
print(stream, "\\t")
elseif '\x00' <= c <= '\x1f'
print(stream, "\\u", lpad(string(UInt16(c), base=16), 4, '0'))
elseif !Unicode.isassigned(c)
# we have to do this because vscode's viewer doesn't like the replace character
print(stream, "[invalid unicode character]")
else
print(stream, c)
end
Expand Down

0 comments on commit 57bbff6

Please sign in to comment.