From 35cf9d4b6a80d99f85e28323021bc696f5a29f12 Mon Sep 17 00:00:00 2001 From: huangdan Date: Sat, 30 May 2015 21:54:59 +0800 Subject: [PATCH 1/8] =?UTF-8?q?scheduler=5Fusage=E3=80=81memory=E3=80=81us?= =?UTF-8?q?ed=20allocated=20Erlang=20data?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/emqttd/src/emqttd_vm.erl | 278 +++++++++------------------------- 1 file changed, 70 insertions(+), 208 deletions(-) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index f4ce3cdd4..c083bfda2 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -26,88 +26,23 @@ %%%----------------------------------------------------------------------------- -module(emqttd_vm). +-define(UTIL_ALLOCATORS, [temp_alloc, + eheap_alloc, + binary_alloc, + ets_alloc, + driver_alloc, + sl_alloc, + ll_alloc, + fix_alloc, + std_alloc + ]). + + -author("Feng Lee "). --define(SYSTEM_INFO, [ - allocated_areas, - allocator, - alloc_util_allocators, - build_type, - check_io, - compat_rel, - creation, - debug_compiled, - dist, - dist_ctrl, - driver_version, - elib_malloc, - dist_buf_busy_limit, - %fullsweep_after, % included in garbage_collection - garbage_collection, - %global_heaps_size, % deprecated - heap_sizes, - heap_type, - info, - kernel_poll, - loaded, - logical_processors, - logical_processors_available, - logical_processors_online, - machine, - %min_heap_size, % included in garbage_collection - %min_bin_vheap_size, % included in garbage_collection - modified_timing_level, - multi_scheduling, - multi_scheduling_blockers, - otp_release, - port_count, - process_count, - process_limit, - scheduler_bind_type, - scheduler_bindings, - scheduler_id, - schedulers, - schedulers_online, - smp_support, - system_version, - system_architecture, - threads, - thread_pool_size, - trace_control_word, - update_cpu_info, - version, - wordsize - ]). - --define(SOCKET_OPTS, [ - active, - broadcast, - delay_send, - dontroute, - exit_on_close, - header, - keepalive, - nodelay, - packet, - packet_size, - read_packets, - recbuf, - reuseaddr, - send_timeout, - send_timeout_close, - sndbuf, - priority, - tos - ]). - - - -export([loads/0, - get_system_info/0, - % get_statistics/0, - % get_process_info/0, - get_ports_info/0, - get_ets_info/0]). + scheduler_usage/1, + get_memory/0]). loads() -> [{load1, ftos(cpu_sup:avg1()/256)}, @@ -117,142 +52,69 @@ loads() -> ftos(F) -> [S] = io_lib:format("~.2f", [F]), S. -get_system_info() -> - [{Key, format_system_info(Key, get_system_info(Key))} || Key <- ?SYSTEM_INFO]. +%%%% erlang vm scheduler_usage fun copied from recon +scheduler_usage(Interval) when is_integer(Interval) -> + %% We start and stop the scheduler_wall_time system flag + %% if it wasn't in place already. Usually setting the flag + %% should have a CPU impact(make it higher) only when under low usage. + FormerFlag = erlang:system_flag(scheduler_wall_time), + First = erlang:statistics(scheduler_wall_time), + timer:sleep(Interval), + Last = erlang:statistics(scheduler_wall_time), + erlang:system_flag(scheduler_wall_time, FormerFlag), + scheduler_usage_diff(First, Last). -get_system_info(Key) -> - try erlang:system_info(Key) catch - error:badarg->undefined - end. +scheduler_usage_diff(First, Last) -> + lists:map( + fun({{I, A0, T0},{I, A1, T1}}) ->{I, (A1 - A0)/(T1 - T0)}end, + lists:zip(lists:sort(First), lists:sort(Last)) + ). -%% conversion functions for erlang:system_info(Key) +get_memory()-> + [{Key, get_memory(Key, current)} || Key <- [used, allocated, unused]] ++ erlang:memory(). -format_system_info(allocated_areas, List) -> - [convert_allocated_areas(Value) || Value <- List]; -format_system_info(allocator, {_,_,_,List}) -> - List; -format_system_info(dist_ctrl, List) -> - lists:map(fun({Node, Socket}) -> - {ok, Stats} = inet:getstat(Socket), - {Node, Stats} - end, List); -format_system_info(driver_version, Value) -> - list_to_binary(Value); -format_system_info(machine, Value) -> - list_to_binary(Value); -format_system_info(otp_release, Value) -> - list_to_binary(Value); -format_system_info(scheduler_bindings, Value) -> - tuple_to_list(Value); -format_system_info(system_version, Value) -> - list_to_binary(Value); -format_system_info(system_architecture, Value) -> - list_to_binary(Value); -format_system_info(version, Value) -> - list_to_binary(Value); -format_system_info(_, Value) -> - Value. +get_memory(used, Keyword) -> + lists:sum(lists:map(fun({_, Prop}) -> + container_size(Prop, Keyword, blocks_size) + end, util_alloc())). +util_alloc()-> + alloc(?UTIL_ALLOCATORS). -convert_allocated_areas({Key, Value1, Value2}) -> - {Key, [Value1, Value2]}; -convert_allocated_areas({Key, Value}) -> - {Key, Value}. +alloc()-> + {_Mem, Allocs} = snapshot_int(), + Allocs. +alloc(Type) -> + [{{T, Instance}, Props} || {{T, Instance}, Props} <- alloc(), lists:member(T, Type)]. +snapshot_int() -> + {erlang:memory(), allocators()}. -get_ports_info()-> - [{pid_port_fun_to_atom(Port), get_port_info(Port)} || Port <- erlang:ports()]. +allocators() -> + UtilAllocators = erlang:system_info(alloc_util_allocators), + Allocators = [sys_alloc, mseg_alloc|UtilAllocators], + [{{A, N},lists:sort(proplists:deleted(versions, Props))} || + A <- Allocators, + Allocs <- [erlang:system_info({allocator, A})], + Allocs =/= false, + {_, N, Props} <- Allocs]. -get_port_info(Port) -> - Stat = get_socket_getstat(Port), - SockName = get_socket_sockname(Port), - Opts = get_socket_opts(Port), - Protocol = get_socket_protocol(Port), - Status = get_socket_status(Port), - Type = get_socket_type(Port), +container_size(Prop, Keyword, Container) -> + Sbcs = container_value(Prop, Keyword, sbcs, Container), + Mbcs = container_value(Prop, Keyword, mbcs, Container), + Sbcs+Mbcs. - lists:flatten(lists:append([ - Stat, - SockName, - Opts, - Protocol, - Status, - Type - ])). +container_value(Prop, Keyword, Type, Container) when is_atom(Keyword)-> + container_value(Prop, 2, Type, Container); +container_value(Props, Pos, mbcs = Type, Container) when is_integer(Pos)-> + Pool = case proplists:get_value(mbcs_pool, Props) of + PoolProps when PoolProps =/= undefined -> + element(Pos, lists:keyfind(Container, 1, PoolProps)); + _ -> 0 + end, + TypeProps = proplists:get_value(Type, Props), + Pool + element(Pos, lists:keyfind(Container, 1, TypeProps)); -get_socket_getstat(Socket) -> - case catch inet:getstat(Socket) of - {ok, Info} -> - Info; - _ -> - [] - end. +container_value(Props, Pos, Type, Container) -> + TypeProps = proplists:get_value(Type, Props), + element(Pos, lists:keyfind(Container, 1, TypeProps)). -get_socket_sockname(Socket) -> - case catch inet:sockname(Socket) of - {ok, {Ip, Port}} -> - [{ip, ip_to_binary(Ip)}, {port, Port}]; - _ -> - [] - end. - -ip_to_binary(Tuple) -> - iolist_to_binary(string:join(lists:map(fun integer_to_list/1, tuple_to_list(Tuple)), ".")). - - -get_socket_protocol(Socket) -> - case erlang:port_info(Socket, name) of - {name, "tcp_inet"} -> - [{protocol, tcp}]; - {name, "udp_inet"} -> - [{protocol, udp}]; - {name,"sctp_inet"} -> - [{protocol, sctp}]; - _ -> - [] - end. - -get_socket_status(Socket) -> - case catch prim_inet:getstatus(Socket) of - {ok, Status} -> - [{status, Status}]; - _ -> - [] - end. - -get_socket_type(Socket) -> - case catch prim_inet:gettype(Socket) of - {ok, Type} -> - [{type, tuple_to_list(Type)}]; - _ -> - [] - end. - -get_socket_opts(Socket) -> - [get_socket_opts(Socket, Key) || Key <- ?SOCKET_OPTS]. - -get_socket_opts(Socket, Key) -> - case catch inet:getopts(Socket, [Key]) of - {ok, Opt} -> - Opt; - _ -> - [] - end. - -get_ets_info() -> - [{Tab, get_ets_dets_info(ets, Tab)} || Tab <- ets:all()]. - -get_ets_dets_info(Type, Tab) -> - case Type:info(Tab) of - undefined -> []; - Entries when is_list(Entries) -> - [{Key, pid_port_fun_to_atom(Value)} || {Key, Value} <- Entries] - end. - -pid_port_fun_to_atom(Term) when is_pid(Term) -> - erlang:list_to_atom(pid_to_list(Term)); -pid_port_fun_to_atom(Term) when is_port(Term) -> - erlang:list_to_atom(erlang:port_to_list(Term)); -pid_port_fun_to_atom(Term) when is_function(Term) -> - erlang:list_to_atom(erlang:fun_to_list(Term)); -pid_port_fun_to_atom(Term) -> - Term. From 4d6e68e2edae12f613ec6210b84f88d741d8e88b Mon Sep 17 00:00:00 2001 From: huangdan Date: Sun, 31 May 2015 16:27:46 +0800 Subject: [PATCH 2/8] memory usage unused --- apps/emqttd/src/emqttd_vm.erl | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index c083bfda2..4e97e0419 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -71,12 +71,21 @@ scheduler_usage_diff(First, Last) -> ). get_memory()-> - [{Key, get_memory(Key, current)} || Key <- [used, allocated, unused]] ++ erlang:memory(). + [{Key, get_memory(Key, current)} || Key <- [used, allocated, unused, usage]] ++ erlang:memory(). get_memory(used, Keyword) -> lists:sum(lists:map(fun({_, Prop}) -> container_size(Prop, Keyword, blocks_size) - end, util_alloc())). + end, util_alloc())); +get_memory(allocated, Keyword) -> + lists:sum(lists:map(fun({_, Prop})-> + container_size(Prop, Keyword, carriers_size) + end, util_alloc())); +get_memory(unused, Keyword) -> + get_memory(allocated, Keyword) - get_memory(used, Keyword); +get_memory(usage, Keyword) -> + get_memory(used, Keyword) / get_memory(allocated, Keyword). + util_alloc()-> alloc(?UTIL_ALLOCATORS). From e81e8c92a0193f4914a322a1b1302b68261e490f Mon Sep 17 00:00:00 2001 From: huangdan Date: Sun, 31 May 2015 20:08:42 +0800 Subject: [PATCH 3/8] process list --- apps/emqttd/src/emqttd_vm.erl | 36 ++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index 4e97e0419..71c27c9ba 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -37,12 +37,18 @@ std_alloc ]). +-define(PROCESS_LIST, [initial_call, + reductions, + memory, + message_queue_len, + current_function]). -author("Feng Lee "). -export([loads/0, scheduler_usage/1, - get_memory/0]). + get_memory/0, + get_process_list/0]). loads() -> [{load1, ftos(cpu_sup:avg1()/256)}, @@ -57,7 +63,7 @@ scheduler_usage(Interval) when is_integer(Interval) -> %% We start and stop the scheduler_wall_time system flag %% if it wasn't in place already. Usually setting the flag %% should have a CPU impact(make it higher) only when under low usage. - FormerFlag = erlang:system_flag(scheduler_wall_time), + FormerFlag = erlang:system_flag(scheduler_wall_time, true), First = erlang:statistics(scheduler_wall_time), timer:sleep(Interval), Last = erlang:statistics(scheduler_wall_time), @@ -101,7 +107,7 @@ snapshot_int() -> allocators() -> UtilAllocators = erlang:system_info(alloc_util_allocators), Allocators = [sys_alloc, mseg_alloc|UtilAllocators], - [{{A, N},lists:sort(proplists:deleted(versions, Props))} || + [{{A, N},lists:sort(proplists:delete(versions, Props))} || A <- Allocators, Allocs <- [erlang:system_info({allocator, A})], Allocs =/= false, @@ -127,3 +133,27 @@ container_value(Props, Pos, Type, Container) -> TypeProps = proplists:get_value(Type, Props), element(Pos, lists:keyfind(Container, 1, TypeProps)). +get_process_list()-> + [get_process_list(Pid) || Pid <- processes()]. + +get_process_list(Pid) when is_pid(Pid) -> + Info = [process_info(Pid, Key) || Key <- ?PROCESS_LIST], + [{pid, pid_port_fun_to_atom(Pid)}] ++ lists:flatten([convert_pid_info(Item) || Item <- Info]). + +convert_pid_info({initial_call,{_M, F, _A}}) -> + {initial_call, F}; +convert_pid_info({current_function, {M, F, A}}) -> + {current_function, list_to_atom(lists:concat([atom_to_list(M),":",atom_to_list(F),"/",integer_to_list(A)]))}; +convert_pid_info({Key, Term}) when is_pid(Term) or is_port(Term) or is_function(Term) -> + {Key, pid_port_fun_to_atom(Term)}; +convert_pid_info(Item) -> + Item. + +pid_port_fun_to_atom(Term) when is_pid(Term) -> + erlang:list_to_atom(pid_to_list(Term)); +pid_port_fun_to_atom(Term) when is_port(Term) -> + erlang:list_to_atom(erlang:port_to_list(Term)); +pid_port_fun_to_atom(Term) when is_function(Term) -> + erlang:list_to_atom(erlang:fun_to_list(Term)); +pid_port_fun_to_atom(Term) -> + Term. From 228e6bd6fbddc775606472095c01abf17a6c2d87 Mon Sep 17 00:00:00 2001 From: huangdan Date: Sun, 31 May 2015 22:14:16 +0800 Subject: [PATCH 4/8] processgc ,leader_process info --- apps/emqttd/src/emqttd_vm.erl | 49 ++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index 71c27c9ba..9808ec898 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -43,12 +43,39 @@ message_queue_len, current_function]). +-define(PROCESS_INFO, [initial_call, + current_function, + registered_name, + status, + message_queue_len, + group_leader, + priority, + trap_exit, + reductions, + binary, + last_calls, + catchlevel, + trace, + suspending, + sequential_trace_token, + error_handler]). + +-define(PROCESS_GC, [memory, + total_heap_size, + heap_size, + stack_size, + min_heap_size]).%, + %fullsweep_after]). + -author("Feng Lee "). -export([loads/0, scheduler_usage/1, get_memory/0, - get_process_list/0]). + get_process_list/0, + get_process_info/0, + get_process_gc/0, + get_process_group_leader_info/1]). loads() -> [{load1, ftos(cpu_sup:avg1()/256)}, @@ -140,10 +167,30 @@ get_process_list(Pid) when is_pid(Pid) -> Info = [process_info(Pid, Key) || Key <- ?PROCESS_LIST], [{pid, pid_port_fun_to_atom(Pid)}] ++ lists:flatten([convert_pid_info(Item) || Item <- Info]). +get_process_info() -> + [get_process_info(Pid) || Pid <- processes()]. +get_process_info(Pid) when is_pid(Pid) -> + ProcessInfo = [process_info(Pid, Key) || Key <- ?PROCESS_INFO], + lists:flatten([convert_pid_info(Item) || Item <- ProcessInfo]). + +get_process_gc() -> + [get_process_gc(Pid) || Pid <- processes()]. +get_process_gc(Pid) when is_pid(Pid) -> + GcInfo = [process_info(Pid, Key) || Key <- ?PROCESS_GC], + lists:flatten([convert_pid_info(E) || E <- GcInfo]). + +get_process_group_leader_info(LeaderPid) when is_pid(LeaderPid) -> + LeaderInfo = [{Key, Value}|| {Key, Value} <- process_info(LeaderPid), lists:member(Key, ?PROCESS_INFO)], + lists:flatten([convert_pid_info(E) || E <- LeaderInfo]). + convert_pid_info({initial_call,{_M, F, _A}}) -> {initial_call, F}; convert_pid_info({current_function, {M, F, A}}) -> {current_function, list_to_atom(lists:concat([atom_to_list(M),":",atom_to_list(F),"/",integer_to_list(A)]))}; +convert_pid_info({suspending, List}) -> + {suspending, [pid_port_fun_to_atom(E) || E <- List]}; +convert_pid_info({binary, List}) -> + {binary,[tuple_to_list(E) || E <- List]}; convert_pid_info({Key, Term}) when is_pid(Term) or is_port(Term) or is_function(Term) -> {Key, pid_port_fun_to_atom(Term)}; convert_pid_info(Item) -> From 1257b53951fdb5e77abbfadbb2030811753e78a0 Mon Sep 17 00:00:00 2001 From: huangdan Date: Mon, 1 Jun 2015 12:19:54 +0800 Subject: [PATCH 5/8] ets info --- apps/emqttd/src/emqttd_vm.erl | 46 ++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index 9808ec898..9eb5374ad 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -75,7 +75,13 @@ get_process_list/0, get_process_info/0, get_process_gc/0, - get_process_group_leader_info/1]). + get_process_group_leader_info/1, + get_ets_list/0, + get_ets_info/0, + get_ets_info/1, + get_ets_object/0, + get_ets_object/1 + ]). loads() -> [{load1, ftos(cpu_sup:avg1()/256)}, @@ -183,6 +189,44 @@ get_process_group_leader_info(LeaderPid) when is_pid(LeaderPid) -> LeaderInfo = [{Key, Value}|| {Key, Value} <- process_info(LeaderPid), lists:member(Key, ?PROCESS_INFO)], lists:flatten([convert_pid_info(E) || E <- LeaderInfo]). +get_ets_list() -> + ets:all(). + +get_ets_info() -> + [get_ets_info(Tab) || Tab <- ets:all()]. + +get_ets_info(Tab) -> + case ets:info(Tab) of + undefined -> + []; + Entries when is_list(Entries) -> + mapping(Entries) + end. + +get_ets_object() -> + [{Tab, get_ets_object(Tab)} || Tab <- ets:all()]. + +get_ets_object(Tab) -> + TabInfo = ets:info(Tab), + Size = proplists:get_value(size, TabInfo), + NameTab = proplists:get_value(named_table, TabInfo), + if (Size == 0) or (NameTab == false) -> + []; + true -> + ets:tab2list(Tab) + end. + +mapping(Entries) -> + mapping(Entries, []). +mapping([], Acc) -> + Acc; +mapping([{owner, V}|Entries], Acc) when is_pid(V) -> + OwnerInfo = process_info(V), + Owner = proplists:get_value(registered_name, OwnerInfo, undefined), + mapping(Entries, [{owner, pid_port_fun_to_atom(Owner)}|Acc]); +mapping([{Key, Value}|Entries], Acc) -> + mapping(Entries, [{Key, pid_port_fun_to_atom(Value)}|Acc]). + convert_pid_info({initial_call,{_M, F, _A}}) -> {initial_call, F}; convert_pid_info({current_function, {M, F, A}}) -> From de3b0fb8c0573662a9fa464d7c9b6c5f9cf5a4c9 Mon Sep 17 00:00:00 2001 From: huangdan Date: Mon, 1 Jun 2015 23:13:34 +0800 Subject: [PATCH 6/8] ports_type --- apps/emqttd/src/emqttd_vm.erl | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index 9eb5374ad..84add1311 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -70,18 +70,23 @@ -author("Feng Lee "). -export([loads/0, - scheduler_usage/1, - get_memory/0, - get_process_list/0, + scheduler_usage/1]). + +-export([get_memory/0]). + +-export([get_process_list/0, get_process_info/0, get_process_gc/0, - get_process_group_leader_info/1, - get_ets_list/0, + get_process_group_leader_info/1]). + +-export([get_ets_list/0, get_ets_info/0, get_ets_info/1, get_ets_object/0, - get_ets_object/1 - ]). + get_ets_object/1]). + +-export([get_port_types/0]). + loads() -> [{load1, ftos(cpu_sup:avg1()/256)}, @@ -216,6 +221,20 @@ get_ets_object(Tab) -> ets:tab2list(Tab) end. +get_port_types() -> + lists:usort(fun({KA, VA},{KB, VB})-> {VA, KB} >{VB, KA} end, + ports_type_count([Type || {_Port, Type} <- ports_type_list()])). + +ports_type_list() -> + [{Port, PortType} || Port <- erlang:ports(), + {_, PortType} <- [erlang:port_info(Port, name)]]. + +ports_type_count(Types) -> + DictTypes = lists:foldl(fun(Type, Acc)-> + dict:update_counter(Type, 1, Acc) + end, dict:new(), Types), + dict:to_list(DictTypes). + mapping(Entries) -> mapping(Entries, []). mapping([], Acc) -> From ae54ec1343cfe99e08eb41ca4155098b82f0ffa3 Mon Sep 17 00:00:00 2001 From: huangdan Date: Wed, 3 Jun 2015 14:07:18 +0800 Subject: [PATCH 7/8] port info --- apps/emqttd/src/emqttd_vm.erl | 125 +++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 1 deletion(-) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index 84add1311..87c7aafd5 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -67,6 +67,37 @@ min_heap_size]).%, %fullsweep_after]). +-define(SOCKET_OPTS, [ + active, + broadcast, + buffer, + buffer, + buffer, + buffer, + delay_send, + dontroute, + exit_on_close, + header, + high_watermark, + ipv6_v6only, + keepalive, + linger, + low_watermark, + mode, + nodelay, + packet, + packet_size, + priority, + read_packets, + recbuf, + reuseaddr, + send_timeout, + send_timeout_close, + sndbuf, + tos + ]). + + -author("Feng Lee "). -export([loads/0, @@ -85,7 +116,9 @@ get_ets_object/0, get_ets_object/1]). --export([get_port_types/0]). +-export([get_port_types/0, + get_port_info/0, + get_port_info/1]). loads() -> @@ -225,6 +258,83 @@ get_port_types() -> lists:usort(fun({KA, VA},{KB, VB})-> {VA, KB} >{VB, KA} end, ports_type_count([Type || {_Port, Type} <- ports_type_list()])). +get_port_info() -> + [get_port_info(Port) ||Port <- erlang:ports()]. + +get_port_info(PortTerm) -> + Port = transform_port(PortTerm), + [port_info(Port, Type) || Type <- [meta, signals, io, memory_used, specific]]. + +port_info(Port, meta) -> + {meta, List} = port_info_type(Port, meta, [id, name, os_pid]), + case port_info(Port, registered_name) of + [] -> {meta, List}; + Name -> {meta, [Name | List]} +end; + +port_info(PortTerm, signals) -> + port_info_type(PortTerm, signals, [connected, links, monitors]); + +port_info(PortTerm, io) -> + port_info_type(PortTerm, io, [input, output]); + +port_info(PortTerm, memory_used) -> + port_info_type(PortTerm, memory_used, [memory, queue_size]); + +port_info(PortTerm, specific) -> + Port = transform_port(PortTerm), + Props = case erlang:port_info(Port, name) of + {_, Type} when Type =:= "udp_inet"; + Type =:= "tcp_inet"; + Type =:= "sctp_inet" -> + case catch inet:getstat(Port) of + {ok, Stats} -> [{statistics, Stats}]; + _ ->[] + + end ++ + case catch inet:peername(Port) of + {ok, Peer} ->[{peername, Peer}]; + {error, _} ->[] + end ++ + case catch inet:sockname(Port) of + {ok, Local} ->[{sockname, Local}]; + {error, _} -> [] +end ++ +case catch inet:getopts(Port, ?SOCKET_OPTS ) of + {ok, Opts} -> [{options, Opts}]; + {error, _} -> [] +end; + {_, "efile"} -> + []; + _ ->[] +end, + {specific, Props}; +port_info(PortTerm, Keys) when is_list(Keys) -> + Port = transform_port(PortTerm), + [erlang:port_info(Port, Key) || Key <- Keys]; +port_info(PortTerm, Key) when is_atom(Key) -> + Port = transform_port(PortTerm), + erlang:port_info(Port, Key). + +port_info_type(PortTerm, Type, Keys) -> + Port = transform_port(PortTerm), + {Type, [erlang:port_info(Port, Key) || Key <- Keys]}. + +transform_port(Port) when is_port(Port) -> Port; +transform_port("#Port<0." ++ Id) -> + N = list_to_integer(lists:sublist(Id, length(Id) - 1)), + transform_port(N); +transform_port(N) when is_integer(N) -> + Name = iolist_to_binary(atom_to_list(node())), + NameLen = iolist_size(Name), + Vsn = binary:last(term_to_binary(self())), + Bin = <<131, 102, 100, + NameLen:2/unit:8, + Name:NameLen/binary, + N:4/unit:8, + Vsn:8>>, + binary_to_term(Bin). + ports_type_list() -> [{Port, PortType} || Port <- erlang:ports(), {_, PortType} <- [erlang:port_info(Port, name)]]. @@ -246,6 +356,9 @@ mapping([{owner, V}|Entries], Acc) when is_pid(V) -> mapping([{Key, Value}|Entries], Acc) -> mapping(Entries, [{Key, pid_port_fun_to_atom(Value)}|Acc]). +%ip_to_binary(Tuple) -> +% iolist_to_binary(string:join(lists:map(fun integer_to_list/1, tuple_to_list(Tuple)), ".")). + convert_pid_info({initial_call,{_M, F, _A}}) -> {initial_call, F}; convert_pid_info({current_function, {M, F, A}}) -> @@ -259,6 +372,16 @@ convert_pid_info({Key, Term}) when is_pid(Term) or is_port(Term) or is_function( convert_pid_info(Item) -> Item. +%convert_port_info({name, Name}) -> +% {name, list_to_binary(Name)}; +%convert_port_info({links, List}) -> +% {links, [pid_port_fun_to_atom(Item) || Item <- List]}; +%convert_port_info({connected, Pid}) -> +% erlang:process_info(Pid, registered_name); +%convert_port_info(Item) -> +% Item. + + pid_port_fun_to_atom(Term) when is_pid(Term) -> erlang:list_to_atom(pid_to_list(Term)); pid_port_fun_to_atom(Term) when is_port(Term) -> From a047d34959a31d1e97235eee5bed06bf3023c964 Mon Sep 17 00:00:00 2001 From: huangdan Date: Wed, 3 Jun 2015 18:19:40 +0800 Subject: [PATCH 8/8] merge dev --- apps/emqttd/src/emqttd_vm.erl | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/emqttd/src/emqttd_vm.erl b/apps/emqttd/src/emqttd_vm.erl index 87c7aafd5..d76942619 100644 --- a/apps/emqttd/src/emqttd_vm.erl +++ b/apps/emqttd/src/emqttd_vm.erl @@ -100,6 +100,8 @@ -author("Feng Lee "). +-export([timestamp/0, microsecs/0]). + -export([loads/0, scheduler_usage/1]). @@ -120,6 +122,13 @@ get_port_info/0, get_port_info/1]). +timestamp() -> + {MegaSecs, Secs, _MicroSecs} = os:timestamp(), + MegaSecs * 1000000 + Secs. + +microsecs() -> + {Mega, Sec, Micro} = erlang:now(), + (Mega * 1000000 + Sec) * 1000000 + Micro. loads() -> [{load1, ftos(cpu_sup:avg1()/256)},