Skip to content

Commit d817366

Browse files
Merge pull request #1259 from rabbitmq/rabbitmq-server-1223
Use system process rss memory when reporting vm memory
2 parents 1c8798a + bbc69fe commit d817366

File tree

3 files changed

+125
-15
lines changed

3 files changed

+125
-15
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_vm.erl

Lines changed: 117 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", "sockjs", "rfc4627_jsonrpc"]).
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_store_persistent, msg_store_transient]),
4645
MetricsETS = ets_memory([rabbit_metrics]),
4746
MetricsProc = try
@@ -52,8 +51,10 @@ memory() ->
5251
0
5352
end,
5453
MgmtDbETS = ets_memory([rabbit_mgmt_storage]),
54+
OsTotal = total_memory(),
5555

56-
[{total, Total},
56+
57+
[{total, ErlangTotal},
5758
{processes, Processes},
5859
{ets, ETS},
5960
{atom, Atom},
@@ -66,30 +67,137 @@ memory() ->
6667
- ConnsReader - ConnsWriter - ConnsChannel - ConnsOther
6768
- Qs - QsSlave - MsgIndexProc - Plugins - MgmtDbProc - MetricsProc,
6869

69-
[{total, Total},
70+
[
71+
%% Connections
7072
{connection_readers, ConnsReader},
7173
{connection_writers, ConnsWriter},
7274
{connection_channels, ConnsChannel},
7375
{connection_other, ConnsOther},
76+
77+
%% Queues
7478
{queue_procs, Qs},
7579
{queue_slave_procs, QsSlave},
80+
81+
%% Processes
7682
{plugins, Plugins},
7783
{other_proc, lists:max([0, OtherProc])}, %% [1]
78-
{mnesia, Mnesia},
84+
85+
%% Metrics
7986
{metrics, MetricsETS + MetricsProc},
8087
{mgmt_db, MgmtDbETS + MgmtDbProc},
81-
{msg_index, MsgIndexETS + MsgIndexProc},
82-
{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)
8394
{binary, Bin},
95+
{msg_index, MsgIndexETS + MsgIndexProc},
96+
97+
%% System
8498
{code, Code},
8599
{atom, Atom},
86-
{other_system, System - ETS - Atom - Bin - Code}].
100+
{other_system, System - ETS - Bin - Code - Atom + (OsTotal - ErlangTotal)},
87101

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

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+
93201
binary() ->
94202
All = interesting_sups(),
95203
{Sums, Rest} =

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, ":"),

0 commit comments

Comments
 (0)