docs: def update_gunicorns():
      """
      Updates the dict of gunicorn processes. Run the ps command and parse its
      output for processes named after gunicorn, building up a dict of gunicorn
      processes. When new gunicorns are discovered, run the netstat command to
      determine the ports they're serving on.
      """
      global tick
      tick += 1
      if (tick * screen_delay) % ps_delay != 0:
          return
      tick = 0
      for pid in gunicorns:
          gunicorns[pid].update({"workers": 0, "mem": 0})
      ps = Popen(PS_ARGS, stdout=PIPE).communicate()[0].split("\n")
      headings = ps.pop(0).split()
      name_col = headings.index(cmd_heading)
      num_cols = len(headings) - 1
      for row in ps:
          cols = row.split(None, num_cols)
          if cols and "gunicorn: " in cols[name_col]:
              if "gunicorn: worker" in cols[name_col]:
                  is_worker = True
              else:
                  is_worker = False
  
              if is_worker:
                  pid = cols[headings.index("PPID")]
              else:
                  pid = cols[headings.index("PID")]
              if pid not in gunicorns:
                  gunicorns[pid] = {"workers": 0, "mem": 0, "port": None, "name":
                      cols[name_col].strip().split("[",1)[1].split("]",1)[:-1]}
              gunicorns[pid]["mem"] += int(cols[headings.index("RSS")])
              if is_worker:
                  gunicorns[pid]["workers"] += 1
      # Remove gunicorns that were not found in the process list.
      for pid in gunicorns.keys()[:]:
          if gunicorns[pid]["workers"] == 0:
              del gunicorns[pid]
      # Determine ports if any are missing.
      if not [g for g in gunicorns.values() if g["port"] is None]:
          return
      for (pid, port) in ports_for_pids(gunicorns.keys()):
          if pid in gunicorns:
              gunicorns[pid]["port"] = port