From 1cd8bceae278d4d63597ea29bd553f48d392dd9a Mon Sep 17 00:00:00 2001 From: SisMaker <1713699517@qq.com> Date: Tue, 22 Dec 2020 19:37:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/comMisc/cast_and_call.erl | 54 --- src/comMisc/loop.erl | 34 -- src/comMisc/misc.erl | 390 ---------------- src/comMisc/misc_admin.erl | 355 --------------- src/comMisc/prof.erl | 25 - src/comMisc/tool.erl | 651 --------------------------- src/comMisc/utMisc.erl | 6 - src/comMisc/{misc1.erl => utPid.erl} | 134 ++---- src/profTrace/utProf.erl | 45 ++ src/srvNodeMgr/utVMInfo.erl | 311 ++++++++++++- 10 files changed, 383 insertions(+), 1622 deletions(-) delete mode 100644 src/comMisc/cast_and_call.erl delete mode 100644 src/comMisc/loop.erl delete mode 100644 src/comMisc/misc.erl delete mode 100644 src/comMisc/misc_admin.erl delete mode 100644 src/comMisc/prof.erl delete mode 100644 src/comMisc/tool.erl rename src/comMisc/{misc1.erl => utPid.erl} (79%) create mode 100644 src/profTrace/utProf.erl diff --git a/src/comMisc/cast_and_call.erl b/src/comMisc/cast_and_call.erl deleted file mode 100644 index f3ab4a0..0000000 --- a/src/comMisc/cast_and_call.erl +++ /dev/null @@ -1,54 +0,0 @@ -%%%--------------------------------------------- -%%% @module : cast_and_call -%%% @Author : csj -%%% @Created : 2010.10.05 -%%% @description: gen_server cast and call 测试 -%%% @result:cast 要比call 快0.006毫秒 -%%%--------------------------------------------- --module(cast_and_call). --behaviour(gen_server). - -%%Interface functions. --export([start/0, test/0]). - -%%gen_server callbacks --export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). - -start() -> - gen_server:start(?MODULE, [], []). - -init([]) -> - {ok, 1}. - -handle_cast('TEST', Status) -> - %%io:format("This is cast. ~n"), - {noreply, Status}. - -handle_call('TEST', _FROM, Status) -> - %%io:format("This is call. ~n"), - {reply, ok, Status}. - -handle_info(_Info, Status) -> - {noreply, Status}. - -terminate(normal, Status) -> - {ok, Status}. - -code_change(_OldVsn, Status, _Extra) -> - {ok, Status}. - -test() -> - {ok, Pid} = start(), - fprof:apply(gen_server, call, [Pid, 'TEST']), - fprof:profile(), - fprof:analyse({dest, "call.analysis"}), - fprof:apply(gen_server, cast, [Pid, 'TEST']), - fprof:profile(), - fprof:analyse({dest, "cast.analysis"}), - F1 = fun() -> gen_server:call(Pid, 'TEST') end, - F2 = fun() -> gen_server:cast(Pid, 'TEST') end, - prof:run(F1, 100000), - prof:run(F2, 100000). - - - diff --git a/src/comMisc/loop.erl b/src/comMisc/loop.erl deleted file mode 100644 index 8d9afa3..0000000 --- a/src/comMisc/loop.erl +++ /dev/null @@ -1,34 +0,0 @@ -%%%--------------------------------------------- -%%% @Module : loop -%%% @Author : csj -%%% @Created : 2010.10.05 -%%% @Description: 测试循环性能 -%%% @Resule : F2 比 F1 快20毫秒 不到10000基本可以忽略不计 -%%%--------------------------------------------- --module(loop). --compile(export_all). - - - - -do_loop([], _Data) -> ok; -do_loop([[_S] | T], Data) -> - do_loop(T, Data). - -do_loop2([], _Data, _X) -> ok; -do_loop2([[S] | T], Data, X) when S == X -> - do_loop2(T, Data, X); -do_loop2([[_S] | T], Data, X) -> - do_loop2(T, Data, X). - -test() -> - F1 = fun() -> - L = [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]], - do_loop2(L, <<16:16>>, [8]) - end, - F2 = fun() -> - L = [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]], - do_loop(lists:delete([8], L), <<16:16>>) - end, - prof:run(F1, 100000), - prof:run(F2, 100000). diff --git a/src/comMisc/misc.erl b/src/comMisc/misc.erl deleted file mode 100644 index 02e9c98..0000000 --- a/src/comMisc/misc.erl +++ /dev/null @@ -1,390 +0,0 @@ --module(misc). -%% -%% Exported Functions -%% --export([ - whereis_name/1, - register/3, - unregister/2, - is_process_alive/1, - % t/1, - % t/2, - % tr/1, - % tun/1, - % tan/1, - % t_clear/0, - dump_process_info/1 - , ets_mem/0 - , tcp_links/0 - , top_back/0 - , top/0 - , request/1 -]). - --export([ - check_mem/1 -]). - --export([ - pstack/1 - , etop/0 - , etop_mem/0 - , etop_stop/0 - , gc_all/0 - - , fprof/3 - , eprof_all/1 - , eprof/2 - - , scheduler_usage/0 - , scheduler_usage/1 - - , scheduler_stat/0 - , scheduler_stat/1 - - , trace/1 - , trace/2 - , trace_stop/0 - - , crash_dump/0 - , process_infos/0 -]). - - -%% @doc 节点所有进程信息 -process_infos() -> - filelib:ensure_dir("./logs/"), - File = "./logs/processes_infos.log", - {ok, Fd} = file:open(File, [write, raw, binary, append]), - Fun = fun(Pi) -> - Info = io_lib:format("=>~p \n\n", [Pi]), - case filelib:is_file(File) of - true -> file:write(Fd, Info); - false -> - file:close(Fd), - {ok, NewFd} = file:open(File, [write, raw, binary, append]), - file:write(NewFd, Info) - end, - timer:sleep(20) - end, - [Fun(erlang:process_info(P)) || P <- erlang:processes()]. - - -%% @doc erlang_dump -crash_dump() -> - Date = erlang:list_to_binary(rfc1123_local_date()), - Header = binary:list_to_bin([<<"=erl_crash_dump:0.2\n">>, Date, <<"\nSystem version: ">>]), - Ets = ets_info(), - Report = binary:list_to_bin([Header, erlang:list_to_binary(erlang:system_info(system_version)), - erlang:system_info(info), erlang:system_info(procs), Ets, erlang:system_info(dist), - <<"=loaded_modules\n">>, binary:replace(erlang:system_info(loaded), - <<"\n">>, <<"\n=mod:">>, [global])]), - file:write_file("erl_crash.dump", Report). - -ets_info() -> - binary:list_to_bin([ets_table_info(T) || T <- ets:all()]). - -ets_table_info(Table) -> - Info = ets:info(Table), - Owner = erlang:list_to_binary(erlang:pid_to_list(proplists:get_value(owner, Info))), - TableN = erlang:list_to_binary(erlang:atom_to_list(proplists:get_value(name, Info))), - Name = erlang:list_to_binary(erlang:atom_to_list(proplists:get_value(name, Info))), - Objects = erlang:list_to_binary(erlang:integer_to_list(proplists:get_value(size, Info))), - binary:list_to_bin([<<"=ets:">>, Owner, <<"\nTable: ">>, TableN, <<"\nName: ">>, Name, - <<"\nObjects: ">>, Objects, <<"\n">>]). - -rfc1123_local_date() -> - rfc1123_local_date(os:timestamp()). -rfc1123_local_date({A, B, C}) -> - rfc1123_local_date(calendar:now_to_local_time({A, B, C})); -rfc1123_local_date({{YYYY, MM, DD}, {Hour, Min, Sec}}) -> - DayNumber = calendar:day_of_the_week({YYYY, MM, DD}), - lists:flatten( - io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT", - [httpd_util:day(DayNumber), DD, httpd_util:month(MM), YYYY, Hour, Min, Sec])); -rfc1123_local_date(Epoch) when erlang:is_integer(Epoch) -> - rfc1123_local_date(calendar:gregorian_seconds_to_datetime(Epoch + 62167219200)). - - -%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(). - -% 统计下1s内调度进程数量(含义:第一个数字执行进程数量,第二个数字迁移进程数量) -scheduler_stat() -> - scheduler_stat(1000). - -scheduler_stat(RunMs) -> - erlang:system_flag(scheduling_statistics, enable), - Ts0 = erlang:system_info(total_scheduling_statistics), - timer:sleep(RunMs), - Ts1 = erlang:system_info(total_scheduling_statistics), - erlang:system_flag(scheduling_statistics, disable), - lists:map(fun({{Key, In0, Out0}, {Key, In1, Out1}}) -> - {Key, In1 - In0, Out1 - Out0} end, lists:zip(Ts0, Ts1)). - -% 统计下1s每个调度器CPU的实际利用率(因为有spin wait、调度工作, 可能usage 比top显示低很多) -scheduler_usage() -> - scheduler_usage(1000). - -scheduler_usage(RunMs) -> - erlang:system_flag(scheduler_wall_time, true), - Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), - timer:sleep(RunMs), - Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), - erlang:system_flag(scheduler_wall_time, false), - Cores = lists:map(fun({{I, A0, T0}, {I, A1, T1}}) -> - {I, (A1 - A0) / (T1 - T0)} end, lists:zip(Ts0, Ts1)), - {A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai, Ti}) -> - {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0, Ts1)), - Total = A / T, - io:format("~p~n", [[{total, Total} | Cores]]). - -% 对整个节点内所有进程执行eprof, eprof 对线上业务有一定影响,慎用! -% 建议TimeoutSec<10s,且进程数< 1000,否则可能导致节点crash -% 结果: -% 输出每个方法实际执行时间(不会累计方法内其他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(). - -% @doc 对MFA 执行分析,会严重减缓运行,建议只对小量业务执行 -% 结果: -% fprof 结果比较详细,能够输出热点调用路径 -fprof(M, F, A) -> - fprof:start(), - fprof:apply(M, F, A), - fprof:profile(), - fprof:analyse([{dest, "fprof.analysis"}, {sort, own}]), - fprof:stop(). - -% @doc 对所有process做gc -gc_all() -> - [erlang:garbage_collect(Pid) || Pid <- processes()]. - -% @doc 进程CPU占用排名 -etop() -> - spawn(fun() -> etop:start([{output, text}, {interval, 10}, {lines, 20}, {sort, runtime}]) end). - -% @doc 进程Mem占用排名 -etop_mem() -> - spawn(fun() -> etop:start([{output, text}, {interval, 10}, {lines, 20}, {sort, memory}]) end). - -% @doc 停止etop -etop_stop() -> - etop:stop(). - -%% @doc 类似于jstack,发现大量进程挂起,进程数过高,运行慢,hang住等问题用到 -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))]). - - - - -%% 检查溢出的内存,强制gc, 并写入日志分析 -check_mem(MemLim) -> - lists:foreach( - fun(P) -> - case is_pid(P) andalso erlang:is_process_alive(P) of - true -> - {memory, Mem} = erlang:process_info(P, memory), - case Mem > MemLim of - true -> - erlang:garbage_collect(P); - false -> - [] - end; - false -> - [] - end - end, erlang:processes()). - -%% @doc 寻找PID -whereis_name({local, Atom}) -> - erlang:whereis(Atom); - -whereis_name({global, Atom}) -> - global:whereis_name(Atom). - -register(local, Name, Pid) -> - erlang:register(Name, Pid); - -register(global, Name, Pid) -> - global:re_register_name(Name, Pid). - -unregister(local, Name) -> - erlang:unregister(Name); -unregister(global, Name) -> - global:unregister_name(Name). - -is_process_alive(Pid) -> - try - case Pid of - _ when is_pid(Pid) -> - Node = node(), - Result = case node(Pid) of - Node -> erlang:is_process_alive(Pid); - Node1 -> rpc:call(Node1, erlang, is_process_alive, [Pid]) - end, - case Result of - {badrpc, _Reason} -> false; - Res -> Res - end; - _ -> false - end - catch - _:_ -> false - end. - -%% @spec top() -> ok -%% @doc 查看系统当前的综合信息 -top() -> - Release = erlang:system_info(otp_release), - SchedNum = erlang:system_info(schedulers), - ProcCount = erlang:system_info(process_count), - ProcLimit = erlang:system_info(process_limit), - ProcMemUsed = erlang:memory(processes_used), - EtsMemAlc = erlang:memory(ets), - MemTot = erlang:memory(total), - %PetNum = all_pets(), - io:format( - "++++++++++++++++++++++++++++++++++++++++++~n" - " Node: ~p~n" - " Erlang Ver: ~p~n" - " Free Threads: ~p~n" - " Process Used Memory: ~pMb~n" - " Ets Used Memory: ~pMb~n" - " Erlang VM Used Memory: ~pMb~n" - " Process Limit: ~p~n" - " Process Used: ~p~n" - "++++++++++++++++++++++++++++++++++++++++++~n" - , [node(), Release, SchedNum, ProcMemUsed / 1024 / 1024, EtsMemAlc / 1024 / 1024, MemTot / 1024 / 1024, ProcLimit, ProcCount]), - ok. - -%% @doc 运维要用 -top_back() -> - Release = erlang:system_info(otp_release), - SchedNum = erlang:system_info(schedulers), - ProcCount = erlang:system_info(process_count), - ProcLimit = erlang:system_info(process_limit), - ProcMemUsed = erlang:memory(processes_used), - EtsMemAlc = erlang:memory(ets), - MemTot = erlang:memory(total), - Str = io_lib:format( - " Erlang 版本: ~p~n" - " 可使用的调度线程: ~p~n" - " 所有进程使用的内存: ~pMb~n" - " 所有ets使用的内存: ~pMb~n" - " Erlang系统占用内存: ~pMb~n" - " 可创建进程数量上限: ~p~n" - " 当前进程数: ~p~n" - , [Release, SchedNum, ProcMemUsed / 1024 / 1024, EtsMemAlc / 1024 / 1024, MemTot / 1024 / 1024, ProcLimit, ProcCount]), - binary_to_list(list_to_binary(Str)). - -%% @spec ets_mem() -> term() -%% @doc 查看内存占用最多的30张ets表 -ets_mem() -> - L = ets:all(), - Mems = lists:map(fun(Tab) -> - Info = ets:info(Tab), - case lists:keyfind(memory, 1, Info) of - {memory, Mem} -> {Tab, Mem}; - _ -> {Tab, 0} - end - end, L), - L1 = lists:sublist(lists:reverse(lists:keysort(2, Mems)), 30), - io:format("~n--------------------------------------------------~n" - "~-30w ~w~n--------------------------------------------------~n" - , [table, used_memory]), - lists:foreach( - fun({Tab, 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 备份进程信息 -dump_process_info(Pid) -> - {{Year, Month, Day}, {Hour, Minutes, Second}} = util:local_time(), - {ok, FileHandle} = file:open(util:fbin("~s-~w-~w-~w-~w-~w-~w", [<<"../logs/pid_info.dump">>, Year, Month, Day, Hour, Minutes, Second]), write), - case erlang:process_info(Pid) of - Info when is_list(Info) -> - lists:foreach(fun({messages, Messages}) -> - case Messages =:= [] of - true -> - io:format(FileHandle, "~w~n", [{messages, Messages}]); - _ -> - io:format(FileHandle, "{messages,~n", []), - lists:foreach(fun(M) -> - io:format(FileHandle, " ~w~n", [M]) - end, Messages), - io:format(FileHandle, "}~n", []) - end; - ({dictionary, Dics}) -> - case Dics =:= [] of - true -> - io:format(FileHandle, "~w~n", [{dictionary, Dics}]); - _ -> - io:format(FileHandle, "{dictionary,~n", []), - lists:foreach(fun(M) -> - io:format(FileHandle, " ~w~n", [M]) - end, Dics), - io:format(FileHandle, "}~n", []) - end; - (E) -> - io:format(FileHandle, "~w~n", [E]) - end, Info); - _ -> - io:format("not find pid info") - end, - file:close(FileHandle). - -request(Url) -> - {ok, RequestId} = httpc:request(get, {Url, []}, [], [{sync, false}]), - receive - {http, {RequestId, {{_Version, 200, _ReasonPhrase}, _Headers, Body}}} -> - Body; - E -> - E - after 500 -> - timeout - end. \ No newline at end of file diff --git a/src/comMisc/misc_admin.erl b/src/comMisc/misc_admin.erl deleted file mode 100644 index 57dfb83..0000000 --- a/src/comMisc/misc_admin.erl +++ /dev/null @@ -1,355 +0,0 @@ --module(misc_admin). - -%%返回码 --define(PARAM_ERROR_CODE, <<"param_error">>). % 参数错误 --define(FLAG_ERROR_CODE, <<"flag_error">>). % 验证失败 --define(FAILED_CODE, <<"failed">>). % 发送消息失败,服务器异常 --define(SUCCESS_CODE, <<"success">>). % 成功 --define(INFO_MSG, io:format). --define(TRACE, io:format). --compile(export_all). - - - -%% 消息广播 -do_handle_request("send_sys_bulletin", KvList, Socket) -> - MsgType = list_to_integer(http_util:get_param("msg_type", KvList)), - Content = http_util:get_param("content", KvList), - cast_to_server(lib_chat, broadcast_sys_msg, [MsgType, Content]), -%% lib_chat:broadcast_sys_msg("test"), - ?INFO_MSG("type:~p content:~ts ~n", [MsgType, Content]), - - gen_tcp:send(Socket, <<"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nhello world!">>); -% gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 发送邮件 -do_handle_request("send_mail", KvList, Socket) -> - ok; -%% Action = http_util:get_param("action", KvList), -%% UserNames = http_util:get_param("user_names", KvList), -%% UserIds = http_util:get_param("user_ids", KvList), -%% MailTitle = http_util:get_param("mail_title", KvList), -%% MailConten = http_util:get_param("mail_content", KvList), -%% UserNameList = string:tokens(UserNames, ","), -%% UserIdList = string:tokens(UserIds, ","), -%% if -%% Action =:= 1 -> % 只对参数 user_names 和 user_ids 指定的用户发送 -%% cast_to_server(lib_mail, broadcast_sys_msg, [Action, UserNameList, UserIdList, MailTitle, MailConten]); -%% Action =:= 2 -> % 只对符合"条件参数"的所有用户发送,“条件参数”包括下列条件 -%% cast_to_server(lib_mail, broadcast_sys_msg, [MsgType, Content]); -%% Action =:= 3 -> % 只对当前在线玩家发送 -%% cast_to_server(lib_mail, broadcast_sys_msg, [Action, MailTitle, MailConten]); -%% true -> -%% ok -%% end, -%% ?INFO_MSG("Action:~p title:~ts content:~ts ~n", [Action, MailTitle, MailConten]), -%% gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% GM回复玩家接口 -do_handle_request("complain_reply", KvList, Socket) -> - UserName = http_util:get_param("user_name", KvList), - Conten = http_util:get_param("content", KvList), - CompainId = http_util:get_param("compain_id", KvList), - cast_to_server(lib_mail, broadcast_sys_msg, [CompainId, UserName, Conten]), - ?INFO_MSG("CompainId:~p UserName::~ts content:~ts ~n", [CompainId, UserName, Conten]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 封禁/解封 账号 -do_handle_request("forbid_login", KvList, Socket) -> - UserNames = http_util:get_param("user_names", KvList), - IsForbid = http_util:get_param("is_forbid", KvList), - ForbidTime = - case http_util:get_param("forbid_time", KvList) of - [] -> 0; - ForbidTime1 -> list_to_integer(ForbidTime1) - end, - Reason = http_util:get_param("reason", KvList), - UserNameList = string:tokens(UserNames, ","), - cast_to_server(lib_admin, ban_role, [UserNameList, list_to_integer(IsForbid), ForbidTime, Reason]), - ?INFO_MSG("IsForbid:~p ~n ForbidTime:~p ~n UserName:~ts ~n list:~ts ~n Reason:~ts ~n", - [IsForbid, ForbidTime, UserNames, UserNameList, Reason]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 封禁/解禁 IP -do_handle_request("ip_ban", KvList, Socket) -> - IP = http_util:get_param("ip", KvList), - IsForbid = http_util:get_param("is_forbid", KvList), - ForbidTime = - case http_util:get_param("forbid_time", KvList) of - [] -> 0; - ForbidTime1 -> list_to_integer(ForbidTime1) - end, - Reason = http_util:get_param("reason", KvList), - IpList = string:tokens(IP, ","), - cast_to_server(lib_admin, ban_ip, [IpList, list_to_integer(IsForbid), ForbidTime, Reason]), - ?INFO_MSG("IsForbid:~p ForbidTime:~p IP:~ts Reason:~ts ~n", [IsForbid, ForbidTime, IP, Reason]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 踢人接口 -do_handle_request("kick_user", KvList, Socket) -> - UserNames = http_util:get_param("user_names", KvList), - KillFlag = list_to_integer(http_util:get_param("kick_all", KvList)), - Reason = http_util:get_param("reason", KvList), - if - KillFlag =:= 0 -> % 存在多个以逗号分隔 - UserNameList = string:tokens(UserNames, ","), - cast_to_server(lib_admin, kick_user, [UserNameList, Reason]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - KillFlag =:= 1 -> % 踢出所有玩家 - cast_to_server(lib_admin, kick_all_user, []), - gen_tcp:send(Socket, ?SUCCESS_CODE); - true -> - gen_tcp:send(Socket, ?PARAM_ERROR_CODE) - end, - ?INFO_MSG("KillFlag:~p Reason:~ts UserNames:~ts ~n", [KillFlag, Reason]); - -%% 禁言 / 解禁 -do_handle_request("ban_chat", KvList, Socket) -> - UserNames = http_util:get_param("user_names", KvList), - BanFlag = list_to_integer(http_util:get_param("is_ban", KvList)), - BanTime1 = http_util:get_param("ban_date", KvList), % 0=永久禁言,否则以此作为时间戳,代表封号结束时间 - BanTime = - case BanTime1 =:= [] of - true -> 0; - false -> list_to_integer(BanTime1) - end, - Reason = http_util:get_param("reason", KvList), - UserNameList = string:tokens(UserNames, ","), - cast_to_server(lib_admin, donttalk, [UserNameList, BanFlag, BanTime, Reason]), %1=禁言; 0=解禁 - ?INFO_MSG("BanFlag:~p BanTime:~p Reason:~ts UserNames:~ts ~n", [BanFlag, BanTime, Reason, UserNames]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 新手指导员接口 -do_handle_request("game_instructor_manage", KvList, Socket) -> - UserName = http_util:get_param("user_name", KvList), - Type = http_util:get_param("type", KvList), %1=禁言 0=解禁 - InstructorType = http_util:get_param("instructor_type", KvList), %1.菜鸟指导员 2.指导员达人3.新手导师4.长期指导员5.GM - StartTime = http_util:get_param("start_time", KvList), - EndTime = http_util:get_param("end_time", KvList), -%% cast_to_server(lib_mail, broadcast_sys_msg, [UserName, Type, InstructorType, StartTime, EndTime]), - ?INFO_MSG("Type:~p InstructorType:~p StartTime:~p EndTime:~p UserName:~ts ~n", [Type, InstructorType, StartTime, EndTime, UserName]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 重置玩家位置 -do_handle_request("reset_user_pos", KvList, Socket) -> - UserName = http_util:get_param("user_name", KvList), -%% cast_to_server(lib_mail, broadcast_sys_msg, UserName), - ?INFO_MSG("content:~ts ~n", [UserName]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 查询满足条件的玩家数量 -do_handle_request("count_user", KvList, Socket) -> - ok; - -%% 单个玩家详细信息接口 -do_handle_request("user_info_detail", KvList, Socket) -> - UserId = http_util:get_param("user_id", KvList), - UserName = http_util:get_param("user_name", KvList), - Account = http_util:get_param("account", KvList), - % 三个参数并不是互斥的关系,有可以三个都传,有可能只传两个。它们之间在SQL语句里面是and的关系 -%% case call_to_server(lib_admin, get_player_info, [UserId, UserName, Account]) of -%% {badrpc, _} -> -%% gen_tcp:send(Socket, ?FAILED_CODE); -%% Player -> -%% RetMsg = <<>>, -%% gen_tcp:send(Socket, ?SUCCESS_CODE) -%% end, - ?INFO_MSG("UserId:~p UserName:~ts Account:~ts ~n", [UserId, UserName, Account]); - - -% desc {"字段名":"字段中文含义"} 如:{"user_name":"角色名称",user_id":"角色ID"} -% data data 中必须包含以下基本信息: -% 字段 含义 -% account 玩家平台账号 -% user_id 玩家ID -% user_name 玩家角色名 -% reg_time 角色创建时间 -% level 玩家等级 -% last_login_ip 玩家最后登陆IP -% last_login_time 玩家最后登陆时间 -% country 玩家阵营名称(若玩家没有阵营,则返回-1) -% guild 玩家帮派名称(若玩家没有帮派,则返回-1) -% career 玩家职业名称(若玩家没有职业,则返回-1) -% 自定义信息(下面标红部分),游戏方可自行添加。 自定义信息与基本信息返回方式一致: -% -% { -% "account":"gfsyra", -% "user_id":"221", -% "user_name":"高富帅有人爱", -% "reg_time":"1371928400", -% "level":"22", -% "reg_time":"22", -% "last_login_ip":"94.123.22.123", -% "last_login_time":"1388928400", -% "country":"魏国", -% "guild":"超级兵马俑", -% "career":"魏将", -% "is_vip":"y", -% "sex":"1", -% ...... -% - -%% 玩家信息列表 -do_handle_request("user_info_list", KvList, Socket) -> - ok; - -%% 单个帮派详细信息接口 -do_handle_request("guild_info_detail", KvList, Socket) -> - GuildId = http_util:get_param("guild_id", KvList), - GuildName = http_util:get_param("guild_name", KvList), -%% call_to_server(lib_mail, broadcast_sys_msg, [GuildId, GuildName]), - ?INFO_MSG("type:~p content:~ts ~n", [GuildId, GuildName]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -% data 中必须包含以下基本信息: -% 字段 含义 -% guild_id 帮派ID -% guild_name 帮派名称 -% guild_level 帮派等级 -% guild_ranking 帮派排名 -% leader 帮忙创建者 -% create_time 创建时间 -% member_count 帮派人数 -% member_list 玩家列表,json数组格式 -% 自定义信息(下面标红部分),游戏方可自行添加。 自定义信息与基本信息返回方式一致: -% -% { -% "guild_id":"1234", -% "guild_name":"高富帅帮", -% "guild_level":"2", -% "guild_ranking":"1", -% "member_count":"3", -% "member_list":[ -% "高", "富","帅","高富帅有人爱" -% ], -% "leader":"高富帅有人爱", -% "create_time":"1388928400", -% "is_vip":"y", -% ...... -% } - -%% 玩家帮派信息列表 -do_handle_request("guild_info_list", KvList, Socket) -> - GuildId = http_util:get_param("guild_id", KvList), - GuildName = http_util:get_param("guild_name", KvList), -%% call_to_server(lib_mail, broadcast_sys_msg, [GuildId, GuildName]), - ?INFO_MSG("type:~p content:~ts ~n", [GuildId, GuildName]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 刷新在线玩家信息 -do_handle_request("freshen_online_user", KvList, Socket) -> -%% cast_to_server(lib_mail, broadcast_sys_msg, []), - ?INFO_MSG("freshen_online_user ~p ~n", []), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 玩家道具查询接口 -do_handle_request("user_props_list", KvList, Socket) -> - UserId = http_util:get_param("user_id", KvList), - UserName = http_util:get_param("user_name", KvList), - Account = http_util:get_param("account", KvList), -%% call_to_server(lib_mail, broadcast_sys_msg, [UserId, UserName, Account]), - ?INFO_MSG("UserId:~p UserName:~ts Account:~ts ~n", [UserId, UserName, Account]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 玩家坐骑查询接口 -do_handle_request("user_horse_list", KvList, Socket) -> - UserId = http_util:get_param("user_id", KvList), - UserName = http_util:get_param("user_name", KvList), - Account = http_util:get_param("account", KvList), -%% call_to_server(lib_mail, broadcast_sys_msg, [UserId, UserName, Account]), - ?INFO_MSG("UserId:~p UserName:~ts Account:~ts ~n", [UserId, UserName, Account]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 玩家宠物查询接口 -do_handle_request("user_pet_list", KvList, Socket) -> - UserId = http_util:get_param("user_id", KvList), - UserName = http_util:get_param("user_name", KvList), - Account = http_util:get_param("account", KvList), -%% call_to_server(lib_mail, broadcast_sys_msg, [UserId, UserName, Account]), - ?INFO_MSG("UserId:~p UserName:~ts Account:~ts ~n", [UserId, UserName, Account]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 玩家技能查询接口 -do_handle_request("user_skill_list", KvList, Socket) -> - UserId = http_util:get_param("user_id", KvList), - UserName = http_util:get_param("user_name", KvList), - Account = http_util:get_param("account", KvList), -%% call_to_server(lib_mail, broadcast_sys_msg, [UserId, UserName, Account]), - ?INFO_MSG("UserId:~p UserName:~ts Account:~ts ~n", [UserId, UserName, Account]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - - -do_handle_request("broad", KvList, Socket) -> - AnnId = http_util:get_param("annid", KvList), - cast_to_server(mod_misc, load_sys_announce, [AnnId, annid]), -%% lib_chat:broadcast_sys_msg("test"), - ?INFO_MSG("type:~p content ~n", [AnnId]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -%% 充值 -do_handle_request("charge", KvList, Socket) -> - AccountId = list_to_integer(http_util:get_param("account_id", KvList)), - OrderId = list_to_integer(http_util:get_param("order_id", KvList)), - cast_to_server(lib_admin, handle_charge, [AccountId, OrderId]), - ?INFO_MSG("Account:~p OrderId:~p ~n", [AccountId, OrderId]), - gen_tcp:send(Socket, ?SUCCESS_CODE); - -do_handle_request(Other, Kvlist, Socket) -> - ?INFO_MSG("admin unknown cmd ~p, ~p", [Other, Kvlist]), - gen_tcp:send(Socket, ?PARAM_ERROR_CODE). - -%% ===================针对玩家的各类操作===================================== -cast_to_server(Module, Method, Args) -> - GameSvrNode = config:get_server_node(local_gateway), - rpc:cast(GameSvrNode, Module, Method, Args). - -call_to_server(Module, Method, Args) -> - GameSvrNode = config:get_server_node(local_gateway), - rpc:call(GameSvrNode, Module, Method, Args). - -%% 安全退出当前游戏服务器(在游戏服务器节点执行) -safe_quit() -> - timer:sleep(10 * 1000), - mod_guild:safe_quit(), - main:server_stop(), - ok. - -stop_server_node([NodeName]) -> - rpc:cast(NodeName, main, server_stop, []). - - -stop_local_gateway_node([NodeName]) -> - rpc:cast(NodeName, main, local_gateway_stop, []). - -stop_game_node([NodeName]) -> - rpc:cast(NodeName, main, gateway_stop, []). - -%% 清数据接口,非请勿用,出问题了别找我 -clear_data() -> - AllTables = db_esql:get_all("show tables"), - Fun = fun(Item) -> - [TName | _] = Item, - TableName = util:bitstring_to_term(TName), - ListTableName = atom_to_list(TableName), - case lists:sublist(ListTableName, 1, 5) =:= "temp_" orelse - lists:sublist(ListTableName, 1, 7) =:= "config_" of - true -> - skip; - false -> - TruncatSql = lists:concat(["truncate table ", TableName]), - db_esql:execute_sql(TruncatSql), - io:format("==truncated table:~p~n", [TableName]) - end - end, - lists:foreach(Fun, AllTables), - timer:sleep(1000), - erlang:halt(). - -%% Sql = lists:concat(["show tables"]), -%% case db_esql:get_row(Sql) of -%% {db_error, _} -> -%% error; -%% [_, A|_]-> -%% CreateTableList = re:split(A,"[\n]",[{return, binary}]), -%% search_auto_increment(CreateTableList) -%% end. diff --git a/src/comMisc/prof.erl b/src/comMisc/prof.erl deleted file mode 100644 index 60475eb..0000000 --- a/src/comMisc/prof.erl +++ /dev/null @@ -1,25 +0,0 @@ -%%%--------------------------------------------- -%%% @Module : prof -%%% @Author : csj -%%% @Created : 2010.10.05 -%%% @Description: 性能测试工具 -%%%--------------------------------------------- --module(prof). --compile(export_all). - -%%性能测试 -%%Fun:函数 -%%Loop:执行次数 -run(Fun, Loop) -> - statistics(wall_clock), - for(1, Loop, Fun), - {_, T1} = statistics(wall_clock), - io:format("~p loops, using time: ~pms~n", [Loop, T1]), - ok. - -for(Max, Max, Fun) -> - Fun(); -for(I, Max, Fun) -> - Fun(), for(I + 1, Max, Fun). - - diff --git a/src/comMisc/tool.erl b/src/comMisc/tool.erl deleted file mode 100644 index 65e1ae4..0000000 --- a/src/comMisc/tool.erl +++ /dev/null @@ -1,651 +0,0 @@ --module(tool). - --compile(export_all). - - - --define(IOFILE(Str, Args), (fun() -> - Command = io_lib:format(Str, Args), - file:write_file("../logs/data/proto_data.log", Command, [append]) - end)()). -%%导出协议统计结果 -stat_proto_data() -> - List = ets:tab2list(proto_stat), - NewList = lists:map(fun({Cmd, ProtoNum}) -> - {ProtoNum, Cmd} - end, List), - lists:foreach(fun({ProtoNum, Cmd}) -> - ?IOFILE("协议->~p使用次数为->~p ~n", [Cmd, ProtoNum]) - end - , lists:sort(NewList)). -%%打印函数调用测试结果 -trace_profile_result() -> - eprof:stop_profiling(), - eprof:analyze(total). - - -%% 分割列表的函数 -split(N, SrcList) -> - case length(SrcList) > N of - true -> - lists:split(N, SrcList); - false -> - {SrcList, []} - end. - - -%% @doc get IP address string from Socket -ip(Socket) -> - {ok, {IP, _Port}} = inet:peername(Socket), - {Ip0, Ip1, Ip2, Ip3} = IP, - list_to_binary(integer_to_list(Ip0) ++ "." ++ integer_to_list(Ip1) ++ "." ++ integer_to_list(Ip2) ++ "." ++ integer_to_list(Ip3)). - - -%% @doc quick sort -sort([]) -> - []; -sort([H | T]) -> - sort([X || X <- T, X < H]) ++ [H] ++ sort([X || X <- T, X >= H]). - -%% for -for(Max, Max, F) -> [F(Max)]; -for(I, Max, F) -> [F(I) | for(I + 1, Max, F)]. - -%%--------------------------------------------------- -%%给列表中元素加下标 by chenzm -%%@spec for(n,m,fun()) -> [] -%%--------------------------------------------------- -add_index([]) -> - []; -add_index(List) -> - for(1, length(List), fun(I) -> - Elem = lists:nth(I, List), - if - is_tuple(Elem) -> - list_to_tuple([I] ++ tuple_to_list(Elem)); - true -> - {I, Elem} - end - end). -add_index_to_record(List) -> - case List of - [] -> - []; - _ -> - for(1, length(List), fun(I) -> - Elem = lists:nth(I, List), - {I, Elem} - end) - end. - - -%% @doc convert float to string, f2s(1.5678) -> 1.57 -f2s(N) when is_integer(N) -> - integer_to_list(N) ++ ".00"; -f2s(F) when is_float(F) -> - [A] = io_lib:format("~.2f", [F]), - A. - - -%% @doc convert other type to atom -to_atom(Msg) when is_atom(Msg) -> - Msg; -to_atom(Msg) when is_binary(Msg) -> - tool:list_to_atom2(binary_to_list(Msg)); -to_atom(Msg) when is_list(Msg) -> - tool:list_to_atom2(Msg); -to_atom(_) -> - throw(other_value). %%list_to_atom(""). - -%% @doc convert other type to list -to_list(Msg) when is_list(Msg) -> - Msg; -to_list(Msg) when is_atom(Msg) -> - atom_to_list(Msg); -to_list(Msg) when is_binary(Msg) -> - binary_to_list(Msg); -to_list(Msg) when is_integer(Msg) -> - integer_to_list(Msg); -to_list(Msg) when is_float(Msg) -> - f2s(Msg); -to_list(_) -> - throw(other_value). - -%% @doc convert other type to binary -to_binary(Msg) when is_binary(Msg) -> - Msg; -to_binary(Msg) when is_atom(Msg) -> - list_to_binary(atom_to_list(Msg)); -%%atom_to_binary(Msg, utf8); -to_binary(Msg) when is_list(Msg) -> - list_to_binary(Msg); -to_binary(Msg) when is_integer(Msg) -> - list_to_binary(integer_to_list(Msg)); -to_binary(Msg) when is_float(Msg) -> - list_to_binary(f2s(Msg)); -to_binary(_Msg) -> - throw(other_value). - -%% @doc convert other type to float -to_float(Msg) -> - Msg2 = to_list(Msg), - list_to_float(Msg2). - -%% @doc convert other type to integer -%% -spec to_integer(Msg :: any()) -> integer(). %%liujing 2012-8-9 cancel -to_integer(Msg) when is_integer(Msg) -> - Msg; -to_integer(Msg) when is_binary(Msg) -> - Msg2 = binary_to_list(Msg), - list_to_integer(Msg2); -to_integer(Msg) when is_list(Msg) -> - list_to_integer(Msg); -to_integer(Msg) when is_float(Msg) -> - round(Msg); -to_integer(_Msg) -> - throw(other_value). - -to_bool(D) when is_integer(D) -> - D =/= 0; -to_bool(D) when is_list(D) -> - length(D) =/= 0; -to_bool(D) when is_binary(D) -> - to_bool(binary_to_list(D)); -to_bool(D) when is_boolean(D) -> - D; -to_bool(_D) -> - throw(other_value). - -%% @doc convert other type to tuple -to_tuple(T) when is_tuple(T) -> T; -to_tuple(T) -> {T}. - -%% @doc get data type {0=integer,1=list,2=atom,3=binary} -get_type(DataValue, DataType) -> - case DataType of - 0 -> - DataValue2 = binary_to_list(DataValue), - list_to_integer(DataValue2); - 1 -> - binary_to_list(DataValue); - 2 -> - DataValue2 = binary_to_list(DataValue), - list_to_atom(DataValue2); - 3 -> - DataValue - end. - -%% @spec is_string(List)-> yes|no|unicode -is_string([]) -> yes; -is_string(List) -> is_string(List, non_unicode). - -is_string([C | Rest], non_unicode) when C >= 0, C =< 255 -> is_string(Rest, non_unicode); -is_string([C | Rest], _) when C =< 65000 -> is_string(Rest, unicode); -is_string([], non_unicode) -> yes; -is_string([], unicode) -> unicode; -is_string(_, _) -> no. - - -%% @doc get random list -list_random(List) -> - case List of - [] -> - {}; - _ -> - RS = lists:nth(random:uniform(length(List)), List), - ListTail = lists:delete(RS, List), - {RS, ListTail} - end. - -%% @doc get a random integer between Min and Max -random(Min, Max) -> - Min2 = Min - 1, - random:uniform(Max - Min2) + Min2. - -%% @doc 掷骰子 -random_dice(Face, Times) -> - if - Times == 1 -> - random(1, Face); - true -> - lists:sum(for(1, Times, fun(_) -> random(1, Face) end)) - end. - -%% @doc 机率 -odds(Numerator, Denominator) -> - Odds = random:uniform(Denominator), - if - Odds =< Numerator -> - true; - true -> - false - end. - -odds_list(List) -> - Sum = odds_list_sum(List), - odds_list(List, Sum). -odds_list([{Id, Odds} | List], Sum) -> - case odds(Odds, Sum) of - true -> - Id; - false -> - odds_list(List, Sum - Odds) - end. -odds_list_sum(List) -> - {_List1, List2} = lists:unzip(List), - lists:sum(List2). - - -%% @doc 取整 大于X的最小整数 -ceil(X) -> - T = trunc(X), - if - X - T == 0 -> - T; - true -> - if - X > 0 -> - T + 1; - true -> - T - end - end. - - -%% @doc 取整 小于X的最大整数 -floor(X) -> - T = trunc(X), - if - X - T == 0 -> - T; - true -> - if - X > 0 -> - T; - true -> - T - 1 - end - end. -%% 4舍5入 -%% round(X) - -%% subatom -subatom(Atom, Len) -> - list_to_atom(lists:sublist(atom_to_list(Atom), Len)). - -%% @doc 暂停多少毫秒 -sleep(Msec) -> - receive - after Msec -> - true - end. - -md5(S) -> - Md5_bin = erlang:md5(S), - Md5_list = binary_to_list(Md5_bin), - lists:flatten(list_to_hex(Md5_list)). - -list_to_hex(L) -> - lists:map(fun(X) -> int_to_hex(X) end, L). - -int_to_hex(N) when N < 256 -> - [hex(N div 16), hex(N rem 16)]. -hex(N) when N < 10 -> - $0 + N; -hex(N) when N >= 10, N < 16 -> - $a + (N - 10). - -list_to_atom2(List) when is_list(List) -> - case catch (list_to_existing_atom(List)) of - {'EXIT', _} -> erlang:list_to_atom(List); - Atom when is_atom(Atom) -> Atom - end. - -combine_lists(L1, L2) -> - Rtn = - lists:foldl( - fun(T, Acc) -> - case lists:member(T, Acc) of - true -> - Acc; - false -> - [T | Acc] - end - end, lists:reverse(L1), L2), - lists:reverse(Rtn). - - -get_process_info_and_zero_value(InfoName) -> - PList = erlang:processes(), - ZList = lists:filter( - fun(T) -> - case erlang:process_info(T, InfoName) of - {InfoName, 0} -> false; - _ -> true - end - end, PList), - ZZList = lists:map( - fun(T) -> {T, erlang:process_info(T, InfoName), erlang:process_info(T, registered_name)} - end, ZList), - [length(PList), InfoName, length(ZZList), ZZList]. - -get_process_info_and_large_than_value(InfoName, Value) -> - PList = erlang:processes(), - ZList = lists:filter( - fun(T) -> - case erlang:process_info(T, InfoName) of - {InfoName, VV} -> - if VV > Value -> true; - true -> false - end; - _ -> true - end - end, PList), - ZZList = lists:map( - fun(T) -> {T, erlang:process_info(T, InfoName), erlang:process_info(T, registered_name)} - end, ZList), - [length(PList), InfoName, Value, length(ZZList), ZZList]. - -get_msg_queue() -> - io:fwrite("process count:~p~n~p value is not 0 count:~p~nLists:~p~n", - get_process_info_and_zero_value(message_queue_len)). - -get_memory() -> - io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", - get_process_info_and_large_than_value(memory, 1048576)). - -get_memory(Value) -> - io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", - get_process_info_and_large_than_value(memory, Value)). - -get_heap() -> - io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", - get_process_info_and_large_than_value(heap_size, 1048576)). - -get_heap(Value) -> - io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", - get_process_info_and_large_than_value(heap_size, Value)). - -get_processes() -> - io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", - get_process_info_and_large_than_value(memory, 0)). - - -list_to_term(String) -> - {ok, T, _} = erl_scan:string(String ++ "."), - case erl_parse:parse_term(T) of - {ok, Term} -> - Term; - {error, Error} -> - Error - end. - - -substr_utf8(Utf8EncodedString, Length) -> - substr_utf8(Utf8EncodedString, 1, Length). -substr_utf8(Utf8EncodedString, Start, Length) -> - ByteLength = 2 * Length, - Ucs = xmerl_ucs:from_utf8(Utf8EncodedString), - Utf16Bytes = xmerl_ucs:to_utf16be(Ucs), - SubStringUtf16 = lists:sublist(Utf16Bytes, Start, ByteLength), - Ucs1 = xmerl_ucs:from_utf16be(SubStringUtf16), - xmerl_ucs:to_utf8(Ucs1). - -ip_str(IP) -> - case IP of - {A, B, C, D} -> - lists:concat([A, ".", B, ".", C, ".", D]); - {A, B, C, D, E, F, G, H} -> - lists:concat([A, ":", B, ":", C, ":", D, ":", E, ":", F, ":", G, ":", H]); - Str when is_list(Str) -> - Str; - _ -> - [] - end. - -%%对正负进行调整:负数变为0,正数保持不变 -int_format(Num) -> - if Num >= 0 -> - Num; - true -> - 0 - end. - -%%去掉字符串空格 -remove_string_black(L) -> - F = fun(S) -> - if S == 32 -> []; - true -> S - end - end, - Result = [F(lists:nth(I, L)) || I <- lists:seq(1, length(L))], - lists:filter(fun(T) -> T =/= [] end, Result). - - -%%获取协议操作的时间戳,true->允许;false -> 直接丢弃该条数据 -%%spec is_operate_ok/1 param: Type -> 添加的协议类型(atom); return: true->允许;false -> 直接丢弃该条数据 -is_operate_ok(Type, TimeStamp) -> - NowTime = util:longunixtime(), - case get(Type) of - undefined -> - put(Type, NowTime), - true; - Value -> - case (NowTime - Value) >= TimeStamp of - true -> - put(Type, NowTime), - true; - false -> - false - end - end. - -%%打包字符串数据 -pack_string(Str) -> - StrBin = tool:to_binary(Str), - Len = byte_size(StrBin), - {Len, StrBin}. - -%%对[{GetName, Rate},..]结构类型的单项随机获取的通用处理,空列表返回undefined -get_rand_single(RateList) -> - Fun = fun({_Tmp, R}, RNum) -> - RNum + R - end, - AllR = lists:foldl(Fun, 0, RateList), - GetRNum = util:rand(1, AllR), - Fun1 = fun({Atom, Rat}, [BGet, Ra, FirstNum, GetAtom1]) -> - EndNum = FirstNum + Rat, - if BGet =:= 0 andalso Ra =< EndNum -> - [1, Ra, EndNum, Atom]; - true -> - [BGet, Ra, EndNum, GetAtom1] - end - end, - [_NewBGet, _NewRa, _FirstNum, GetAtom] = lists:foldl(Fun1, [0, GetRNum, 0, undefined], RateList), - GetAtom. - -%%对[{GetName, Rate, MinNum, MaxNum},..]结构类型的单项随机获取的通用处理,空列表返回undefined -get_rand_single2(RateList) -> - Fun = fun({_Tmp, R, _Mn, _Mx}, RNum) -> - RNum + R - end, - AllR = lists:foldl(Fun, 0, RateList), - GetRNum = util:rand(1, AllR), - Fun1 = fun({Atom, Rat, MinNum, MaxNum}, [BGet, Ra, FirstNum, GetAtom1]) -> - EndNum = FirstNum + Rat, - if BGet =:= 0 andalso Ra =< EndNum -> - [1, Ra, EndNum, {Atom, MinNum, MaxNum}]; - true -> - [BGet, Ra, EndNum, GetAtom1] - end - end, - [_NewBGet, _NewRa, _FirstNum, GetAtom] = lists:foldl(Fun1, [0, GetRNum, 0, undefined], RateList), - GetAtom. - - -%%对单个玩家数据回档的操作函数======2012-9-17 from liujing====== - -%%获取需要处理的表名(返回字符串结构的表名) -get_handle_table_name() -> - TableList = lib_player_rw:get_all_tables(), - F = fun(TableName, GetList) -> - TableName1 = util:term_to_string(TableName), - case TableName1 =/= "cards" andalso TableName1 =/= "sys_acm" andalso string:str(TableName1, "admin") =/= 1 - andalso TableName1 =/= "auto_ids" andalso TableName1 =/= "shop" andalso string:str(TableName1, "base") =/= 1 - andalso TableName1 =/= "slaves" andalso TableName1 =/= "battle_cache_data" andalso string:str(TableName1, "arena") =/= 1 - andalso string:str(TableName1, "log_") =/= 1 andalso string:str(TableName1, "th") =/= 1 - andalso TableName1 =/= "rela" of - false -> GetList; - true -> - GetList ++ [util:string_to_term(tool:to_list(TableName1))] - end - end, - lists:foldl(F, [], TableList). - -ini_faraway_mongo_db(PoolId, Num) -> - Host = - case Num of - 1 -> - "113.105.250.125"; - 2 -> - "113.105.251.123"; - 4 -> - "183.61.130.69"; - _ -> - %%连接内部192.168.51.174服务器 - "192.168.51.174" - end, -%% Host = io:get_line("remote database ip:") , - Port = 27017, - case Num of - 0 -> - DB = "csj_dev_S1"; - _ -> - DB = lists:concat(["csj_dev_S", Num]) - end, - io:format("====dest db:~p~n", [[Host, DB]]), - - EmongoSize = 1, - emongo_sup:start_link(), - emongo_app:initialize_pools([PoolId, Host, Port, DB, EmongoSize]). - -ini_local_mongo_db(PoolId, Num) -> - Host = "192.168.51.174", -%% Host = io:get_line("sorce database ip:") , - Port = 27017, - case Num of - 0 -> - DB = "csj_dev_src_S1"; - _ -> - DB = lists:concat(["csj_dev_src_S", Num]) - end, - io:format("====src db:~p~n", [DB]), - EmongoSize = 1, - emongo_sup:start_link(), - emongo_app:initialize_pools([PoolId, Host, Port, DB, EmongoSize]). - -get_mongo_to_mysql(UidList, ServerNum) -> -%% CONFIG_FILE = "../config/gateway.config", - FarPoolId = lists:concat(["master_mongo_tmp", ServerNum]), - LocalPoolId = "master_mongo_l", - TableList = get_handle_table_name(), - ini_faraway_mongo_db(FarPoolId, ServerNum), - ini_local_mongo_db(LocalPoolId, ServerNum), - Fun1 = fun(TableName, GetUid) -> - case TableName of - player -> - io:format("========_1_~n"), - [WhereOpertion, FieldOpertion] = db_mongoutil:make_select_opertion(db_mongo:transfer_fields(TableName, "*"), [{id, GetUid}], [], []), - L = emongo:find_all(LocalPoolId, tool:to_list(TableName), WhereOpertion, FieldOpertion), - io:format("========_1_~p~n", [L]), - RList = db_mongo:handle_all_result(TableName, db_mongo:transfer_fields(TableName, "*"), L), - [DelOpertion] = db_mongoutil:make_delete_opertion([{id, GetUid}]), - emongo:delete(FarPoolId, tool:to_list(TableName), DelOpertion), - case RList of - [] -> - GetUid; - _ -> - FieldList = db_mongo:get_all_fields(TableName), - Fun2 = fun(RL) -> - FullKeyValuelist = db_mongo:fullKeyValue(TableName, lists:zip(FieldList, RL)), - FullKeyValuelist1 = checkF(FullKeyValuelist), - Opertion = db_mongoutil:make_insert_opertion(FullKeyValuelist1), - emongo:insert(FarPoolId, tool:to_list(TableName), Opertion) - end, - lists:foreach(Fun2, RList), - GetUid - end; - _ -> - io:format("========_3_[~p]~n", [TableName]), - FieldList = db_mongo:get_all_fields(TableName), - case FieldList of - undefined -> - GetUid; - [] -> - GetUid; - _ -> - [WhereOpertion, FieldOpertion] = db_mongoutil:make_select_opertion(db_mongo:transfer_fields(TableName, "*"), [{uid, GetUid}], [], []), - L = emongo:find_all(LocalPoolId, tool:to_list(TableName), WhereOpertion, FieldOpertion), - - RList = db_mongo:handle_all_result(TableName, db_mongo:transfer_fields(TableName, "*"), L), - [DelOpertion] = db_mongoutil:make_delete_opertion([{uid, GetUid}]), - emongo:delete(FarPoolId, tool:to_list(TableName), DelOpertion), - case RList of - [] -> - GetUid; - _ -> - Fun2 = fun(RL) -> - FullKeyValuelist = db_mongo:fullKeyValue(TableName, lists:zip(FieldList, RL)), - FullKeyValuelist1 = checkF(FullKeyValuelist), - Opertion = db_mongoutil:make_insert_opertion(FullKeyValuelist1), - emongo:insert(FarPoolId, tool:to_list(TableName), Opertion) - end, - lists:foreach(Fun2, RList), - GetUid - end - end - end - end, - Fun = fun(Uid) -> - lists:foldl(Fun1, Uid, TableList) - end, - lists:foreach(Fun, UidList). - -checkF(KeyVList) -> - Fun = fun({Key, Val}) -> - case Val of - [] -> - {Key, <<"[]">>}; - undefined -> - {Key, <<"[]">>}; - _ -> - {Key, Val} - end - end, - - lists:map(Fun, KeyVList). - -%%打印结构体,哥只能做到这样的 -%%dynamic_compile死活编译不过 -recinfo(FieldList, Rec) -> - RecordName = lists:nth(1, tuple_to_list(Rec)), - ValueList = lists:nthtail(1, tuple_to_list(Rec)), - Length = min(length(FieldList), length(ValueList)), - OutStr = "#" ++ tool:to_list(RecordName) ++ "{\r\n", - OutStr1 = lists:foldl(fun(Idx, Str) -> - Str ++ io_lib:format(" ~p = ~p,~n", [lists:nth(Idx, FieldList), lists:nth(Idx, ValueList)]) - end, OutStr, lists:seq(1, Length - 1)), - OutStr1 ++ io_lib:format(" ~p = ~p}~n", [lists:nth(Length, FieldList), lists:nth(Length, ValueList)]). - -gcd(A, 0) -> - A; -gcd(A, B) when A >= B -> - gcd(A rem B, B); -gcd(A, B) -> - gcd(B, A). -%%求最小公约数 -hcd([H | T]) -> - gcd(H, hcd(T)); -hcd([]) -> - 0. - diff --git a/src/comMisc/utMisc.erl b/src/comMisc/utMisc.erl index c36f32c..e8b56ac 100644 --- a/src/comMisc/utMisc.erl +++ b/src/comMisc/utMisc.erl @@ -70,13 +70,7 @@ compile_base_data(Table, ModName, IDPoses) -> end, ok. -%% 得到CPU核数 -coreCnt() -> - erlang:system_info(schedulers). -%% 获取当前进程运行的核id -coreIndex() -> - erlang:system_info(scheduler_id). diff --git a/src/comMisc/misc1.erl b/src/comMisc/utPid.erl similarity index 79% rename from src/comMisc/misc1.erl rename to src/comMisc/utPid.erl index 8434301..1cf947a 100644 --- a/src/comMisc/misc1.erl +++ b/src/comMisc/utPid.erl @@ -1,9 +1,17 @@ --module(misc1). - +-module(utPid). %% -%% API Functions +%% Exported Functions %% -%% get the pid of a registered name +-export([ + whereis_name/1, + register/3, + unregister/2, + is_process_alive/1 + +]). + + +%% @doc 寻找PID whereis_name({local, Atom}) -> erlang:whereis(Atom); @@ -14,33 +22,27 @@ register(local, Name, Pid) -> erlang:register(Name, Pid); register(global, Name, Pid) -> -%% case global:whereis_name(Name) of -%% Pid0 when is_pid(Pid0) -> -%% exit(Pid0,normal); -%% undefined -> -%% global:re_register_name(Name, Pid) -%% end. - global:re_register_name(Name, Pid); - -register(unique, Name, Pid) -> - global:register_name(Name, Pid). - -unregister({local, Atom}) -> - erlang:unregister(Atom); + global:re_register_name(Name, Pid). -unregister({global, Atom}) -> - global:unregister(Atom). +unregister(local, Name) -> + erlang:unregister(Name); +unregister(global, Name) -> + global:unregister_name(Name). is_process_alive(Pid) -> try - if is_pid(Pid) -> - %%现在都是单节点,无需访问节点来判断 -%% case rpc:call(node(Pid), erlang, is_process_alive, [Pid]) of -%% {badrpc, _Reason} -> false; -%% Res -> Res -%% end; - erlang:is_process_alive(Pid); - true -> false + case Pid of + _ when is_pid(Pid) -> + Node = node(), + Result = case node(Pid) of + Node -> erlang:is_process_alive(Pid); + Node1 -> rpc:call(Node1, erlang, is_process_alive, [Pid]) + end, + case Result of + {badrpc, _Reason} -> false; + Res -> Res + end; + _ -> false end catch _:_ -> false @@ -340,80 +342,4 @@ get_process_data({registered_name, Pid}) -> _ -> "" catch _:_ -> "" - end. -%% -------------------------------------------------------------------- -%% Func: get_online_role_count/1 -%% Purpose: get online role count -%% Returns: {0,0} or {SpecsCount,ActiveCount} -%% -------------------------------------------------------------------- -%% get_online_role_count(AccountList) -> -%% case AccountList of -%% AccAtom when is_atom(AccAtom) -> -%% get_online_role_count([AccAtom], 0, 0); -%% AccList when is_list(AccList) -> -%% get_online_role_count(AccList, 0, 0) -%% end. -%% -%% get_online_role_count([], Count, ActiveCount) ->{Count,ActiveCount}; -%% get_online_role_count(Ports, Count, ActiveCount) -> -%% [AccountSupName|T] = Ports, -%% {SNum,ANum} = get_online_role_count_item(AccountSupName), -%% get_online_role_count(T, Count + SNum, ActiveCount + ANum). -%% -%% get_online_role_count_item(SupName) -> -%% try supervisor:count_children(SupName) of -%% [] -> {0,0}; -%% SupList when erlang:is_list(SupList) -> -%% %% io:format("SupList ~p ~n", [SupList]), -%% SCount = -%% case proplists:lookup(specs, SupList) of -%% {specs, SNum} -> SNum; -%% _ -> 0 -%% end, -%% ACount = -%% case proplists:lookup(active, SupList) of -%% {active, ANum} -> ANum; -%% _ -> 0 -%% end, -%% {SCount,ACount}; -%% _ -> {0,0} -%% catch -%% _:_ -> {0,0} -%% end. - -%% -------------------------------------------------------------------- -%% Func: replace_all/4 -%% Purpose: Subject,RE,Replacement,Options -%% Returns: List -%% -------------------------------------------------------------------- -replace_all(Subject, RE, Replacement, Options) -> - ReSubject = re:replace(Subject, RE, Replacement, Options), - case ReSubject =:= Subject of - false -> - replace_all(ReSubject, RE, Replacement, Options); - _ -> - ReSubject - end. - -pg2_get_members(Pg2_name) -> - L = case pg2:get_members(Pg2_name) of - {error, _} -> - timer:sleep(100), - pg2:get_members(Pg2_name); - Other when is_list(Other) -> - Other - end, - if not is_list(L) -> []; - true -> lists:usort(L) - end. - -get_http_content(Url) -> - case httpc:request(Url) of - {ok, {_Status, _Headers, Raw}} -> - Raw; - {error, _Reason} -> - "" - end. - - - + end. \ No newline at end of file diff --git a/src/profTrace/utProf.erl b/src/profTrace/utProf.erl new file mode 100644 index 0000000..96eb9e1 --- /dev/null +++ b/src/profTrace/utProf.erl @@ -0,0 +1,45 @@ +-module(utProf). + + +%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(). + +% 对整个节点内所有进程执行eprof, eprof 对线上业务有一定影响,慎用! +% 建议TimeoutSec<10s,且进程数< 1000,否则可能导致节点crash +% 结果: +% 输出每个方法实际执行时间(不会累计方法内其他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(). + +% @doc 对MFA 执行分析,会严重减缓运行,建议只对小量业务执行 +% 结果: +% fprof 结果比较详细,能够输出热点调用路径 +fprof(M, F, A) -> + fprof:start(), + fprof:apply(M, F, A), + fprof:profile(), + fprof:analyse([{dest, "fprof.analysis"}, {sort, own}]), + fprof:stop(). diff --git a/src/srvNodeMgr/utVMInfo.erl b/src/srvNodeMgr/utVMInfo.erl index 4005279..59014d4 100644 --- a/src/srvNodeMgr/utVMInfo.erl +++ b/src/srvNodeMgr/utVMInfo.erl @@ -221,9 +221,314 @@ show1(N) -> [io:format("~p : per_memory=~p process_num=~p ~n", [Name, (M div Num), Num]) || {Name, M, Num} <- Infos4], ok. +%% 得到CPU核数 +coreCnt() -> + erlang:system_info(schedulers). -%% ==================================================================== -%% Internal functions -%% ==================================================================== +%% 获取当前进程运行的核id +coreIndex() -> + erlang:system_info(scheduler_id). + + +%% @doc 节点所有进程信息 +process_infos() -> + filelib:ensure_dir("./logs/"), + File = "./logs/processes_infos.log", + {ok, Fd} = file:open(File, [write, raw, binary, append]), + Fun = fun(Pi) -> + Info = io_lib:format("=>~p \n\n", [Pi]), + case filelib:is_file(File) of + true -> file:write(Fd, Info); + false -> + file:close(Fd), + {ok, NewFd} = file:open(File, [write, raw, binary, append]), + file:write(NewFd, Info) + end, + timer:sleep(20) + end, + [Fun(erlang:process_info(P)) || P <- erlang:processes()]. + +rfc1123_local_date() -> + rfc1123_local_date(os:timestamp()). +rfc1123_local_date({A, B, C}) -> + rfc1123_local_date(calendar:now_to_local_time({A, B, C})); +rfc1123_local_date({{YYYY, MM, DD}, {Hour, Min, Sec}}) -> + DayNumber = calendar:day_of_the_week({YYYY, MM, DD}), + lists:flatten( + io_lib:format("~s, ~2.2.0w ~3.s ~4.4.0w ~2.2.0w:~2.2.0w:~2.2.0w GMT", + [httpd_util:day(DayNumber), DD, httpd_util:month(MM), YYYY, Hour, Min, Sec])); +rfc1123_local_date(Epoch) when erlang:is_integer(Epoch) -> + rfc1123_local_date(calendar:gregorian_seconds_to_datetime(Epoch + 62167219200)). + +%% @doc erlang_dump +crash_dump() -> + Date = erlang:list_to_binary(rfc1123_local_date()), + Header = binary:list_to_bin([<<"=erl_crash_dump:0.2\n">>, Date, <<"\nSystem version: ">>]), + Ets = ets_info(), + Report = binary:list_to_bin([Header, erlang:list_to_binary(erlang:system_info(system_version)), + erlang:system_info(info), erlang:system_info(procs), Ets, erlang:system_info(dist), + <<"=loaded_modules\n">>, binary:replace(erlang:system_info(loaded), + <<"\n">>, <<"\n=mod:">>, [global])]), + file:write_file("erl_crash.dump", Report). + +ets_info() -> + binary:list_to_bin([ets_table_info(T) || T <- ets:all()]). + +ets_table_info(Table) -> + Info = ets:info(Table), + Owner = erlang:list_to_binary(erlang:pid_to_list(proplists:get_value(owner, Info))), + TableN = erlang:list_to_binary(erlang:atom_to_list(proplists:get_value(name, Info))), + Name = erlang:list_to_binary(erlang:atom_to_list(proplists:get_value(name, Info))), + Objects = erlang:list_to_binary(erlang:integer_to_list(proplists:get_value(size, Info))), + binary:list_to_bin([<<"=ets:">>, Owner, <<"\nTable: ">>, TableN, <<"\nName: ">>, Name, + <<"\nObjects: ">>, Objects, <<"\n">>]). + +% 统计下1s内调度进程数量(含义:第一个数字执行进程数量,第二个数字迁移进程数量) +scheduler_stat() -> + scheduler_stat(1000). + +scheduler_stat(RunMs) -> + erlang:system_flag(scheduling_statistics, enable), + Ts0 = erlang:system_info(total_scheduling_statistics), + timer:sleep(RunMs), + Ts1 = erlang:system_info(total_scheduling_statistics), + erlang:system_flag(scheduling_statistics, disable), + lists:map(fun({{Key, In0, Out0}, {Key, In1, Out1}}) -> + {Key, In1 - In0, Out1 - Out0} end, lists:zip(Ts0, Ts1)). + +% 统计下1s每个调度器CPU的实际利用率(因为有spin wait、调度工作, 可能usage 比top显示低很多) +scheduler_usage() -> + scheduler_usage(1000). + +scheduler_usage(RunMs) -> + erlang:system_flag(scheduler_wall_time, true), + Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), + timer:sleep(RunMs), + Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), + erlang:system_flag(scheduler_wall_time, false), + Cores = lists:map(fun({{I, A0, T0}, {I, A1, T1}}) -> + {I, (A1 - A0) / (T1 - T0)} end, lists:zip(Ts0, Ts1)), + {A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai, Ti}) -> + {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0, Ts1)), + Total = A / T, + io:format("~p~n", [[{total, Total} | Cores]]). + + +% @doc 对所有process做gc +gc_all() -> + [erlang:garbage_collect(Pid) || Pid <- processes()]. + +% @doc 进程CPU占用排名 +etop() -> + spawn(fun() -> etop:start([{output, text}, {interval, 10}, {lines, 20}, {sort, runtime}]) end). + +% @doc 进程Mem占用排名 +etop_mem() -> + spawn(fun() -> etop:start([{output, text}, {interval, 10}, {lines, 20}, {sort, memory}]) end). + +% @doc 停止etop +etop_stop() -> + etop:stop(). + +%% @doc 类似于jstack,发现大量进程挂起,进程数过高,运行慢,hang住等问题用到 +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))]). + + + + +%% 检查溢出的内存,强制gc, 并写入日志分析 +check_mem(MemLim) -> + lists:foreach( + fun(P) -> + case is_pid(P) andalso erlang:is_process_alive(P) of + true -> + {memory, Mem} = erlang:process_info(P, memory), + case Mem > MemLim of + true -> + erlang:garbage_collect(P); + false -> + [] + end; + false -> + [] + end + end, erlang:processes()). + +%% @spec top() -> ok +%% @doc 查看系统当前的综合信息 +top() -> + Release = erlang:system_info(otp_release), + SchedNum = erlang:system_info(schedulers), + ProcCount = erlang:system_info(process_count), + ProcLimit = erlang:system_info(process_limit), + ProcMemUsed = erlang:memory(processes_used), + EtsMemAlc = erlang:memory(ets), + MemTot = erlang:memory(total), + %PetNum = all_pets(), + io:format( + "++++++++++++++++++++++++++++++++++++++++++~n" + " Node: ~p~n" + " Erlang Ver: ~p~n" + " Free Threads: ~p~n" + " Process Used Memory: ~pMb~n" + " Ets Used Memory: ~pMb~n" + " Erlang VM Used Memory: ~pMb~n" + " Process Limit: ~p~n" + " Process Used: ~p~n" + "++++++++++++++++++++++++++++++++++++++++++~n" + , [node(), Release, SchedNum, ProcMemUsed / 1024 / 1024, EtsMemAlc / 1024 / 1024, MemTot / 1024 / 1024, ProcLimit, ProcCount]), + ok. + +%% @doc 运维要用 +top_back() -> + Release = erlang:system_info(otp_release), + SchedNum = erlang:system_info(schedulers), + ProcCount = erlang:system_info(process_count), + ProcLimit = erlang:system_info(process_limit), + ProcMemUsed = erlang:memory(processes_used), + EtsMemAlc = erlang:memory(ets), + MemTot = erlang:memory(total), + Str = io_lib:format( + " Erlang 版本: ~p~n" + " 可使用的调度线程: ~p~n" + " 所有进程使用的内存: ~pMb~n" + " 所有ets使用的内存: ~pMb~n" + " Erlang系统占用内存: ~pMb~n" + " 可创建进程数量上限: ~p~n" + " 当前进程数: ~p~n" + , [Release, SchedNum, ProcMemUsed / 1024 / 1024, EtsMemAlc / 1024 / 1024, MemTot / 1024 / 1024, ProcLimit, ProcCount]), + binary_to_list(list_to_binary(Str)). + +%% @spec ets_mem() -> term() +%% @doc 查看内存占用最多的30张ets表 +ets_mem() -> + L = ets:all(), + Mems = lists:map(fun(Tab) -> + Info = ets:info(Tab), + case lists:keyfind(memory, 1, Info) of + {memory, Mem} -> {Tab, Mem}; + _ -> {Tab, 0} + end + end, L), + L1 = lists:sublist(lists:reverse(lists:keysort(2, Mems)), 30), + io:format("~n--------------------------------------------------~n" + "~-30w ~w~n--------------------------------------------------~n" + , [table, used_memory]), + lists:foreach( + fun({Tab, 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 备份进程信息 +dump_process_info(Pid) -> + {{Year, Month, Day}, {Hour, Minutes, Second}} = util:local_time(), + {ok, FileHandle} = file:open(util:fbin("~s-~w-~w-~w-~w-~w-~w", [<<"../logs/pid_info.dump">>, Year, Month, Day, Hour, Minutes, Second]), write), + case erlang:process_info(Pid) of + Info when is_list(Info) -> + lists:foreach(fun({messages, Messages}) -> + case Messages =:= [] of + true -> + io:format(FileHandle, "~w~n", [{messages, Messages}]); + _ -> + io:format(FileHandle, "{messages,~n", []), + lists:foreach(fun(M) -> + io:format(FileHandle, " ~w~n", [M]) + end, Messages), + io:format(FileHandle, "}~n", []) + end; + ({dictionary, Dics}) -> + case Dics =:= [] of + true -> + io:format(FileHandle, "~w~n", [{dictionary, Dics}]); + _ -> + io:format(FileHandle, "{dictionary,~n", []), + lists:foreach(fun(M) -> + io:format(FileHandle, " ~w~n", [M]) + end, Dics), + io:format(FileHandle, "}~n", []) + end; + (E) -> + io:format(FileHandle, "~w~n", [E]) + end, Info); + _ -> + io:format("not find pid info") + end, + file:close(FileHandle). + +get_process_info_and_zero_value(InfoName) -> + PList = erlang:processes(), + ZList = lists:filter( + fun(T) -> + case erlang:process_info(T, InfoName) of + {InfoName, 0} -> false; + _ -> true + end + end, PList), + ZZList = lists:map( + fun(T) -> {T, erlang:process_info(T, InfoName), erlang:process_info(T, registered_name)} + end, ZList), + [length(PList), InfoName, length(ZZList), ZZList]. + +get_process_info_and_large_than_value(InfoName, Value) -> + PList = erlang:processes(), + ZList = lists:filter( + fun(T) -> + case erlang:process_info(T, InfoName) of + {InfoName, VV} -> + if VV > Value -> true; + true -> false + end; + _ -> true + end + end, PList), + ZZList = lists:map( + fun(T) -> {T, erlang:process_info(T, InfoName), erlang:process_info(T, registered_name)} + end, ZList), + [length(PList), InfoName, Value, length(ZZList), ZZList]. + +get_msg_queue() -> + io:fwrite("process count:~p~n~p value is not 0 count:~p~nLists:~p~n", + get_process_info_and_zero_value(message_queue_len)). + +get_memory() -> + io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", + get_process_info_and_large_than_value(memory, 1048576)). + +get_memory(Value) -> + io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", + get_process_info_and_large_than_value(memory, Value)). + +get_heap() -> + io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", + get_process_info_and_large_than_value(heap_size, 1048576)). + +get_heap(Value) -> + io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", + get_process_info_and_large_than_value(heap_size, Value)). + +get_processes() -> + io:fwrite("process count:~p~n~p value is large than ~p count:~p~nLists:~p~n", + get_process_info_and_large_than_value(memory, 0)).