Skip to content

Commit 72415b1

Browse files
Merge branch 'stable'
Conflicts: src/rabbit_vm.erl src/term_to_binary_compat.erl
2 parents bc5048b + d817366 commit 72415b1

File tree

6 files changed

+174
-39
lines changed

6 files changed

+174
-39
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ define PROJECT_ENV
1616
{ssl_options, []},
1717
{vm_memory_high_watermark, 0.4},
1818
{vm_memory_high_watermark_paging_ratio, 0.5},
19+
{vm_memory_calculation_strategy, rss},
1920
{memory_monitor_interval, 2500},
2021
{disk_free_limit, 50000000}, %% 50MB
2122
{msg_store_index_module, rabbit_msg_store_ets_index},

src/rabbit_queue_index.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ recover_message(false, _, no_del, RelSeq, {Segment, DirtyCount}) ->
691691
DirtyCount + 2}.
692692

693693
queue_name_to_dir_name(Name = #resource { kind = queue }) ->
694-
<<Num:128>> = erlang:md5(term_to_binary_compat:queue_name_to_binary(Name)),
694+
<<Num:128>> = erlang:md5(term_to_binary_compat:term_to_binary_1(Name)),
695695
rabbit_misc:format("~.36B", [Num]).
696696

697697
queues_base_dir() ->

src/rabbit_vm.erl

Lines changed: 116 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
-module(rabbit_vm).
1818

19-
-export([memory/0, binary/0, ets_tables_memory/1]).
19+
-export([memory/0, total_memory/0, binary/0, ets_tables_memory/1]).
2020

2121
-define(MAGIC_PLUGINS, ["cowboy", "ranch", "sockjs"]).
2222

@@ -30,7 +30,6 @@
3030

3131
%%----------------------------------------------------------------------------
3232

33-
%% Like erlang:memory(), but with awareness of rabbit-y things
3433
memory() ->
3534
All = interesting_sups(),
3635
{Sums, _Other} = sum_processes(
@@ -41,7 +40,7 @@ memory() ->
4140
[aggregate(Names, Sums, memory, fun (X) -> X end)
4241
|| Names <- distinguished_interesting_sups()],
4342

44-
Mnesia = mnesia_memory(),
43+
MnesiaETS = mnesia_memory(),
4544
MsgIndexETS = ets_memory(msg_stores()),
4645
MetricsETS = ets_memory([rabbit_metrics]),
4746
MetricsProc =
@@ -53,8 +52,9 @@ memory() ->
5352
0
5453
end,
5554
MgmtDbETS = ets_memory([rabbit_mgmt_storage]),
55+
OsTotal = total_memory(),
5656

57-
[{total, Total},
57+
[{total, ErlangTotal},
5858
{processes, Processes},
5959
{ets, ETS},
6060
{atom, Atom},
@@ -67,30 +67,137 @@ memory() ->
6767
- ConnsReader - ConnsWriter - ConnsChannel - ConnsOther
6868
- Qs - QsSlave - MsgIndexProc - Plugins - MgmtDbProc - MetricsProc,
6969

70-
[{total, Total},
70+
[
71+
%% Connections
7172
{connection_readers, ConnsReader},
7273
{connection_writers, ConnsWriter},
7374
{connection_channels, ConnsChannel},
7475
{connection_other, ConnsOther},
76+
77+
%% Queues
7578
{queue_procs, Qs},
7679
{queue_slave_procs, QsSlave},
80+
81+
%% Processes
7782
{plugins, Plugins},
7883
{other_proc, lists:max([0, OtherProc])}, %% [1]
79-
{mnesia, Mnesia},
84+
85+
%% Metrics
8086
{metrics, MetricsETS + MetricsProc},
8187
{mgmt_db, MgmtDbETS + MgmtDbProc},
82-
{msg_index, MsgIndexETS + MsgIndexProc},
83-
{other_ets, ETS - Mnesia - MsgIndexETS - MgmtDbETS},
88+
89+
%% ETS
90+
{mnesia, MnesiaETS},
91+
{other_ets, ETS - MnesiaETS - MetricsETS - MgmtDbETS - MsgIndexETS},
92+
93+
%% Messages (mostly, some binaries are not messages)
8494
{binary, Bin},
95+
{msg_index, MsgIndexETS + MsgIndexProc},
96+
97+
%% System
8598
{code, Code},
8699
{atom, Atom},
87-
{other_system, System - ETS - Atom - Bin - Code}].
100+
{other_system, System - ETS - Bin - Code - Atom + (OsTotal - ErlangTotal)},
88101

102+
{total, OsTotal}
103+
].
89104
%% [1] - erlang:memory(processes) can be less than the sum of its
90105
%% parts. Rather than display something nonsensical, just silence any
91106
%% claims about negative memory. See
92107
%% http://erlang.org/pipermail/erlang-questions/2012-September/069320.html
93108

109+
%% Memory reported by erlang:memory(total) is not supposed to
110+
%% be equal to the total size of all pages mapped to the emulator,
111+
%% according to http://erlang.org/doc/man/erlang.html#memory-0
112+
%% erlang:memory(total) under-reports memory usage by around 20%
113+
-spec total_memory() -> Bytes :: integer().
114+
total_memory() ->
115+
case get_memory_calculation_strategy() of
116+
rss ->
117+
case get_system_process_resident_memory() of
118+
{ok, MemInBytes} ->
119+
MemInBytes;
120+
{error, Reason} ->
121+
rabbit_log:debug("Unable to get system memory used. Reason: ~p."
122+
" Falling back to erlang memory reporting",
123+
[Reason]),
124+
erlang:memory(total)
125+
end;
126+
erlang ->
127+
erlang:memory(total)
128+
end.
129+
130+
-spec get_memory_calculation_strategy() -> rss | erlang.
131+
get_memory_calculation_strategy() ->
132+
case application:get_env(rabbit, vm_memory_calculation_strategy, rss) of
133+
erlang ->
134+
erlang;
135+
rss ->
136+
rss;
137+
UnsupportedValue ->
138+
rabbit_log:warning(
139+
"Unsupported value '~p' for vm_memory_calculation_strategy. "
140+
"Supported values: (rss|erlang). "
141+
"Defaulting to 'rss'",
142+
[UnsupportedValue]
143+
),
144+
rss
145+
end.
146+
147+
-spec get_system_process_resident_memory() -> {ok, Bytes :: integer()} | {error, term()}.
148+
get_system_process_resident_memory() ->
149+
try
150+
get_system_process_resident_memory(os:type())
151+
catch _:Error ->
152+
{error, {"Failed to get process resident memory", Error}}
153+
end.
154+
155+
get_system_process_resident_memory({unix,darwin}) ->
156+
get_ps_memory();
157+
158+
get_system_process_resident_memory({unix, linux}) ->
159+
get_ps_memory();
160+
161+
get_system_process_resident_memory({unix,freebsd}) ->
162+
get_ps_memory();
163+
164+
get_system_process_resident_memory({unix,openbsd}) ->
165+
get_ps_memory();
166+
167+
get_system_process_resident_memory({win32,_OSname}) ->
168+
OsPid = os:getpid(),
169+
Cmd = " tasklist /fi \"pid eq " ++ OsPid ++ "\" /fo LIST 2>&1 ",
170+
CmdOutput = os:cmd(Cmd),
171+
%% Memory usage is displayed in kilobytes
172+
%% with comma-separated thousands
173+
case re:run(CmdOutput, "Mem Usage:\\s+([0-9,]+)\\s+K", [{capture, all_but_first, list}]) of
174+
{match, [Match]} ->
175+
NoCommas = [ N || N <- Match, N =/= $, ],
176+
{ok, list_to_integer(NoCommas) * 1024};
177+
_ ->
178+
{error, {unexpected_output_from_command, Cmd, CmdOutput}}
179+
end;
180+
181+
get_system_process_resident_memory({unix, sunos}) ->
182+
get_ps_memory();
183+
184+
get_system_process_resident_memory({unix, aix}) ->
185+
get_ps_memory();
186+
187+
get_system_process_resident_memory(_OsType) ->
188+
{error, not_implemented_for_os}.
189+
190+
get_ps_memory() ->
191+
OsPid = os:getpid(),
192+
Cmd = "ps -p " ++ OsPid ++ " -o rss=",
193+
CmdOutput = os:cmd(Cmd),
194+
case re:run(CmdOutput, "[0-9]+", [{capture, first, list}]) of
195+
{match, [Match]} ->
196+
{ok, list_to_integer(Match) * 1024};
197+
_ ->
198+
{error, {unexpected_output_from_command, Cmd, CmdOutput}}
199+
end.
200+
94201
binary() ->
95202
All = interesting_sups(),
96203
{Sums, Rest} =

src/term_to_binary_compat.erl

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,8 @@
1818

1919
-include("rabbit.hrl").
2020

21-
-export([queue_name_to_binary/1]).
21+
-export([term_to_binary_1/1]).
2222

23-
queue_name_to_binary(#resource{kind = queue, virtual_host = VHost, name = Name}) ->
24-
VHostBSize = byte_size(VHost),
25-
NameBSize = byte_size(Name),
26-
<<131, %% Binary format "version"
27-
104, 4, %% 4-element tuple
28-
100, 0, 8, "resource", %% `resource` atom
29-
109, VHostBSize:32, VHost/binary, %% Vhost binary
30-
100, 0, 5, "queue", %% `queue` atom
31-
109, NameBSize:32, Name/binary>>. %% Name binary
23+
term_to_binary_1(Term) ->
24+
term_to_binary(Term, [{minor_version, 1}]).
3225

src/vm_memory_monitor.erl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,14 @@ get_memory_limit() ->
117117

118118
get_memory_use(bytes) ->
119119
MemoryLimit = get_memory_limit(),
120-
{erlang:memory(total), case MemoryLimit > 0.0 of
121-
true -> MemoryLimit;
122-
false -> infinity
123-
end};
120+
{rabbit_vm:total_memory(), case MemoryLimit > 0.0 of
121+
true -> MemoryLimit;
122+
false -> infinity
123+
end};
124124
get_memory_use(ratio) ->
125125
MemoryLimit = get_memory_limit(),
126126
case MemoryLimit > 0.0 of
127-
true -> erlang:memory(total) / MemoryLimit;
127+
true -> rabbit_vm:total_memory() / MemoryLimit;
128128
false -> infinity
129129
end.
130130

@@ -268,7 +268,7 @@ parse_mem_limit(_) ->
268268
internal_update(State = #state { memory_limit = MemLimit,
269269
alarmed = Alarmed,
270270
alarm_funs = {AlarmSet, AlarmClear} }) ->
271-
MemUsed = erlang:memory(total),
271+
MemUsed = rabbit_vm:total_memory(),
272272
NewAlarmed = MemUsed > MemLimit,
273273
case {Alarmed, NewAlarmed} of
274274
{false, true} -> emit_update_info(set, MemUsed, MemLimit),
@@ -365,6 +365,7 @@ get_total_memory({unix, aix}) ->
365365
get_total_memory(_OsType) ->
366366
unknown.
367367

368+
368369
%% A line looks like "Foo bar: 123456."
369370
parse_line_mach(Line) ->
370371
[Name, RHS | _Rest] = string:tokens(Line, ":"),

test/term_to_binary_compat_prop_SUITE.erl

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,11 @@
2424
-include_lib("proper/include/proper.hrl").
2525

2626
all() ->
27-
%% The test should run on OTP < 20 (erts < 9)
28-
case erts_gt_8() of
29-
true ->
30-
[];
31-
false ->
32-
[queue_name_to_binary]
33-
end.
27+
[
28+
pre_3_6_11_works,
29+
term_to_binary_latin_atom,
30+
queue_name_to_binary
31+
].
3432

3533
erts_gt_8() ->
3634
Vsn = erlang:system_info(version),
@@ -47,16 +45,51 @@ end_per_suite(Config) ->
4745
init_per_testcase(Testcase, Config) ->
4846
rabbit_ct_helpers:testcase_started(Config, Testcase).
4947

48+
%% If this test fails - the erlang version is not supported in
49+
%% RabbitMQ-3.6.10 and earlier.
50+
pre_3_6_11_works(Config) ->
51+
Fun = fun () -> prop_pre_3_6_11_works(Config) end,
52+
rabbit_ct_proper_helpers:run_proper(Fun, [], 50000).
53+
54+
prop_pre_3_6_11_works(_Config) ->
55+
?FORALL(Term, any(),
56+
begin
57+
Current = term_to_binary(Term),
58+
Compat = term_to_binary_compat:term_to_binary_1(Term),
59+
Current =:= Compat
60+
end).
61+
62+
term_to_binary_latin_atom(Config) ->
63+
Fun = fun () -> prop_term_to_binary_latin_atom(Config) end,
64+
rabbit_ct_proper_helpers:run_proper(Fun, [], 10000).
65+
66+
prop_term_to_binary_latin_atom(_Config) ->
67+
?FORALL(LatinString, list(integer(0, 255)),
68+
begin
69+
Length = length(LatinString),
70+
Atom = list_to_atom(LatinString),
71+
Binary = list_to_binary(LatinString),
72+
<<131,100, Length:16, Binary/binary>> =:= term_to_binary_compat:term_to_binary_1(Atom)
73+
end).
74+
5075
queue_name_to_binary(Config) ->
5176
Fun = fun () -> prop_queue_name_to_binary(Config) end,
5277
rabbit_ct_proper_helpers:run_proper(Fun, [], 10000).
5378

5479

5580
prop_queue_name_to_binary(_Config) ->
56-
?FORALL({Vhost, QName}, {binary(), binary()},
81+
?FORALL({VHost, QName}, {binary(), binary()},
5782
begin
58-
Resource = rabbit_misc:r(Vhost, queue, QName),
59-
Legacy = term_to_binary_compat:queue_name_to_binary(Resource),
60-
Current = term_to_binary(Resource),
61-
Current =:= Legacy
62-
end).
83+
VHostBSize = byte_size(VHost),
84+
NameBSize = byte_size(QName),
85+
Expected =
86+
<<131, %% Binary format "version"
87+
104, 4, %% 4-element tuple
88+
100, 0, 8, "resource", %% `resource` atom
89+
109, VHostBSize:32, VHost/binary, %% Vhost binary
90+
100, 0, 5, "queue", %% `queue` atom
91+
109, NameBSize:32, QName/binary>>, %% Name binary
92+
Resource = rabbit_misc:r(VHost, queue, QName),
93+
Current = term_to_binary_compat:term_to_binary_1(Resource),
94+
Current =:= Expected
95+
end).

0 commit comments

Comments
 (0)