-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filter trace to range #222
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work! Could you also please interactive rebase over current master, and squash commits into logical groupings? Seems like a few commits unrelated to your work snuck in.
core/trace_filter.ml
Outdated
open! Core | ||
|
||
module Range = struct | ||
type t = string * string [@@deriving sexp] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this a record? Accepting it as a (start stop)
sexp and then manually expanding it into named record fields in the arg type parser sounds reasonable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, if we do this, we don't need the extra Range
module, and could call of_command_string
for both left/right of the tuple here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we still need two modules to express the difference between a the filter we get from the command line (range of Symbol_selection.t
s) and a filter that's been evaluated (turned into strings) by fzf.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turned it into a record and changed things around a bit so [Unevaluated] is the inner module. I think it reads a bit better, but let me know if I'm missing something obvious and can get rid of the extra module altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess what I'm unclear on is why not have:
module Symbol_range = struct
type t =
{ start_symbol : Symbol_selection.t
; stop_symbol : Symbol_selection.t
}
(* Accepts '(foo bar)', returns { start_symbol = User_selected "foo"; stop_symbol = User_selected = "bar" } *)
let arg_type = ...
end
and not have the Option.map
call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This lets you get rid of String_pair
I think.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that makes sense, wasn't thinking through what I was doing with the Option.map
src/trace_writer.ml
Outdated
rewrite_callstack t ~callstack:thread_info.callstack ~thread_info ~time | ||
;; | ||
|
||
let maybe_start_hot_section t ~should_write ~time = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe_start_trimmed_region
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filtered_region?
src/trace_writer.ml
Outdated
Hashtbl.iter t.thread_info ~f:(fun thread_info -> | ||
flush t ~to_time:time thread_info; | ||
Deque.clear thread_info.start_events); | ||
t.in_hot_section <- true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`in_trimmed_range?
@@ -9,6 +9,8 @@ type t = | |||
| Syscall | |||
[@@deriving sexp, compare] | |||
|
|||
let equal t1 t2 = compare t1 t2 = 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does [@@deriving equal]
work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because Int64.Hex
(used by Perf_map_location
) doesn't derive equal.
core/trace_filter.ml
Outdated
open! Core | ||
|
||
module Range = struct | ||
type t = string * string [@@deriving sexp] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess what I'm unclear on is why not have:
module Symbol_range = struct
type t =
{ start_symbol : Symbol_selection.t
; stop_symbol : Symbol_selection.t
}
(* Accepts '(foo bar)', returns { start_symbol = User_selected "foo"; stop_symbol = User_selected = "bar" } *)
let arg_type = ...
end
and not have the Option.map
call.
[@@deriving fields] | ||
end | ||
|
||
type t = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this type used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's returned by evaluate_trace_filter
in trace.ml and gets passed around until the filter is actually applied.
src/for_range.ml
Outdated
| Error _ | Ok (Power _) -> hits, in_filtered_region | ||
| Ok (Trace ok) -> | ||
(match | ||
( Time_ns_unix.Span.(ok.time = hd.time) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about something like
let hits, in_filtered_region =
match hits with
| [] -> hits, in_filtered_region
| hd :: tl ->
(match event with
| Ok (Trace { kind = Some Call; time; dst; _ })
when Time_ns_unix.Span.(time = hd.time) &&
Symbol.equal dst.symbol hd.symbol -> tl, not in_filtered_region
| _ -> hits, in_filtered_region)
in
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to something close to this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise LGTM. I think if you rebased/squashed we could be good to merge.
1d7693e
to
d792775
Compare
I had to update the range logic a bit to handle Making the behavior identical would require a bit more work: the control flow would have to be fairly different depending on if we're receiving sampling events or perf events. I think using sampling with the filter isn't likely to be a super common use-case, but let me know what you think. |
…put to include only events between consecutive occurences of <start> and <stop>. Signed-off-by: Peter Baumbacher <pbaumbacher@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
Adds a new flag
-filter "(<start> <stop>)"
to magic trace. With this flag, the trace is trimmed to only include events that occur betweenstart
(inclusive) andstop
(exclusive) (#81). If either symbol doesn't appear in the trace, no output is produced. In multi-snapshot mode, the trace only includes regions between consecutivestart
andstop
calls. The-filter
flag is compatible with the same modes as the-trigger
flag.When producing a
.sexp
output, only events that occur in the filtered region are emitted. When producing a fuchsia.fxt
output, the full available callstack around the filtered region is reconstructed. Active stack frames at the beginning of the filtered region have the timestart
was called as their inferred start time.