anchor.diff:                       Pid = element(1, X),
                        pdb:delete(Pid, TableName),
                        %% plot data is:
  -                     Status = try element(2, process_info(Pid, status))
  -                              catch _:_ -> dead_pid
  -                              end,
  +                     Infos = try_process_info(Pid, [status, memory, stack_size]),
  +                     Status = process_info_get(Infos, status, dead_pid),
                        {vals_pid(X),
                         Status,
                         vals_mqlen(X)/Count,
                         vals_cpu_usage(X, Count),
  -                      try element(2, process_info(Pid, memory))
  -                      catch _Level2:_Reason2 -> 0
  -                      end}
  +                      process_info_get(Infos, memory, 0),
  +                      process_info_get(Infos, stack_size, 0)}
                    end || X <- R1, is_tuple(X), is_pid(element(1, X)) ],
       SortedPlotData = lists:keysort(sort_by(State), PlotData),
       L = length(SortedPlotData),
  
positive.code:     catch _:_ -> ok
      end,
      {pdb:new(?MODULE, [set, protected]), false, false,
       os:timestamp(), 0, _SortBy = 3, self()}.
  
  -spec top() -> ok.
  top() ->
      io:format("~p~n", [io:rows(standard_io)]),
      Pid = pid_groups:find_a(?MODULE),
      comm:send_local(Pid, {mon_on}),
      comm:send_local(Pid, {output_on}),
      comm:send_local(Pid, {start_mon}),
      top_interactive(Pid),
      comm:send_local(Pid, {output_off}),
      comm:send_local(Pid, {stop_mon}).
  
  top_interactive(Pid) ->
      {ok, [Char]} = io:fread(">", "~c"),
      Quit =
          case Char of
              "q" -> quit;
              "e" ->
                  comm:send_local(Pid, {output_off}),
                  Expr = io:parse_erl_exprs('expr>'),
                  comm:send_local(Pid, {output_on}),
                  case element(1, Expr) of
                      ok ->
                          spawn(fun() -> erl_eval:exprs(element(2, Expr), erl_eval:new_bindings()) end),
  
