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 + -
显示快捷键?