From 896b367ad01ffa27637567af8fb722b9a379b972 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 29 Oct 2018 12:00:07 +0100 Subject: [cdv] Speed up reading of dump with many processes Eliminate an ets:select per process, which was used for reading position data needed for progress reporting. Now this data is stored in dictionary along with the last tag and id instead. --- lib/observer/src/crashdump_viewer.erl | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'lib/observer') diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index 2a5c3bb1f9..41a569c2bf 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -580,9 +580,9 @@ truncated_here(Tag) -> case get(truncated) of true -> case get(last_tag) of - Tag -> % Tag == {TagType,Id} + {Tag,_Pos} -> % Tag == {TagType,Id} true; - {Tag,_Id} -> + {{Tag,_Id},_Pos} -> true; _LastTag -> truncated_earlier(Tag) @@ -837,8 +837,8 @@ do_read_file(File) -> case check_dump_version(Id) of {ok,DumpVsn} -> reset_tables(), - insert_index(Tag,Id,N1+1), - put_last_tag(Tag,""), + insert_index(Tag,Id,Pos=N1+1), + put_last_tag(Tag,"",Pos), DecodeOpts = get_decode_opts(DumpVsn), indexify(Fd,DecodeOpts,Rest,N1), end_progress(), @@ -906,12 +906,10 @@ indexify(Fd,DecodeOpts,Bin,N) -> _ -> insert_index(Tag,Id,NewPos) end, - case put_last_tag(Tag,Id) of - {?proc_heap,LastId} -> - [{_,LastPos}] = lookup_index(?proc_heap,LastId), + case put_last_tag(Tag,Id,NewPos) of + {{?proc_heap,LastId},LastPos} -> ets:insert(cdv_heap_file_chars,{LastId,N+Start+1-LastPos}); - {?literals,[]} -> - [{_,LastPos}] = lookup_index(?literals,[]), + {{?literals,[]},LastPos} -> ets:insert(cdv_heap_file_chars,{literals,N+Start+1-LastPos}); _ -> ok end, @@ -954,10 +952,10 @@ tag(Fd,<<>>,N,Gat,Di,Now) -> check_if_truncated() -> case get(last_tag) of - {?ende,_} -> + {{?ende,_},_} -> put(truncated,false), put(truncated_proc,false); - {?literals,[]} -> + {{?literals,[]},_} -> put(truncated,true), put(truncated_proc,false), %% Literals are truncated. Make sure we never @@ -965,7 +963,7 @@ check_if_truncated() -> %% references literals will show markers for %% incomplete heaps, but will otherwise work.) delete_index(?literals, []); - TruncatedTag -> + {TruncatedTag,_} -> put(truncated,true), find_truncated_proc(TruncatedTag) end. @@ -3213,13 +3211,13 @@ tag_to_atom(UnknownTag) -> %%%----------------------------------------------------------------- %%% Store last tag for use when truncated, and reason if aborted -put_last_tag(?abort,Reason) -> +put_last_tag(?abort,Reason,_Pos) -> %% Don't overwrite the real last tag, and don't return it either, %% since that would make the caller of this function believe that %% the tag was complete. put(truncated_reason,Reason); -put_last_tag(Tag,Id) -> - put(last_tag,{Tag,Id}). +put_last_tag(Tag,Id,Pos) -> + put(last_tag,{{Tag,Id},Pos}). %%%----------------------------------------------------------------- %%% Fetch next chunk from crashdump file -- cgit v1.2.3 From c9c1efe3815a49eb59ef62e8319cd9f6ea6c67d8 Mon Sep 17 00:00:00 2001 From: Siri Hansen Date: Mon, 29 Oct 2018 16:12:01 +0100 Subject: [cdv] Handle multiple "Yc" lines refering to the same refc binary Usually, sub binaries are implemented as special sub binary terms ("Ys" lines). But if a sub binary is sent to another process, sub binaries will be eliminated and incorporated into the ProcBin ("Yc" line), and when that happens there can be several "Yc" lines that refer to the same underlying binary object. Make sure that that the crash dump viewer can handle multiple "Yc" lines referring to the same binary object. --- lib/observer/src/crashdump_viewer.erl | 4 ++-- lib/observer/test/crashdump_helper.erl | 18 ++++++++++++++++++ lib/observer/test/crashdump_viewer_SUITE.erl | 7 +++++++ 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'lib/observer') diff --git a/lib/observer/src/crashdump_viewer.erl b/lib/observer/src/crashdump_viewer.erl index 41a569c2bf..af4e2f1dda 100644 --- a/lib/observer/src/crashdump_viewer.erl +++ b/lib/observer/src/crashdump_viewer.erl @@ -2802,12 +2802,12 @@ parse_heap_term("Yc"++Line0, Addr, DecodeOpts, D0) -> %Reference-counted binary. SymbolicBin = {'#CDVBin',Start}, Term = cdvbin(Offset, Sz, SymbolicBin), D1 = gb_trees:insert(Addr, Term, D0), - D = gb_trees:insert(Binp, SymbolicBin, D1), + D = gb_trees:enter(Binp, SymbolicBin, D1), {Term,Line,D}; [] -> Term = '#CDVNonexistingBinary', D1 = gb_trees:insert(Addr, Term, D0), - D = gb_trees:insert(Binp, Term, D1), + D = gb_trees:enter(Binp, Term, D1), {Term,Line,D} end; parse_heap_term("Ys"++Line0, Addr, DecodeOpts, D0) -> %Sub binary. diff --git a/lib/observer/test/crashdump_helper.erl b/lib/observer/test/crashdump_helper.erl index d8f4e046ae..315116fab7 100644 --- a/lib/observer/test/crashdump_helper.erl +++ b/lib/observer/test/crashdump_helper.erl @@ -62,6 +62,7 @@ n1_proc(Creator,_N2,Pid2,Port2,_L) -> put(ref,Ref), put(pid,Pid), put(bin,Bin), + put(proc_bins,create_proc_bins()), put(bins,create_binaries()), put(sub_bin,SubBin), put(sub_bins,create_sub_binaries(get(bins))), @@ -117,6 +118,23 @@ create_sub_binary(Bin, Start, LenSub) -> <<_:Start/bytes,Sub:Len/bytes,_/bytes>> = Bin, Sub. +create_proc_bins() -> + Parent = self(), + Pid = + spawn( + fun() -> + %% Just reverse the list here, so this binary is not + %% confused with the one created in n1_proc/5 above, + %% which is used for testing truncation (see + %% crashdump_viewer_SUITE:truncate_dump_binary/1) + Bin = list_to_binary(lists:reverse(lists:seq(1, 255))), + <> = Bin, + Parent ! {self(),{A,B,C}} + end), + receive + {Pid,ProcBins} -> ProcBins + end. + %%% %%% Test dumping of maps. Dumping of maps only from OTP 20.2. %%% diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index 864454cdff..25368da734 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -399,6 +399,13 @@ special(File,Procs) -> crashdump_viewer:expand_binary({SOffset,SSize,SPos}), io:format(" expand binary ok",[]), + ProcBins = proplists:get_value(proc_bins,Dict), + {['#CDVBin',0,65,ProcBin], + ['#CDVBin',65,65,ProcBin], + ['#CDVBin',130,125,ProcBin]} = ProcBins, + io:format(" ProcBins ok",[]), + + Binaries = crashdump_helper:create_binaries(), verify_binaries(Binaries, proplists:get_value(bins,Dict)), io:format(" binaries ok",[]), -- cgit v1.2.3