negative.code:                                       _ -> Acc
                                    end end, 0, PlotData)
                ]),
      {{_, IOIn}, {_, IOOut}} = erlang:statistics(io),
      %% {GCNum, GCFreed, _} = erlang:statistics(garbage_collection),
      %% io:format("Context Switches: ~p Garb.Coll: ~p ~s~n",
      %%           [element(1, erlang:statistics(context_switches)),
      %%            GCNum, readable_mem(GCFreed)]),
  
      io:format("IO: ~s/~s in/out Mem: ~s procs, ~s atom, ~s binary, ~s ets~n",
                [readable_mem(IOIn), readable_mem(IOOut),
                 readable_mem(ProcsMem),
                 readable_mem(erlang:memory(atom)),
                 readable_mem(erlang:memory(binary)),
                 readable_mem(erlang:memory(ets))
                ]),
      io:format("FPS: ~.1f~n", [Count / Delay]),
      WordSize = erlang:system_info(wordsize),
      io:format("~11s ~1s ~1s ~-20s ~9s ~6s ~6s ~5s ~5s~n",
                [ "PID", "T", "S", "NAME", "W-Msg", "%CPU", "%MEM", "MEM", "STACK" ]),
      _ = [ begin
            Type = case catch(gen_component:is_gen_component(Pid)) of
                       true -> "G";
                       _ -> "E"
                   end,
            io:format("~11w ~1s ~1s ~-20s ~9.2f ~6.2f ~6.2f ~5s ~5s~n",
                      [Pid, Type, readable_status(Status),
                       readable_pid_name(Pid), MQLen, CPUUsage,
                       MemUsage / ProcsMemUsed * 100,
                       readable_mem(MemUsage),
                       readable_mem(WordSize * StackSize)])
        end
        || {Pid, Status, MQLen, CPUUsage, MemUsage, StackSize} <- lists:reverse(PlotThese)],
      usage(),
      msg_delay:send_local(2, self(), {output_all}),
      S1 = set_counter(State, 0),
      set_timestamp(S1, os:timestamp());
  
  on({output_all}, State) -> State;
  
  on({output_pid, Pid}, State) when pid =:= element(3, State) ->
      TableName = table(State),
      Now = os:timestamp(),
      Delay = timer:now_diff(Now, timestamp(State)) / 1000000,
      Count = counter(State),
      Infos = try_process_info(
                Pid, [dictionary, registered_name, memory, total_heap_size,
                      stack_size, status, message_queue_len, current_function]),
      PD = process_info_get(Infos, dictionary, 0),
      R1 = pdb:tab2list(TableName),
      PlotData = [ begin
                       pdb:delete(PidAndCFun, TableName),
                       %% plot data is:
                       {PidAndCFun,
                        no_status,
                        no_mqlen,
                        vals_cpu_usage(X, Count),
                        no_mem}
                   end || {PidAndCFun, _MQLen, _Status} = X <- R1
                          %% is_pid(element(1, element(1,X)))
                 ],
      SortedPlotData = lists:keysort(sort_by(State), PlotData),
      L = length(SortedPlotData),
      {ok, Lines} = io:rows(), %% terminal rows
      SkipLines = 11,
      {_, PlotThese} =
          lists:split(erlang:max(0, L - (Lines - SkipLines)), SortedPlotData),
  
      Time = element(2, calendar:local_time()),
      WallClock = element(1, erlang:statistics(wall_clock)) div 60000,
      io:format("top - ~2..0B:~2..0B:~2..0B up ~B days, ~B:~2..0B~n",
                [element(1, Time), element(2, Time), element(3, Time),
                 WallClock div (60*24),
                 WallClock rem (60*24) div 60,
                 (WallClock rem (60*60)) rem 60
                ]),
      IdlePlotDataEntry = lists:keyfind({Pid, not_running}, 1, PlotData),
      Idle = element(4, IdlePlotDataEntry),
      io:format("Pid: ~p, ~6.2f% run, ~6.2f% idle~n",
                [ Pid, 100.0 - Idle, Idle ]),
      io:format("Name: ~p",
                [process_info_get(Infos, registered_name, [])]),
      case gen_component:is_gen_component(Pid) of
          true -> io:format(" ~p", [readable_grp_and_pid_name(Pid)]);
          false -> ok
      end,
      io:format("~n"),
      MemUsage = process_info_get(Infos, memory, 0),
      HeapSize = process_info_get(Infos, total_heap_size, 0),
      StackSize = process_info_get(Infos, stack_size, 0),
      PDSize = case PD of
                   0 -> 0;
                   _ -> erlang:external_size(PD)
               end,
      WordSize = erlang:system_info(wordsize),
      io:format("Mem: ~s total, ~s heap, ~s stack, ~s dictionary (~p entries)~n",
                [readable_mem(MemUsage),
                 readable_mem((HeapSize - StackSize) * WordSize),
                 readable_mem(StackSize * WordSize),
                 readable_mem(PDSize), length(PD)
                ]),
  
      io:format("Status: ~s MQLen: ~p Current Function: ~p~n",
                [readable_status(
                   process_info_get(Infos, status, dead_pid)),
                 process_info_get(Infos, message_queueu_len, 0),
                 process_info_get(Infos, current_function, none)
                ]),
      io:format("FPS: ~.1f~n", [Count / Delay]),
  
      io:format("~11s ~-35s ~6s~n",
                [ "PID", "FUNCTION", "%TIME"]),
      _ = [ begin
                CFun = element(2, PlotPid),
                CFunString =
                    case is_tuple(CFun) of
                        true ->
                            io_lib:write(element(1, CFun))
                                ++ ":" ++ io_lib:write(element(2, CFun))
                                ++ "/" ++ io_lib:write(element(3, CFun));
                        false -> io_lib:write(CFun)
                    end,
                io:format("~11w ~-35s ~6.2f~n",
                          [element(1, PlotPid), CFunString, CPUUsage ])
            end
            || {PlotPid, _Status, _MQLen, CPUUsage, _MemUsage}
                   <- lists:reverse(PlotThese)],
      util:for_to(1, Lines - SkipLines - length(PlotThese),
                  fun(_) -> io:format("~n") end),
      usage_inspect(),
      msg_delay:send_local(2, self(), {output_pid, Pid}),
      S1 = set_counter(State, 0),
      set_timestamp(S1, os:timestamp());
  
  on({output_pid, _Pid}, State) -> State;
  
  on({stop_sampling}, State) ->
      TableName = table(State),
      R1 = pdb:tab2list(TableName),
      _ = [ pdb:delete(element(1, X), TableName)
            || {_,_,_} = X <- R1, is_pid(element(1, X)) ],
      S1 = set_counter(State, 0),
      set_sampling(S1, false).
  
  
  table(State) -> element(1, State).
  set_sampling(State, Val) -> setelement(2, State, Val).
  set_output(State, Val) -> setelement(3, State, Val).
  timestamp(State) -> element(4, State).
  set_timestamp(State, Val) -> setelement(4, State, Val).
  counter(State) -> element(5, State).
  inc_counter(State) -> setelement(5, State, 1 + element(5, State)).
  