Browse Source

部分代码整理

master
SisMaker 4 years ago
parent
commit
44d5bb0a53
10 changed files with 110 additions and 1794 deletions
  1. +0
    -1045
      src/dynamicCompile/smerl.erl
  2. +1
    -2
      src/dynamicCompile/utMMake.erl
  3. +2
    -2
      src/hotUpdate/h.erl
  4. +0
    -0
      src/measure/test.erl
  5. +0
    -0
      src/measure/tools.erl
  6. +22
    -0
      src/measure/utProf.erl
  7. +0
    -149
      src/srvNodeMgr/main.erl
  8. +0
    -350
      src/srvNodeMgr/mmake.erl
  9. +0
    -145
      src/srvNodeMgr/server_control_main.erl
  10. +85
    -101
      src/srvNodeMgr/utVMInfo.erl

+ 0
- 1045
src/dynamicCompile/smerl.erl
File diff suppressed because it is too large
View File


src/dynamicCompile/mmake.erl → src/dynamicCompile/utMMake.erl View File

@ -4,7 +4,7 @@
%% mods也可以包含多个模块,1,
%% process进行编译,.
-module(mmake).
-module(utMMake).
-include_lib("kernel/include/file.hrl").
-export([
@ -20,7 +20,6 @@ all(Worker) when is_integer(Worker) ->
all(Worker, []).
all(Worker, Options) when is_integer(Worker) ->
%% io:format("make all Options:~w", [Options]),
{MakeOpts, CompileOpts} = sort_options(Options, [], []),
case read_emakefile('Emakefile', CompileOpts) of
Files when is_list(Files) ->

+ 2
- 2
src/hotUpdate/h.erl View File

@ -46,10 +46,10 @@ h() ->
hh() ->
StartTime = unixtime(),
c:l(mmake),
c:l(utMMake),
io:format("----------makes----------~n", []),
c:cd("../"),
Res = (catch mmake:all(8, [netload])),
Res = (catch utMMake:all(8, [netload])),
c:cd("ebin"),
EndTime = unixtime(),
io:format("MMake result = ~p~nMMake Time : ~p s", [Res, EndTime - StartTime]),

src/srvNodeMgr/test.erl → src/measure/test.erl View File


src/srvNodeMgr/tools.erl → src/measure/tools.erl View File


+ 22
- 0
src/measure/utProf.erl View File

@ -43,3 +43,25 @@ fprof(M, F, A) ->
fprof:profile(),
fprof:analyse([{dest, "fprof.analysis"}, {sort, own}]),
fprof:stop().
%% ====================================================================
%% trace
%% mod MFA log args
%% trace Mod
%% --------------------------------------------------------------------
trace(Mod) ->
dbg:tracer(),
dbg:tpl(Mod, '_', []),
dbg:p(all, c).
%% trace Node上指定 Mod , shell
trace(Node, Mod) ->
dbg:tracer(),
dbg:n(Node),
dbg:tpl(Mod, '_', []),
dbg:p(all, c).
%% trace
trace_stop() ->
dbg:stop_clear().
%% ====================================================================

+ 0
- 149
src/srvNodeMgr/main.erl View File

@ -1,149 +0,0 @@
-module(main).
-export([
server_start/0,
server_stop/0,
server_stop/1,
is_running/0,
is_running/1,
reload/0,
info/0,
psl/0,
psl/1,
psl/2,
get_info/0
]).
-define(SERVER_APPS, [sasl, crypto, inets, ranch, os_mon, hot]).
server_start() ->
ok = application:load(hot),
app_misc:init(),
ok = start_applications(?SERVER_APPS).
%%
reload() ->
reloader:reload_all().
%%
server_stop() ->
server_stop(30).
is_running() ->
is_running(node()).
is_running(Node) ->
node_misc:is_process_running(Node, server).
%%
server_stop(_SleepSeconds) ->
app_misc:pause_accept(),
stop_applications(?SERVER_APPS),
ok.
info() ->
io:format("abormal termination:
~n Scheduler id: ~p
~n Num scheduler: ~p
~n Process count: ~p
~n Process limit: ~p
~n Memory used by erlang processes: ~p
~n Memory allocated by erlang processes: ~p
~n The total amount of memory allocated: ~p
~n",
get_info()),
ok.
get_info() ->
SchedId = erlang:system_info(scheduler_id),
SchedNum = erlang:system_info(schedulers),
ProcCount = erlang:system_info(process_count),
ProcLimit = erlang:system_info(process_limit),
ProcMemUsed = erlang:memory(processes_used),
ProcMemAlloc = erlang:memory(processes),
MemTot = erlang:memory(total),
[SchedId, SchedNum, ProcCount, ProcLimit,
ProcMemUsed, ProcMemAlloc, MemTot].
psl() ->
psl(100).
psl(Num) ->
lists:foldl(
fun(P, true) ->
case erlang:process_info(P, message_queue_len) of
{message_queue_len, Count} when Count > Num ->
print_process_info(P),
false;
_ ->
true
end;
(_, false) ->
false
end, true, erlang:processes()).
psl(ProcessPid, Num) ->
case erlang:process_info(ProcessPid, message_queue_len) of
{message_queue_len, Count} when Count > Num ->
print_process_info(ProcessPid);
_ ->
ok
end.
print_process_info(P) ->
io:format("~n~n=====process info===~n"
"~p~n~p~n~p~n~p~n~p~n~p~n~p~n~p~n~p~n~p~n~n~n",
[P,
erlang:process_info(P, registered_name),
erlang:process_info(P, current_function),
erlang:process_info(P, message_queue_len),
erlang:process_info(P, status),
erlang:process_info(P, suspending),
erlang:process_info(P, last_calls),
erlang:process_info(P, links),
erlang:process_info(P, dictionary),
erlang:process_info(P, current_stacktrace)
]).
%%##########################
manage_applications(Iterate, Do, Undo, SkipError, ErrorTag, Apps) ->
Iterate(fun(App, Acc) ->
case Do(App) of
ok -> [App | Acc];%
{error, {SkipError, _}} when is_atom(SkipError) ->
Acc;
{error, {Error, Reason}} when is_list(SkipError) ->
case lists:member(Error, SkipError) of
true ->
Acc;
false ->
io:format(
"App ~p, Reason ~p~n", [App, Reason]),
lists:foreach(Undo, Acc),
throw({error, {ErrorTag, App, Reason}})
end;
{error, Reason} ->
io:format("App ~p, Reason ~p~n", [App, Reason]),
lists:foreach(Undo, Acc),
throw({error, {ErrorTag, App, Reason}})
end
end, [], Apps),
ok.
start_applications(Apps) ->
manage_applications(fun lists:foldl/3,
fun application:start/1,
fun application:stop/1,
[already_started, cannot_start_application],
cannot_start_application,
Apps).
stop_applications(Apps) ->
io:format("stop_applications stopping.~n", []),
manage_applications(fun lists:foldr/3,
fun application:stop/1,
fun application:start/1,
not_started,
cannot_stop_application,
Apps).

+ 0
- 350
src/srvNodeMgr/mmake.erl View File

@ -1,350 +0,0 @@
%% ,otp/lib/tools/src/make.erl
%% Emakefile,{mods, options},
%% ()
%% mods也可以包含多个模块,1,
%% process进行编译,.
-module(mmake).
-export([all/1, all/2, files/2, files/3]).
-include_lib("kernel/include/file.hrl").
-define(MakeOpts, [noexec, load, netload, noload]).
all(Worker) when is_integer(Worker) ->
all(Worker, []).
all(Worker, Options) when is_integer(Worker) ->
{MakeOpts, CompileOpts} = sort_options(Options, [], []),
case read_emakefile('Emakefile', CompileOpts) of
Files when is_list(Files) ->
do_make_files(Worker, Files, MakeOpts);
error ->
error
end.
files(Worker, Fs) ->
files(Worker, Fs, []).
files(Worker, Fs0, Options) ->
Fs = [filename:rootname(F, ".erl") || F <- Fs0],
{MakeOpts, CompileOpts} = sort_options(Options, [], []),
case get_opts_from_emakefile(Fs, 'Emakefile', CompileOpts) of
Files when is_list(Files) ->
do_make_files(Worker, Files, MakeOpts);
error -> error
end.
do_make_files(Worker, Fs, Opts) ->
%io:format("worker:~p~nfs:~p~nopts:~p~n", [Worker, Fs, Opts]),
process(Fs, Worker, lists:member(noexec, Opts), load_opt(Opts)).
sort_options([H | T], Make, Comp) ->
case lists:member(H, ?MakeOpts) of
true ->
sort_options(T, [H | Make], Comp);
false ->
sort_options(T, Make, [H | Comp])
end;
sort_options([], Make, Comp) ->
{Make, lists:reverse(Comp)}.
%%% Reads the given Emakefile and returns a list of tuples: {Mods,Opts}
%%% Mods is a list of module names (strings)
%%% Opts is a list of options to be used when compiling Mods
%%%
%%% Emakefile can contain elements like this:
%%% Mod.
%%% {Mod,Opts}.
%%% Mod is a module name which might include '*' as wildcard
%%% or a list of such module names
%%%
%%% These elements are converted to [{ModList,OptList},...]
%%% ModList is a list of modulenames (strings)
read_emakefile(Emakefile, Opts) ->
case file:consult(Emakefile) of
{ok, Emake} ->
transform(Emake, Opts, [], []);
{error, enoent} ->
%% No Emakefile found - return all modules in current
%% directory and the options given at command line
Mods = [filename:rootname(F) || F <- filelib:wildcard("*.erl")],
[{Mods, Opts}];
{error, Other} ->
io:format("make: Trouble reading 'Emakefile':~n~p~n", [Other]),
error
end.
transform([{Mod, ModOpts} | Emake], Opts, Files, Already) ->
case expand(Mod, Already) of
[] ->
transform(Emake, Opts, Files, Already);
Mods ->
transform(Emake, Opts, [{Mods, ModOpts ++ Opts} | Files], Mods ++ Already)
end;
transform([Mod | Emake], Opts, Files, Already) ->
case expand(Mod, Already) of
[] ->
transform(Emake, Opts, Files, Already);
Mods ->
transform(Emake, Opts, [{Mods, Opts} | Files], Mods ++ Already)
end;
transform([], _Opts, Files, _Already) ->
lists:reverse(Files).
expand(Mod, Already) when is_atom(Mod) ->
expand(atom_to_list(Mod), Already);
expand(Mods, Already) when is_list(Mods), not is_integer(hd(Mods)) ->
lists:concat([expand(Mod, Already) || Mod <- Mods]);
expand(Mod, Already) ->
case lists:member($*, Mod) of
true ->
Fun = fun(F, Acc) ->
M = filename:rootname(F),
case lists:member(M, Already) of
true -> Acc;
false -> [M | Acc]
end
end,
lists:foldl(Fun, [], filelib:wildcard(Mod ++ ".erl"));
false ->
Mod2 = filename:rootname(Mod, ".erl"),
case lists:member(Mod2, Already) of
true -> [];
false -> [Mod2]
end
end.
%%% Reads the given Emakefile to see if there are any specific compile
%%% options given for the modules.
get_opts_from_emakefile(Mods, Emakefile, Opts) ->
case file:consult(Emakefile) of
{ok, Emake} ->
Modsandopts = transform(Emake, Opts, [], []),
ModStrings = [coerce_2_list(M) || M <- Mods],
get_opts_from_emakefile2(Modsandopts, ModStrings, Opts, []);
{error, enoent} ->
[{Mods, Opts}];
{error, Other} ->
io:format("make: Trouble reading 'Emakefile':~n~p~n", [Other]),
error
end.
get_opts_from_emakefile2([{MakefileMods, O} | Rest], Mods, Opts, Result) ->
case members(Mods, MakefileMods, [], Mods) of
{[], _} ->
get_opts_from_emakefile2(Rest, Mods, Opts, Result);
{I, RestOfMods} ->
get_opts_from_emakefile2(Rest, RestOfMods, Opts, [{I, O} | Result])
end;
get_opts_from_emakefile2([], [], _Opts, Result) ->
Result;
get_opts_from_emakefile2([], RestOfMods, Opts, Result) ->
[{RestOfMods, Opts} | Result].
members([H | T], MakefileMods, I, Rest) ->
case lists:member(H, MakefileMods) of
true ->
members(T, MakefileMods, [H | I], lists:delete(H, Rest));
false ->
members(T, MakefileMods, I, Rest)
end;
members([], _MakefileMods, I, Rest) ->
{I, Rest}.
%% Any flags that are not recognixed as make flags are passed directly
%% to the compiler.
%% So for example make:all([load,debug_info]) will make everything
%% with the debug_info flag and load it.
load_opt(Opts) ->
case lists:member(netload, Opts) of
true ->
netload;
false ->
case lists:member(load, Opts) of
true ->
load;
_ ->
noload
end
end.
%%
process([{[], _Opts} | Rest], Worker, NoExec, Load) ->
process(Rest, Worker, NoExec, Load);
process([{L, Opts} | Rest], Worker, NoExec, Load) ->
Len = length(L),
Worker2 = erlang:min(Len, Worker),
case catch do_worker(L, Opts, NoExec, Load, Worker2) of
error ->
error;
ok ->
process(Rest, Worker, NoExec, Load)
end;
process([], _Worker, _NoExec, _Load) ->
up_to_date.
%% worker进行编译
do_worker(L, Opts, NoExec, Load, Worker) ->
WorkerList = do_split_list(L, Worker),
%io:format("worker:~p worker list(~p)~n", [Worker, length(WorkerList)]),
%
Ref = make_ref(),
Pids =
[begin
start_worker(E, Opts, NoExec, Load, self(), Ref)
end || E <- WorkerList],
do_wait_worker(length(Pids), Ref).
%%
do_wait_worker(0, _Ref) ->
ok;
do_wait_worker(N, Ref) ->
receive
{ack, Ref} ->
do_wait_worker(N - 1, Ref);
{error, Ref} ->
throw(error);
{'EXIT', _P, _Reason} ->
do_wait_worker(N, Ref);
_Other ->
io:format("receive unknown msg:~p~n", [_Other]),
do_wait_worker(N, Ref)
end.
%% L分割成最多包含N个子列表的列表
do_split_list(L, N) ->
Len = length(L),
%
LLen = (Len + N - 1) div N,
do_split_list(L, LLen, []).
do_split_list([], _N, Acc) ->
lists:reverse(Acc);
do_split_list(L, N, Acc) ->
{L2, L3} = lists:split(erlang:min(length(L), N), L),
do_split_list(L3, N, [L2 | Acc]).
%% worker进程
start_worker(L, Opts, NoExec, Load, Parent, Ref) ->
Fun =
fun() ->
[begin
case recompilep(coerce_2_list(F), NoExec, Load, Opts) of
error ->
Parent ! {error, Ref},
exit(error);
_ ->
ok
end
end || F <- L],
Parent ! {ack, Ref}
end,
spawn_link(Fun).
recompilep(File, NoExec, Load, Opts) ->
ObjName = lists:append(filename:basename(File),
code:objfile_extension()),
ObjFile = case lists:keysearch(outdir, 1, Opts) of
{value, {outdir, OutDir}} ->
filename:join(coerce_2_list(OutDir), ObjName);
false ->
ObjName
end,
case exists(ObjFile) of
true ->
recompilep1(File, NoExec, Load, Opts, ObjFile);
false ->
recompile(File, NoExec, Load, Opts)
end.
recompilep1(File, NoExec, Load, Opts, ObjFile) ->
{ok, Erl} = file:read_file_info(lists:append(File, ".erl")),
{ok, Obj} = file:read_file_info(ObjFile),
recompilep1(Erl, Obj, File, NoExec, Load, Opts).
recompilep1(#file_info{mtime = Te},
#file_info{mtime = To}, File, NoExec, Load, Opts) when Te > To ->
recompile(File, NoExec, Load, Opts);
recompilep1(_Erl, #file_info{mtime = To}, File, NoExec, Load, Opts) ->
recompile2(To, File, NoExec, Load, Opts).
%% recompile2(ObjMTime, File, NoExec, Load, Opts)
%% Check if file is of a later date than include files.
recompile2(ObjMTime, File, NoExec, Load, Opts) ->
IncludePath = include_opt(Opts),
case check_includes(lists:append(File, ".erl"), IncludePath, ObjMTime) of
true ->
recompile(File, NoExec, Load, Opts);
false ->
false
end.
include_opt([{i, Path} | Rest]) ->
[Path | include_opt(Rest)];
include_opt([_First | Rest]) ->
include_opt(Rest);
include_opt([]) ->
[].
%% recompile(File, NoExec, Load, Opts)
%% Actually recompile and load the file, depending on the flags.
%% Where load can be netload | load | noload
recompile(File, true, _Load, _Opts) ->
io:format("Out of date: ~s\n", [File]);
recompile(File, false, noload, Opts) ->
io:format("Recompile: ~s\n", [File]),
compile:file(File, [report_errors, report_warnings, error_summary | Opts]);
recompile(File, false, load, Opts) ->
io:format("Recompile: ~s\n", [File]),
c:c(File, Opts);
recompile(File, false, netload, Opts) ->
io:format("Recompile: ~s\n", [File]),
c:nc(File, Opts).
exists(File) ->
case file:read_file_info(File) of
{ok, _} ->
true;
_ ->
false
end.
coerce_2_list(X) when is_atom(X) ->
atom_to_list(X);
coerce_2_list(X) ->
X.
%%% If you an include file is found with a modification
%%% time larger than the modification time of the object
%%% file, return true. Otherwise return false.
check_includes(File, IncludePath, ObjMTime) ->
Path = [filename:dirname(File) | IncludePath],
case epp:open(File, Path, []) of
{ok, Epp} ->
check_includes2(Epp, File, ObjMTime);
_Error ->
false
end.
check_includes2(Epp, File, ObjMTime) ->
case epp:parse_erl_form(Epp) of
{ok, {attribute, 1, file, {File, 1}}} ->
check_includes2(Epp, File, ObjMTime);
{ok, {attribute, 1, file, {IncFile, 1}}} ->
case file:read_file_info(IncFile) of
{ok, #file_info{mtime = MTime}} when MTime > ObjMTime ->
epp:close(Epp),
true;
_ ->
check_includes2(Epp, File, ObjMTime)
end;
{ok, _} ->
check_includes2(Epp, File, ObjMTime);
{eof, _} ->
epp:close(Epp),
false;
{error, _Error} ->
check_includes2(Epp, File, ObjMTime)
end.

+ 0
- 145
src/srvNodeMgr/server_control_main.erl View File

@ -1,145 +0,0 @@
-module(server_control_main).
-export([start/0]).
-define(RPC_TIMEOUT, infinity).
commands_desc() ->
[{"stop", "停止游戏服务器进程"},
{"stop_all", "停止游戏集群进程"},
{"stop_app", "关闭server application"},
{"start_app", "打开server application"},
{"cluster_status", "集群状态"}].
opt_spec_list() ->
Node = case get(nodename) of
undefined ->
throw(not_nodename);
V ->
V
end,
[
{help, $h, "help", undefined, "显示帮助,然后退出"},
{node, undefined, "node", {atom, Node}, "管理节点"}
].
usage() ->
getopt:usage(opt_spec_list(), "server_ctl", "<command> [<args>]", commands_desc()),
err_misc:quit(1).
parse_arguments(CmdLine) ->
case getopt:parse(opt_spec_list(), CmdLine) of
{ok, {Opts, [Command | Args]}} ->
{ok, {list_to_atom(Command), Opts, Args}};
{ok, {_Opts, []}} ->
no_command;
Error ->
io:format("Error ~p~n", [Error]),
no_command
end.
start() ->
{ok, [[NodeStr | _] | _]} = init:get_argument(nodename),
put(nodename, list_to_atom(NodeStr)),
{Command, Opts, Args} =
case parse_arguments(init:get_plain_arguments()) of
{ok, Res} ->
Res;
no_command ->
usage()
end,
Node = proplists:get_value(node, Opts),
net_adm:ping(Node),
timer:sleep(1000), %% wait auto find node
%% The reason we don't use a try/catch here is that rpc:call turns
%% thrown errors into normal return values
% io:format("Opts ~p~n", [Opts]),
case catch action(Command, Node, Args, Opts) of
ok ->
io:format("done.~n", []),
quit(0);
{ok, Info} ->
io:format("done (~p).~n", [Info]),
quit(0);
Other ->
io:format("other result ~p~n", [Other]),
quit(2)
end.
action(info, Node, _Args, _Opts) ->
io:format("System info for Node ~p~n", [Node]),
Res = call(Node, {main, get_info, []}),
io:format(" ~n Scheduler id: ~p
~n Num scheduler: ~p
~n Process count: ~p
~n Process limit: ~p
~n Memory used by erlang processes: ~p
~n Memory allocated by erlang processes: ~p
~n The total amount of memory allocated: ~p
~n",
Res),
ok;
action(backup, Node, _Args, _Opts) ->
case call(Node, {app_misc, backup, []}) of
{error, Msg} ->
io:format("~s~n", [Msg]);
{ok, FileName} ->
io:format("backup file:~s~n", [FileName]),
io:format("backup file to remote ......~n", []),
Result = os:cmd("bash copy_to_remote.sh " ++ FileName),
io:format("~s~n", [Result])
end,
ok;
action(pause_accept, Node, _Args, _Opts) ->
io:format("Pause accept new client ~p~n", [Node]),
call(Node, {app_misc, pause_accept, []}),
ok;
action(resume_accept, Node, _Args, _Opts) ->
io:format("Resume accept new client ~p~n", [Node]),
call(Node, {app_misc, resume_accept, []}),
ok;
action(accept_state, Node, _Args, _Opts) ->
Res = call(Node, {app_misc, can_accept_new, []}),
io:format("Node ~p accept state:~p~n ", [Node, Res]),
ok;
action(reload, Node, _Args, _Opts) ->
io:format("Reloading node ~p~n", [Node]),
call(Node, {main, reload, []});
action(stop_all, MasterNode, _Args, _Opts) ->
io:format("Stopping and halting all node~n", []),
PidMRefs = [{spawn_monitor(fun() ->
call(Node, {main, stop_and_halt, [5]})
end), Node}
|| Node <- nodes() -- [MasterNode]],
[receive
{'DOWN', MRef, process, _, normal} ->
ok;
{'DOWN', MRef, process, _, Reason} ->
io:format("Node ~p Error, Reason ~p", [Node, Reason])
end || {{_Pid, MRef}, Node} <- PidMRefs],
call(MasterNode, {main, stop_and_halt, [5]}),
ok;
action(stop, Node, _Args, _Opts) ->
io:format("Stopping and halting node ~p~n", [Node]),
call(Node, {main, stop_and_halt, [5]});
action(Command, _Node, Args, Opts) ->
io:format("Command: ~p Args: ~p Opts: ~p~n", [Command, Args, Opts]),
invalid_command.
call(Node, {Mod, Fun, Args}) ->
%%rpc_call(Node, Mod, Fun, lists:map(fun list_to_binary/1, Args)).
rpc_call(Node, Mod, Fun, Args).
rpc_call(Node, Mod, Fun, Args) ->
rpc:call(Node, Mod, Fun, Args, ?RPC_TIMEOUT).
quit(Status) ->
case os:type() of
{unix, _} ->
halt(Status);
{win32, _} ->
init:stop(Status),
receive
after infinity ->
ok
end
end.

+ 85
- 101
src/srvNodeMgr/utVMInfo.erl View File

@ -1,84 +1,100 @@
-module(utVMInfo).
-compile([export_all, nowarn_export_all]).
-export([
vmInfo/0 %%
, processInfo/1 %%
, processMqlInfo/0 %%
, processMqlInfo/1 %%
, showEtsCache/0 %%
, processHeapSize/0 %%
, processCnt/0 %%
, pstack/1 %%
, gcAll/0 %% process做gc gc不过来
, gcOne/1 %% process做gc gc不过来
, scheduler_usage/0 %% 1s每个调度器CPU的实际利用率(spin wait, usage top显示低很多)
, scheduler_usage/1 %% 1s每个调度器CPU的实际利用率(spin wait, usage top显示低很多)\
, scheduler_stat/0 %% 1s内调度进程数量()
, scheduler_stat/1 %% 1s内调度进程数量()
]).
%%
vmInfo() ->
io:format("abormal termination:
~n Scheduler id: ~p
~n Num scheduler: ~p
~n Process count: ~p
~n Process limit: ~p
~n Memory used by erlang processes: ~p
~n Memory allocated by erlang processes: ~p
~n The total amount of memory allocated: ~p
~n",
[erlang:system_info(scheduler_id), erlang:system_info(schedulers), erlang:system_info(process_count), erlang:system_info(process_limit), erlang:memory(processes_used), erlang:memory(processes), erlang:memory(total)]),
ok.
%%
processInfo(Pid) ->
io:format("~n~n=====process info===~n~p~n~p~n~p~n~p~n~p~n~p~n~p~n~p~n~p~n~p~n~n~n",
[
Pid,
erlang:process_info(Pid, registered_name),
erlang:process_info(Pid, current_function),
erlang:process_info(Pid, message_queue_len),
erlang:process_info(Pid, status),
erlang:process_info(Pid, suspending),
erlang:process_info(Pid, last_calls),
erlang:process_info(Pid, links),
erlang:process_info(Pid, dictionary),
erlang:process_info(Pid, current_stacktrace)
]).
%%
processMqlInfo() ->
processMqlInfo(100).
processMqlInfo(Num) ->
[processMqlInfo(Pid, Num) || Pid <- erlang:processes()],
ok.
%%
processMqlInfo(Pid, Num) ->
case erlang:process_info(Pid, message_queue_len) of
{message_queue_len, Count} when Count > Num ->
processInfo(Pid);
_ ->
ok
end.
%%
show_cache() ->
showEtsCache() ->
io:format("table name | memory | size~n", []),
lists:reverse(lists:keysort(2, [{T, ets:info(T, memory), ets:info(T, size)} || T <- ets:all()])).
%%
show_process() ->
%%
processHeapSize() ->
lists:reverse(lists:keysort(2, [{erlang:process_info(P, registered_name), erlang:process_info(P, heap_size)} || P <- erlang:processes()])).
%%
show_process_count() ->
length(erlang:processes()).
%%
%% 线reltools没掌握好
decompile(Mod) ->
{ok,{_,[{abstract_code,{_,AC}}]}} = beam_lib:chunks(code:which(Mod), [abstract_code]),
io:format("~s~n", [erl_prettypr:format(erl_syntax:form_list(AC))]).
%%
processCnt() ->
erlang:system_info(process_count).
%%
%% jstackhang住等问题用到
%% jstackhang住等问题用到
pstack(Reg) when is_atom(Reg) ->
case whereis(Reg) of
undefined -> undefined;
Pid -> pstack(Pid)
end;
pstack(Pid) ->
io:format("~s~n", [element(2, process_info(Pid, backtrace))]).
%% ====================================================================
%% etop
%% cpu占用进程使w进程node 使
%% CPU占用排名
%% --------------------------------------------------------------------
etop() ->
spawn(fun() -> etop:start([{output, text}, {interval, 10}, {lines, 20}, {sort, reductions}]) end).
%% Mem占用排名
etop_mem() ->
spawn(fun() -> etop:start([{output, text}, {interval, 10}, {lines, 20}, {sort, memory}]) end).
%% etop
etop_stop() ->
etop:stop().
%% ====================================================================
%% process做gc
%% gc不过来
gc_all() ->
case is_atom(Reg) andalso whereis(Reg) of
false -> io:format("~s~n", [element(2, erlang:process_info(Reg, backtrace))]);
undefined ->
undefined;
Pid -> io:format("~s~n", [element(2, erlang:process_info(Pid, backtrace))])
end.
%% process做gc gc不过来
gcAll() ->
[erlang:garbage_collect(Pid) || Pid <- processes()],
ok.
%% MFA
%% :
%% fprof
fprof(M, F, A) ->
fprof:start(),
fprof:apply(M, F, A),
fprof:profile(),
fprof:analyse(),
fprof:stop().
%% eprof, eprof 线,!
%% TimeoutSec<10s< 1000crash
%% :
%% mod调用执行时间
%% mod - Fun
eprof_all(TimeoutSec) ->
eprof(processes() -- [whereis(eprof)], TimeoutSec).
eprof(Pids, TimeoutSec) ->
eprof:start(),
eprof:start_profiling(Pids),
timer:sleep(TimeoutSec),
eprof:stop_profiling(),
eprof:analyze(total),
eprof:stop().
%% process做gc gc不过来
gcOne(Pid) ->
erlang:garbage_collect(Pid),
ok.
%% scheduler usage
%% 1s每个调度器CPU的实际利用率(spin wait, usage top显示低很多)
@ -112,27 +128,7 @@ scheduler_stat(RunMs) ->
lists:map(fun({{_Key, In0, Out0}, {Key, In1, Out1}}) ->
{Key, In1 - In0, Out1 - Out0} end, lists:zip(Ts0, Ts1)).
%% ====================================================================
%% trace
%% mod MFA log args
%% trace Mod
%% --------------------------------------------------------------------
trace(Mod) ->
dbg:tracer(),
dbg:tpl(Mod, '_', []),
dbg:p(all, c).
%% trace Node上指定 Mod , shell
trace(Node, Mod) ->
dbg:tracer(),
dbg:n(Node),
dbg:tpl(Mod, '_', []),
dbg:p(all, c).
%% trace
trace_stop() ->
dbg:stop_clear().
%% ====================================================================
%% OOM
%% etop 10w+ , proc后通过pstackmessage_queu_len
@ -367,19 +363,7 @@ ets_mem() ->
io:format("~-30w ~wKb~n", [Tab, Mem / 1024])
end, L1).
%% @spec tcp_links() -> Info
%% @doc tcp链接
tcp_links() ->
L = erlang:ports(),
F = fun(P) ->
Pinfo = erlang:port_info(P),
case lists:keyfind(name, 1, Pinfo) of
{name, "tcp_inet"} -> true;
_ -> false
end
end,
L1 = lists:filter(F, L),
io:format("~n当前socket数量(包括链接数据库的socket): ~w~n", [length(L1)]).
%% @doc

Loading…
Cancel
Save