erts_alloc_config.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 586 行 · 第 1/2 页
ERL
586 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%%%%-------------------------------------------------------------------%%% File : erts_alloc_config.erl%%% Author : Rickard Green%%% Description : Generate an erts_alloc configuration suitable for%%% a limited amount of runtime scenarios.%%%%%% Created : 9 May 2007 by Rickard Green%%%--------------------------------------------------------------------module(erts_alloc_config).-record(state, {have_scenario = false, alloc}).-record(alloc, {name, enabled, alloc_util, low_mbc_blocks_size, high_mbc_blocks_size, sbct, segments}).-record(conf, {segments, format_to}).-record(segment, {size,number}).-define(PRINT_WITDH, 76).-define(SERVER, '__erts_alloc_config__').-define(KB, 1024).-define(MB, 1048576).-define(B2KB(B), ((((B) - 1) div ?KB) + 1)).-define(ROUNDUP(V, R), ((((V) - 1) div (R)) + 1)*(R)).-define(LARGE_GROWTH_ABS_LIMIT, 20*?MB).-define(MBC_MSEG_LIMIT, 150).-define(FRAG_FACT, 1.25).-define(GROWTH_SEG_FACT, 2).-define(MIN_SEG_SIZE, 1*?MB).-define(SMALL_GROWTH_SEGS, 5).-define(ALLOC_UTIL_ALLOCATOR(A), A == binary_alloc; A == std_alloc; A == ets_alloc; A == eheap_alloc; A == ll_alloc; A == sl_alloc; A == temp_alloc).-define(ALLOCATORS, [binary_alloc, ets_alloc, eheap_alloc, fix_alloc, ll_alloc, mseg_alloc, sl_alloc, std_alloc, sys_alloc, temp_alloc]).-define(MMBCS_DEFAULTS, [{binary_alloc, 131072}, {std_alloc, 131072}, {ets_alloc, 131072}, {eheap_alloc, 524288}, {ll_alloc, 2097152}, {sl_alloc, 131072}, {temp_alloc, 131072}]).-define(MMMBC_DEFAULTS, [{binary_alloc, 10}, {std_alloc, 10}, {ets_alloc, 10}, {eheap_alloc, 10}, {ll_alloc, 0}, {sl_alloc, 10}, {temp_alloc, 10}]).%%%%%% Exported interface%%%-export([save_scenario/0, make_config/0, make_config/1, stop/0]).%% Test and debug export-export([state/0]).save_scenario() -> req(save_scenario).make_config() -> make_config(group_leader()).make_config(FileName) when is_list(FileName) -> case file:open(FileName, [write]) of {ok, IODev} -> Res = req({make_config, IODev}), file:close(IODev), Res; Error -> Error end;make_config(IODev) -> req({make_config, IODev}).stop() -> req(stop).%% state() is intentionally undocumented, and is for testing%% and debugging only...state() -> req(state).%%%%%% Server%%%req(Req) -> Ref = make_ref(), ReqMsg = {request, self(), Ref, Req}, req(ReqMsg, Ref, true).req(ReqMsg, Ref, TryStart) -> req(ReqMsg, Ref, TryStart, erlang:monitor(process, ?SERVER)).req(ReqMsg, Ref, TryStart, Mon) -> (catch ?SERVER ! ReqMsg), receive {response, Ref, Res} -> erlang:demonitor(Mon, [flush]), Res; {'DOWN', Mon, _, _, noproc} -> case TryStart of true -> start_server(Ref, ReqMsg); false -> {error, server_died} end; {'DOWN', Mon, _, _, Reason} -> {error, Reason} end.start_server(Ref, ReqMsg) -> Starter = self(), Pid = spawn(fun () -> register(?SERVER, self()), Starter ! {Ref, self(), started}, server_loop(make_state()) end), Mon = erlang:monitor(process, Pid), receive {Ref, Pid, started} -> req(ReqMsg, Ref, false, Mon); {'DOWN', Mon, _, _, _} -> req(ReqMsg, Ref, false) end.server_loop(State) -> NewState = receive {request, From, Ref, save_scenario} -> Alloc = save_scenario(State#state.alloc), From ! {response, Ref, ok}, State#state{alloc = Alloc, have_scenario = true}; {request, From, Ref, {make_config, IODev}} -> case State#state.have_scenario of true -> Conf = #conf{segments = ?MBC_MSEG_LIMIT, format_to = IODev}, Res = mk_config(Conf, State#state.alloc), From ! {response, Ref, Res}; _ -> From ! {response, Ref, no_scenario_saved} end, State; {request, From, Ref, stop} -> From ! {response, Ref, ok}, exit(normal); {request, From, Ref, state} -> From ! {response, Ref, State}, State; {request, From, Ref, Req} -> From ! {response, Ref, {unknown_request, Req}}, State; _ -> State end, server_loop(NewState).make_state() -> #state{alloc = lists:map(fun (A) -> #alloc{name = A} end, ?ALLOCATORS)}.%%%% Save scenario%%ai_value(Key1, Key2, AI) -> case lists:keysearch(Key1, 1, AI) of {value, {Key1, Value1}} -> case lists:keysearch(Key2, 1, Value1) of {value, Result} -> Result; _ -> undefined end; _ -> undefined end.chk_mbcs_blocks_size(#alloc{low_mbc_blocks_size = undefined, high_mbc_blocks_size = undefined} = Alc, Min, Max) -> Alc#alloc{low_mbc_blocks_size = Min, high_mbc_blocks_size = Max, enabled = true};chk_mbcs_blocks_size(#alloc{low_mbc_blocks_size = LowBS, high_mbc_blocks_size = HighBS} = Alc, Min, Max) -> true = is_integer(LowBS), true = is_integer(HighBS), Alc1 = case Min < LowBS of true -> Alc#alloc{low_mbc_blocks_size = Min}; false -> Alc end, case Max > HighBS of true -> Alc1#alloc{high_mbc_blocks_size = Max}; false -> Alc1 end.set_alloc_util(#alloc{alloc_util = AU} = Alc, AU) -> Alc;set_alloc_util(Alc, Val) -> Alc#alloc{alloc_util = Val}.chk_sbct(#alloc{sbct = undefined} = Alc, AI) -> case ai_value(options, sbct, AI) of {sbct, Bytes} when is_integer(Bytes) -> Alc#alloc{sbct = b2kb(Bytes)}; _ -> Alc end;chk_sbct(Alc, _AI) -> Alc.save_scenario(AlcList) -> %% The high priority is not really necessary. It is %% used since it will make retrieval of allocator %% information less spread out in time on a highly %% loaded system. OP = process_flag(priority, high), Res = do_save_scenario(AlcList), process_flag(priority, OP), Res. do_save_scenario(AlcList) -> lists:map(fun (#alloc{enabled = false} = Alc) -> Alc; (#alloc{name = Name} = Alc) -> case erlang:system_info({allocator, Name}) of undefined -> exit({bad_allocator_name, Name}); false -> Alc#alloc{enabled = false}; AI when is_list(AI) -> Alc1 = chk_sbct(Alc, AI), case ai_value(mbcs, blocks_size, AI) of
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?