16
16
17
17
-module (rabbit_vm ).
18
18
19
- -export ([memory /0 , binary /0 , ets_tables_memory /1 ]).
19
+ -export ([memory /0 , total_memory / 0 , binary /0 , ets_tables_memory /1 ]).
20
20
21
21
-define (MAGIC_PLUGINS , [" cowboy" , " sockjs" , " rfc4627_jsonrpc" ]).
22
22
30
30
31
31
% %----------------------------------------------------------------------------
32
32
33
- % % Like erlang:memory(), but with awareness of rabbit-y things
34
33
memory () ->
35
34
All = interesting_sups (),
36
35
{Sums , _Other } = sum_processes (
@@ -41,7 +40,7 @@ memory() ->
41
40
[aggregate (Names , Sums , memory , fun (X ) -> X end )
42
41
|| Names <- distinguished_interesting_sups ()],
43
42
44
- Mnesia = mnesia_memory (),
43
+ MnesiaETS = mnesia_memory (),
45
44
MsgIndexETS = ets_memory ([msg_store_persistent , msg_store_transient ]),
46
45
MetricsETS = ets_memory ([rabbit_metrics ]),
47
46
MetricsProc = try
@@ -52,8 +51,10 @@ memory() ->
52
51
0
53
52
end ,
54
53
MgmtDbETS = ets_memory ([rabbit_mgmt_storage ]),
54
+ OsTotal = total_memory (),
55
55
56
- [{total , Total },
56
+
57
+ [{total , ErlangTotal },
57
58
{processes , Processes },
58
59
{ets , ETS },
59
60
{atom , Atom },
@@ -66,30 +67,137 @@ memory() ->
66
67
- ConnsReader - ConnsWriter - ConnsChannel - ConnsOther
67
68
- Qs - QsSlave - MsgIndexProc - Plugins - MgmtDbProc - MetricsProc ,
68
69
69
- [{total , Total },
70
+ [
71
+ % % Connections
70
72
{connection_readers , ConnsReader },
71
73
{connection_writers , ConnsWriter },
72
74
{connection_channels , ConnsChannel },
73
75
{connection_other , ConnsOther },
76
+
77
+ % % Queues
74
78
{queue_procs , Qs },
75
79
{queue_slave_procs , QsSlave },
80
+
81
+ % % Processes
76
82
{plugins , Plugins },
77
83
{other_proc , lists :max ([0 , OtherProc ])}, % % [1]
78
- {mnesia , Mnesia },
84
+
85
+ % % Metrics
79
86
{metrics , MetricsETS + MetricsProc },
80
87
{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)
83
94
{binary , Bin },
95
+ {msg_index , MsgIndexETS + MsgIndexProc },
96
+
97
+ % % System
84
98
{code , Code },
85
99
{atom , Atom },
86
- {other_system , System - ETS - Atom - Bin - Code }].
100
+ {other_system , System - ETS - Bin - Code - Atom + ( OsTotal - ErlangTotal )},
87
101
102
+ {total , OsTotal }
103
+ ].
88
104
% % [1] - erlang:memory(processes) can be less than the sum of its
89
105
% % parts. Rather than display something nonsensical, just silence any
90
106
% % claims about negative memory. See
91
107
% % http://erlang.org/pipermail/erlang-questions/2012-September/069320.html
92
108
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
+
93
201
binary () ->
94
202
All = interesting_sups (),
95
203
{Sums , Rest } =
0 commit comments