Skip to content

Commit aa59594

Browse files
committed
better compress location?
1 parent 9424a02 commit aa59594

File tree

2 files changed

+50
-26
lines changed

2 files changed

+50
-26
lines changed

example/dune

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
(public_name example)
55
(libraries pyro-caml-instruments unix)
66
(modes exe)
7-
(preprocess
8-
(pps ppx_pyro_caml --auto))
97
(foreign_stubs
108
(language c)
119
(names example_stubs)

lib/Stack_trace.ml

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,50 @@
1919

2020
type slot = Printexc.backtrace_slot
2121

22+
let equal_slot s1 s2 =
23+
let name_eq =
24+
Option.equal String.equal (Printexc.Slot.name s1) (Printexc.Slot.name s2)
25+
in
26+
let loc1 = Printexc.Slot.location s1 in
27+
let loc2 = Printexc.Slot.location s2 in
28+
let loc_eq =
29+
match (loc1, loc2) with
30+
| None, None -> true
31+
| Some l1, Some l2 ->
32+
l1.filename = l2.filename && l1.line_number = l2.line_number
33+
| _, _ -> false
34+
in
35+
name_eq && loc_eq
36+
37+
(* Looking ahead by up to 3 can be useful for recursive functions to make them
38+
much more legible. E.g. List.map can be very recursive, and pyroscope has a
39+
~1000 stack frame limit, so if we iterate through say, 10k items there's a
40+
good chance we may max out, which will cause any frames past the limit to be
41+
dropped and instead replaced with a single frame that says "other".
42+
43+
It's also nice to do this on the client side since it reduces how much data
44+
we have to turn into runtime events and reduces the overall number of events
45+
since there will be less partial events needed.
46+
*)
47+
let compress_slot_array array =
48+
(* TODO how to do this inline w/an array? *)
49+
let array_list = Array.to_list array in
50+
let rec aux acc = function
51+
| [] -> List.rev acc
52+
| s1 :: s2 :: s3 :: (s4 :: s5 :: s6 :: _ as rest)
53+
when equal_slot s1 s4 && equal_slot s2 s5 && equal_slot s3 s6 ->
54+
aux acc rest
55+
| s1 :: s2 :: (s3 :: s4 :: _ as rest)
56+
when equal_slot s1 s3 && equal_slot s2 s4 ->
57+
aux acc rest
58+
| s1 :: (s2 :: _ as rest) when equal_slot s1 s2 -> aux acc rest
59+
| s :: rest -> aux (s :: acc) rest
60+
in
61+
aux [] array_list
62+
2263
(* What's sent via runtime events. this HAS to be marshalable*)
2364
type raw_stack_trace = {
24-
slots : slot array;
65+
slots : slot list;
2566
domain_id : int;
2667
thread_name : string;
2768
}
@@ -33,7 +74,12 @@ let raw_stack_trace_of_backtrace bt : raw_stack_trace =
3374
(* Nice to call it main but probably not necessary *)
3475
let name = if Domain.is_main_domain () then "main" else string_of_int did in
3576
(* if there aren't any slots then not much we can do *)
36-
let slots = Option.value ~default:[||] Printexc.(backtrace_slots bt) in
77+
let slots =
78+
bt
79+
|> Printexc.(backtrace_slots)
80+
|> Option.map compress_slot_array
81+
|> Option.value ~default:[]
82+
in
3783
{ slots; domain_id = did; thread_name = name }
3884

3985
(*****************************************************************************)
@@ -65,27 +111,7 @@ let stack_frame_of_slot (slot : Printexc.backtrace_slot) : frame =
65111
let inlined = Printexc.Slot.is_inline slot in
66112
{ name; filename; line; inlined }
67113

68-
(* Looking ahead by up to 3 can be useful for recursive functions to make them
69-
much more legible. E.g. List.map can be very recursive, and pyroscope has a
70-
~1000 stack frame limit, so if we iterate through say, 10k items there's a
71-
good chance we may max out, which will cause any frames past the limit to be
72-
dropped and instead replaced with a single frame that says "other"*)
73-
let compress frames =
74-
let rec aux acc = function
75-
| [] -> List.rev acc
76-
| f1 :: f2 :: f3 :: (f4 :: f5 :: f6 :: _ as rest)
77-
when equal_frame f1 f4 && equal_frame f2 f5 && equal_frame f3 f6 ->
78-
aux acc rest
79-
| f1 :: f2 :: (f3 :: f4 :: _ as rest)
80-
when equal_frame f1 f3 && equal_frame f2 f4 ->
81-
aux acc rest
82-
| f1 :: (f2 :: _ as rest) when equal_frame f1 f2 -> aux acc rest
83-
| f :: rest -> aux (f :: acc) rest
84-
in
85-
aux [] frames
86-
87-
let stack_frames_of_slots slots =
88-
slots |> List.map stack_frame_of_slot |> compress
114+
let stack_frames_of_slots = List.map stack_frame_of_slot
89115

90116
(*****************************************************************************)
91117
(* Stack traces *)
@@ -94,7 +120,7 @@ let stack_frames_of_slots slots =
94120
type t = { frames : frame list; thread_id : int; thread_name : string }
95121

96122
let t_of_raw_stack_trace raw_stack_trace =
97-
let frames = stack_frames_of_slots (Array.to_list raw_stack_trace.slots) in
123+
let frames = stack_frames_of_slots raw_stack_trace.slots in
98124
{
99125
frames;
100126
thread_id = raw_stack_trace.domain_id;

0 commit comments

Comments
 (0)