Skip to content
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

Address hdr_histogram issues #162

Merged
merged 6 commits into from
Feb 6, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ branches:
only:
- master
- release_2.0
- hist
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