gproc_info.erl 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. %% ``The contents of this file are subject to the Erlang Public License,
  2. %% Version 1.1, (the "License"); you may not use this file except in
  3. %% compliance with the License. You should have received a copy of the
  4. %% Erlang Public License along with this software. If not, it can be
  5. %% retrieved via the world wide web at http://www.erlang.org/.
  6. %%
  7. %% Software distributed under the License is distributed on an "AS IS"
  8. %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  9. %% the License for the specific language governing rights and limitations
  10. %% under the License.
  11. %%
  12. %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
  13. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
  14. %% AB. All Rights Reserved.''
  15. %%
  16. %% @author Ulf Wiger <ulf@wiger.net>
  17. %%
  18. -module(gproc_info).
  19. -export([i/0]).
  20. -import(lists, [foldl/3]).
  21. -import(io, [format/2]).
  22. %% c:i() extended with gproc info
  23. -spec i() -> 'ok'.
  24. i() -> i(processes()).
  25. -spec i([pid()]) -> 'ok'.
  26. i(Ps) ->
  27. i(Ps, length(Ps)).
  28. -spec i([pid()], non_neg_integer()) -> 'ok'.
  29. i(Ps, N) when N =< 100 ->
  30. iformat("Pid", "Initial Call", "Heap", "Reds",
  31. "Msgs"),
  32. iformat("Registered", "Current Function", "Stack", "",
  33. ""),
  34. {R,M,H,S} = foldl(fun(Pid, {R0,M0,H0,S0}) ->
  35. {A,B,C,D} = display_info(Pid),
  36. {R0+A,M0+B,H0+C,S0+D}
  37. end, {0,0,0,0}, Ps),
  38. iformat("Total", "", w(H), w(R), w(M)),
  39. iformat("", "", w(S), "", "");
  40. i(Ps, N) ->
  41. iformat("Pid", "Initial Call", "Heap", "Reds",
  42. "Msgs"),
  43. iformat("Registered", "Current Function", "Stack", "",
  44. ""),
  45. paged_i(Ps, {0,0,0,0}, N, 50).
  46. paged_i([], {R,M,H,S}, _, _) ->
  47. iformat("Total", "", w(H), w(R), w(M)),
  48. iformat("", "", w(S), "", "");
  49. paged_i(Ps, Acc, N, Page) ->
  50. {Pids, Rest, N1} =
  51. if N > Page ->
  52. {L1,L2} = lists:split(Page, Ps),
  53. {L1,L2,N-Page};
  54. true ->
  55. {Ps, [], 0}
  56. end,
  57. NewAcc = foldl(fun(Pid, {R,M,H,S}) ->
  58. {A,B,C,D} = display_info(Pid),
  59. {R+A,M+B,H+C,S+D}
  60. end, Acc, Pids),
  61. case Rest of
  62. [_|_] ->
  63. choice(fun() -> paged_i(Rest, NewAcc, N1, Page) end);
  64. [] ->
  65. paged_i([], NewAcc, 0, Page)
  66. end.
  67. choice(F) ->
  68. case get_line('(c)ontinue (q)uit -->', "c\n") of
  69. "c\n" ->
  70. F();
  71. <<"c\n">> ->
  72. F();
  73. "q\n" ->
  74. quit;
  75. <<"q\n">> ->
  76. quit;
  77. _ ->
  78. choice(F)
  79. end.
  80. iformat(A1, A2, A3, A4, A5) ->
  81. format("~-21s ~-33s ~8s ~8s ~4s~n", [A1,A2,A3,A4,A5]).
  82. get_line(P, Default) ->
  83. case io:get_line(P) of
  84. "\n" ->
  85. Default;
  86. L ->
  87. L
  88. end.
  89. w(X) ->
  90. io_lib:write(X).
  91. w(X, L) ->
  92. S = lists:flatten(io_lib:format("~w", [X])),
  93. case length(S) of
  94. Len when Len > L ->
  95. lists:sublist(S, 1, L-3) ++ "...";
  96. _ ->
  97. S
  98. end.
  99. display_info(Pid) ->
  100. Res = c:display_info(Pid),
  101. {gproc, GI} = gproc:info(Pid, gproc),
  102. case GI of
  103. [] ->
  104. skip;
  105. _ ->
  106. display_gproc_info("Gproc: ", [{n, N,S,V} || {{n,S,N},V} <- GI]),
  107. display_gproc_info(" ", [{p, N,S,V} || {{p,S,N},V} <- GI])
  108. end,
  109. Res.
  110. display_gproc_info(_, []) ->
  111. skip;
  112. display_gproc_info(Hdr, [H|T] = Entries) ->
  113. L = 3 + length(Hdr),
  114. Max = 78 - L - 8,
  115. {Ck, Cv} = info_cols(Entries, Max),
  116. Fmt = fun(I, {Type, K, Sc, V}) ->
  117. if Cv == 0 ->
  118. io_lib:format(
  119. I ++ "~w,~w: ~-" ++ i2l(Ck)
  120. ++ "s ~n", [Type, Sc, w(K, Ck)]);
  121. true ->
  122. io_lib:format(
  123. I ++ "~w,~w: ~-" ++ i2l(Ck)
  124. ++ "s | ~-" ++ i2l(Cv) ++ "s~n",
  125. [Type, Sc, w(K, Ck), w(V, Cv)])
  126. end
  127. end,
  128. format(" ~s~s", [Hdr, Fmt("", H)]),
  129. Indent = lists:duplicate(L, $\s),
  130. lists:foreach(
  131. fun(X) ->
  132. io:format(Fmt(Indent, X))
  133. end, T).
  134. info_cols(L, Max) ->
  135. case [V || {_,_,_,V} <- L, V =/= undefined] of
  136. [] ->
  137. {Max, 0};
  138. _ ->
  139. KMax = lists:max([w_length(K) || {_,K,_,_} <- L]),
  140. Ck = erlang:min(KMax, round(Max*2/3)),
  141. {Ck, Max - Ck}
  142. end.
  143. w_length(Term) ->
  144. lists:flatlength(io_lib:format("~w", [Term])).
  145. i2l(I) ->
  146. integer_to_list(I).