Skip to content

Commit

Permalink
Merge pull request #162 from gomoripeti/hist
Browse files Browse the repository at this point in the history
Address hdr_histogram issues
  • Loading branch information
gomoripeti committed Feb 6, 2019
2 parents 1672d00 + f55817d commit 0777759
Show file tree
Hide file tree
Showing 14 changed files with 876 additions and 59 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ matrix:
include:
- otp_release: 20.0
- otp_release: 19.3
- otp_release: 19.3
env: XPROF_ERL_HIST=true
- otp_release: 18.3
env: COWBOY_VERSION=1.1.2
- otp_release: 17.5
Expand Down
15 changes: 14 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Registry.dispatch(MyApp.Registry, "topic1", _) -> nil; (MyApp.Registry, "topic2"

## Erlang records

Elrang record syntax is supported in the queries and works similar to the Erlang
Erlang record syntax is supported in the queries and works similar to the Erlang
shell. XProf keeps a single global list of loaded record definitions. Record
definitions can be loaded at startup time from modules listed in app env
`load_records` or at runtime calling `xprof_core:rr(Module)` (see documentation
Expand All @@ -208,6 +208,19 @@ debug_info of the beam files belonging to the loaded modules. As the list is
global there can be only one record with the same name loaded at a time and
records loaded later might override previously loaded ones.

## Compile-time configuration

`XPROF_ERL_HIST` - By default XProf uses the `hdr_histogram_erl` NIF
library. If you have compilation problems you can choose to use a
native Erlang histogram implementation by defining the OS env var
`XPROF_ERL_HIST` when compiling `xprof_core`.

`COWBOY_VERSION` - By default XProf uses Cowboy version 2.x. This
version is only supported from Erlang/OTP 19 and is not backwards
compatible with older Cowboy versions. If for some reason you would
like to use Cowboy version 1.x you can define the OS env var
`COWBOY_VERSION=1` when compiling `xprof_gui`.

## Contributing

All improvements, fixes and ideas are very welcomed!
Expand Down
7 changes: 5 additions & 2 deletions apps/xprof_core/rebar.config
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{deps,
[{customized_hdr_histogram, "0.3.2"},
[{hdr_histogram, "0.3.2"},
{lager, "3.2.4"}
]}.

{erl_opts, [debug_info,
{parse_transform, lager_transform},
{platform_define, "^((1[8|9])|2)", rand_module}]}.
{platform_define, "^(R|17|18)", before_OTP_19},
{platform_define, "^((1[8|9])|2)", rand_module},
{platform_define, "^[^R1]", ceil_floor}
]}.
12 changes: 12 additions & 0 deletions apps/xprof_core/rebar.config.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
case os:getenv("XPROF_ERL_HIST") of
false ->
CONFIG;
_ ->
ErlOpts = proplists:get_value(erl_opts, CONFIG, []),
NewErlOpts = {erl_opts, [{d, 'XPROF_ERL_HIST'}|ErlOpts]},
Config2 = lists:keystore(erl_opts, 1, CONFIG, NewErlOpts),

Deps = proplists:get_value(deps, CONFIG, []),
NewDeps = {deps, lists:keydelete(hdr_histogram, 1, Deps)},
lists:keystore(deps, 1, Config2, NewDeps)
end.
2 changes: 1 addition & 1 deletion apps/xprof_core/src/xprof_core.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
,stdlib
,compiler
,lager
,customized_hdr_histogram
,hdr_histogram
]}
,{env,[]}
,{modules, []}
Expand Down
42 changes: 14 additions & 28 deletions apps/xprof_core/src/xprof_core_cmd_funlatency.erl
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ init(Options, _MFASpec) ->
undefined -> undefined;
_ -> 0
end,
{ok, HDR} = hdr_histogram:open(MaxDuration, 3),
{ok, HDR} = xprof_core_hist:hdr_new(MaxDuration, 3),
{ok, #state{hdr_ref = HDR,
max_duration = MaxDuration,
ignore_recursion = IgnoreRecursion,
Expand Down Expand Up @@ -116,9 +116,9 @@ handle_event({trace_ts, Pid, Tag, MFA, RetOrExc, EndTime},
lager:error("Call ~p took ~p ms that is larger than the maximum "
"that can be stored (~p ms)",
[MFA, CallTime/1000, MaxDuration div 1000]),
ok = hdr_histogram:record(Ref, MaxDuration);
ok = xprof_core_hist:hdr_record(Ref, MaxDuration);
true ->
ok = hdr_histogram:record(Ref, CallTime)
ok = xprof_core_hist:hdr_record(Ref, CallTime)
end,

maybe_capture({Pid, CallTime, Args, {Tag, NewRet}},
Expand All @@ -128,7 +128,7 @@ handle_event({trace_ts, Pid, Tag, MFA, RetOrExc, EndTime},

take_snapshot(State = #state{hdr_ref = Ref, nomatch_count = NoMatch}) ->
Snapshot = get_current_hist_stats(Ref, NoMatch),
hdr_histogram:reset(Ref),
xprof_core_hist:hdr_reset(Ref),
maybe_reset_nomatch_count(Snapshot, State, NoMatch).

maybe_reset_nomatch_count(Snapshot, _State, _NoMatch = undefined) ->
Expand Down Expand Up @@ -211,30 +211,16 @@ maybe_capture({_Pid, CallTime, Args, _Res} = Item, Threshold, _State) ->
end.

get_current_hist_stats(HistRef, NoMatch) ->
Count = hdr_histogram:get_total_count(HistRef),
TotalCountAndRate =
case NoMatch of
undefined ->
[];
_ ->
TotalCount = Count + NoMatch,
[{total_count, TotalCount},
{match_rate, percent(Count, TotalCount)}]
end,
[{min, hdr_histogram:min(HistRef)},
{mean, hdr_histogram:mean(HistRef)},
%%{median, hdr_histogram:median(HistRef)},
{max, hdr_histogram:max(HistRef)},
%%{stddev, hdr_histogram:stddev(HistRef)},
%%{p25, hdr_histogram:percentile(HistRef,25.0)},
{p50, hdr_histogram:percentile(HistRef,50.0)},
{p75, hdr_histogram:percentile(HistRef,75.0)},
{p90, hdr_histogram:percentile(HistRef,90.0)},
{p99, hdr_histogram:percentile(HistRef,99.0)},
%%{p9999999, hdr_histogram:percentile(HistRef,99.9999)},
%%{memsize, hdr_histogram:get_memory_size(HistRef)},
{count, Count}
|TotalCountAndRate].
[{count, Count}|_] = Stats = xprof_core_hist:hdr_stats(HistRef),
case NoMatch of
undefined ->
Stats;
_ ->
TotalCount = Count + NoMatch,
[{total_count, TotalCount},
{match_rate, percent(Count, TotalCount)}
|Stats]
end.

percent(_, 0) ->
0;
Expand Down
Loading

0 comments on commit 0777759

Please sign in to comment.