summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Sackman <matthew@lshift.net>2009-10-28 16:06:03 +0000
committerMatthew Sackman <matthew@lshift.net>2009-10-28 16:06:03 +0000
commitdf5a328a797154e5cdec87cfbf409e8320d8a7b3 (patch)
treef1e53338a5828f667dbeef1f934b6f4ec9ad631a
parent34ec9525426def320d29757ffd79d681133ed847 (diff)
downloadrabbitmq-server-df5a328a797154e5cdec87cfbf409e8320d8a7b3.tar.gz
cosmetics and rearranging only - conformance and consistency
-rw-r--r--src/vm_memory_monitor.erl216
1 files changed, 111 insertions, 105 deletions
diff --git a/src/vm_memory_monitor.erl b/src/vm_memory_monitor.erl
index d1bec186..7d291f38 100644
--- a/src/vm_memory_monitor.erl
+++ b/src/vm_memory_monitor.erl
@@ -30,17 +30,17 @@
%%
%% In practice erlang shouldn't be allowed to grow to more than a half
-%% of available memory. The pessimistic scenario is when erlang VM has
-%% a single erlang process that's consuming all the memory.
-%% In such case during garbage collection erlang tries to allocate
-%% huge chunk of continuous memory, which can result in a crash
-%% (likely on 32-bit machine) or heavy swapping (likely on 64-bit).
+%% of available memory. The pessimistic scenario is when erlang VM has
+%% a single erlang process that's consuming all the memory. In such
+%% case during garbage collection erlang tries to allocate huge chunk
+%% of continuous memory, which can result in a crash (likely on 32-bit
+%% machine) or heavy swapping (likely on 64-bit).
%%
-%% This module tries to warn Rabbit before such situations happen,
-%% so that it has higher chances to prevent running out of memory.
+%% This module tries to warn Rabbit before such situations happen, so
+%% that it has higher chances to prevent running out of memory.
%%
-%% This code depends on Erlang Memsup supervisor. Setting the update interval
-%% causes a side effect of setting the interval on Memsup.
+%% This code depends on Erlang Memsup supervisor. Setting the update
+%% interval causes a side effect of setting the interval on Memsup.
%% This should rarely be an issue.
-module(vm_memory_monitor).
@@ -53,15 +53,16 @@
terminate/2, code_change/3]).
-export([update/0, get_total_memory/1,
- get_check_interval/0, set_check_interval/1,
- get_vm_memory_high_watermark/0, set_vm_memory_high_watermark/1]).
+ get_check_interval/0, set_check_interval/1,
+ get_vm_memory_high_watermark/0, set_vm_memory_high_watermark/1]).
-define(SERVER, ?MODULE).
-define(DEFAULT_MEMORY_CHECK_INTERVAL, 1000).
-%% For unknown OS, we assume that we have 512 MB of memory, which is pretty
-%% safe value, even for 32 bit systems. It's better to be slow than to crash.
+%% For unknown OS, we assume that we have 512 MB of memory, which is
+%% pretty safe value, even for 32 bit systems. It's better to be slow
+%% than to crash.
-define(MEMORY_SIZE_FOR_UNKNOWN_OS, 512*1024*1024).
-record(state, {total_memory,
@@ -72,17 +73,78 @@
}).
%%----------------------------------------------------------------------------
+%% gen_server callbacks
+%%----------------------------------------------------------------------------
start_link(Args) ->
gen_server2:start_link({local, ?SERVER}, ?MODULE, [Args], []).
+init([MemFraction]) ->
+ TotalMemory =
+ case get_total_memory(os:type()) of
+ unknown ->
+ rabbit_log:info("Unknown total memory size for your OS ~p. "
+ "Assuming memory size is ~p bytes.~n",
+ [os:type(), ?MEMORY_SIZE_FOR_UNKNOWN_OS]),
+ ?MEMORY_SIZE_FOR_UNKNOWN_OS;
+ M -> M
+ end,
+ MemLimit = get_mem_limit(MemFraction, TotalMemory),
+ rabbit_log:info("Memory limit set to ~pMiB.~n",
+ [trunc(MemLimit/1048576)]),
+ TRef = start_timer(?DEFAULT_MEMORY_CHECK_INTERVAL),
+ State = #state { total_memory = TotalMemory,
+ memory_limit = MemLimit,
+ timeout = ?DEFAULT_MEMORY_CHECK_INTERVAL,
+ timer = TRef,
+ alarmed = false},
+ {ok, internal_update(State)}.
+
+handle_call(get_vm_memory_high_watermark, _From, State) ->
+ {reply, State#state.memory_limit / State#state.total_memory, State};
+
+handle_call({set_vm_memory_high_watermark, MemFraction}, _From, State) ->
+ MemLimit = get_mem_limit(MemFraction, State#state.total_memory),
+ rabbit_log:info("Memory alarm changed to ~p, ~p bytes.~n",
+ [MemFraction, MemLimit]),
+ {reply, ok, State#state{memory_limit = MemLimit}};
+
+handle_call(get_check_interval, _From, State) ->
+ {reply, State#state.timeout, State};
+
+handle_call({set_check_interval, Timeout}, _From, State) ->
+ {ok, cancel} = timer:cancel(State#state.timer),
+ {reply, ok, State#state{timeout = Timeout, timer = start_timer(Timeout)}};
+
+handle_call(_Request, _From, State) ->
+ {noreply, State}.
+
+handle_cast(update, State) ->
+ {noreply, internal_update(State)};
+
+handle_cast(_Request, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%----------------------------------------------------------------------------
+%% Public API
+%%----------------------------------------------------------------------------
+
update() ->
gen_server2:cast(?SERVER, update).
-%%----------------------------------------------------------------------------
%% get_total_memory(OS) -> Total
%% Windows and Freebsd code based on: memsup:get_memory_usage/1
-%% Original code was part of OTP and released under "Erlang Public License".
+%% Original code was part of OTP and released under "Erlang Public
+%% License".
%% Darwin: Uses vm_stat command.
get_total_memory({unix,darwin}) ->
@@ -96,16 +158,16 @@ get_total_memory({unix,darwin}) ->
MemTotal = PageSize * (Inactive + Active + Free + Wired),
MemTotal;
-%% FreeBSD: Look in /usr/include/sys/vmmeter.h for the format of struct
-%% vmmeter
+%% FreeBSD: Look in /usr/include/sys/vmmeter.h for the format of
+%% struct vmmeter
get_total_memory({unix,freebsd}) ->
PageSize = freebsd_sysctl("vm.stats.vm.v_page_size"),
PageCount = freebsd_sysctl("vm.stats.vm.v_page_count"),
NMemTotal = PageCount * PageSize,
NMemTotal;
-%% Win32: Find out how much memory is in use by asking
-%% the os_mon_sysinfo process.
+%% Win32: Find out how much memory is in use by asking the
+%% os_mon_sysinfo process.
get_total_memory({win32,_OSname}) ->
[Result|_] = os_mon_sysinfo:get_mem_info(),
{ok, [_MemLoad, TotPhys, _AvailPhys,
@@ -127,11 +189,26 @@ get_total_memory({unix, sunos}) ->
Dict = dict:from_list(lists:map(fun parse_line_sunos/1, Lines)),
MemTotal = dict:fetch('Memory size', Dict),
MemTotal;
-
get_total_memory(_OsType) ->
unknown.
+get_check_interval() ->
+ gen_server2:call(?MODULE, get_check_interval).
+
+set_check_interval(Fraction) ->
+ gen_server2:call(?MODULE, {set_check_interval, Fraction}).
+
+get_vm_memory_high_watermark() ->
+ gen_server2:call(?MODULE, get_vm_memory_high_watermark).
+
+set_vm_memory_high_watermark(Fraction) ->
+ gen_server2:call(?MODULE, {set_vm_memory_high_watermark, Fraction}).
+
+%%----------------------------------------------------------------------------
+%% Internal Helpers
+%%----------------------------------------------------------------------------
+
%% A line looks like "Foo bar: 123456."
parse_line_mach(Line) ->
[Name, RHS | _Rest] = string:tokens(Line, ":"),
@@ -181,107 +258,37 @@ parse_line_sunos(Line) ->
[Name, RHS | _Rest] ->
[Value1 | UnitsRest] = string:tokens(RHS, " "),
Value2 = case UnitsRest of
- ["Gigabytes"] -> list_to_integer(Value1) * 1024 * 1024 * 1024;
- ["Megabytes"] -> list_to_integer(Value1) * 1024 * 1024;
- ["Kilobytes"] -> list_to_integer(Value1) * 1024;
- _ -> Value1 ++ UnitsRest %% no known units
- end,
+ ["Gigabytes"] ->
+ list_to_integer(Value1) * 1024 * 1024 * 1024;
+ ["Megabytes"] ->
+ list_to_integer(Value1) * 1024 * 1024;
+ ["Kilobytes"] ->
+ list_to_integer(Value1) * 1024;
+ _ ->
+ Value1 ++ UnitsRest %% no known units
+ end,
{list_to_atom(Name), Value2};
[Name] -> {list_to_atom(Name), none}
end.
-
-
-%%----------------------------------------------------------------------------
-
-%% On a 32-bit machine, if you're using more than 2 gigs of RAM
-%% you're in big trouble anyway.
+%% On a 32-bit machine, if you're using more than 2 gigs of RAM you're
+%% in big trouble anyway.
get_vm_limit() ->
case erlang:system_info(wordsize) of
4 -> 2*1024*1024*1024; % 2 GiB for 32 bits
8 -> 64*1024*1024*1024*1024 % 64 TiB for 64 bits
end.
-
get_mem_limit(MemFraction, TotalMemory) ->
- lists:min([trunc(TotalMemory * MemFraction),
- get_vm_limit()]).
-
-init([MemFraction]) ->
- TotalMemory = case get_total_memory(os:type()) of
- unknown ->
- rabbit_log:info("Unknown total memory size for your OS ~p. "
- "Assuming memory size is ~p bytes.~n",
- [os:type(), ?MEMORY_SIZE_FOR_UNKNOWN_OS]),
- ?MEMORY_SIZE_FOR_UNKNOWN_OS;
- M -> M
- end,
- MemLimit = get_mem_limit(MemFraction, TotalMemory),
- rabbit_log:info("Memory limit set to ~pMiB.~n",
- [trunc(MemLimit/1048576)]),
- TRef = start_timer(?DEFAULT_MEMORY_CHECK_INTERVAL),
- State = #state { total_memory = TotalMemory,
- memory_limit = MemLimit,
- timeout = ?DEFAULT_MEMORY_CHECK_INTERVAL,
- timer = TRef,
- alarmed = false},
- {ok, internal_update(State)}.
+ lists:min([trunc(TotalMemory * MemFraction), get_vm_limit()]).
start_timer(Timeout) ->
{ok, TRef} = timer:apply_interval(Timeout, ?MODULE, update, []),
TRef.
-
-get_check_interval() ->
- gen_server2:call(?MODULE, get_check_interval).
-
-set_check_interval(Fraction) ->
- gen_server2:call(?MODULE, {set_check_interval, Fraction}).
-
-get_vm_memory_high_watermark() ->
- gen_server2:call(?MODULE, get_vm_memory_high_watermark).
-
-set_vm_memory_high_watermark(Fraction) ->
- gen_server2:call(?MODULE, {set_vm_memory_high_watermark, Fraction}).
-
-
-handle_call(get_vm_memory_high_watermark, _From, State) ->
- {reply, State#state.memory_limit / State#state.total_memory, State};
-
-handle_call({set_vm_memory_high_watermark, MemFraction}, _From, State) ->
- MemLimit = get_mem_limit(MemFraction, State#state.total_memory),
- rabbit_log:info("Memory alarm changed to ~p, ~p bytes.~n",
- [MemFraction, MemLimit]),
- {reply, ok, State#state{memory_limit = MemLimit}};
-
-handle_call(get_check_interval, _From, State) ->
- {reply, State#state.timeout, State};
-
-handle_call({set_check_interval, Timeout}, _From, State) ->
- {ok, cancel} = timer:cancel(State#state.timer),
- {reply, ok, State#state{timeout = Timeout, timer = start_timer(Timeout)}};
-
-handle_call(_Request, _From, State) ->
- {noreply, State}.
-
-handle_cast(update, State) ->
- {noreply, internal_update(State)};
-
-handle_cast(_Request, State) ->
- {noreply, State}.
-
-handle_info(_Info, State) ->
- {noreply, State}.
-
-terminate(_Reason, _State) ->
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
emit_update_info(State, MemUsed, MemLimit) ->
rabbit_log:info("vm_memory_high_watermark ~p. Memory used:~p allowed:~p~n",
- [State, MemUsed, MemLimit]).
+ [State, MemUsed, MemLimit]).
internal_update(State = #state { memory_limit = MemLimit,
alarmed = Alarmed}) ->
@@ -296,6 +303,5 @@ internal_update(State = #state { memory_limit = MemLimit,
alarm_handler:clear_alarm(vm_memory_high_watermark);
_ ->
ok
- end,
+ end,
State #state {alarmed = NewAlarmed}.
-