docs: def memory_usage(proc=-1, interval=.1, timeout=None, run_in_place=False):
      """
      Return the memory usage of a process or piece of code
  
      Parameters
      ----------
      proc : {int, string, tuple}, optional
          The process to monitor. Can be given by a PID, by a string
          containing a filename or by a tuple. The tuple should contain
          three values (f, args, kw) specifies to run the function
          f(*args, **kw).  Set to -1 (default) for current process.
  
      interval : float, optional
  
      timeout : float, optional
  
  
      run_in_place : boolean, optional. False by default
          If False fork the process and retrieve timings from a different
          process. You shouldn't need to change this unless you are affected
          by this (http://blog.vene.ro/2012/07/04/on-why-my-memit-fails-on-osx)
          bug.
  
      Returns
      -------
      mm : list of integers, size less than num
          memory usage, in KB
      """
      ret = []
  
      if timeout is not None:
          max_iter = timeout / interval
      elif isinstance(proc, int):
          # external process and no timeout
          max_iter = 1
      else:
          # for a Python function wait until it finishes
          max_iter = float('inf')
  
      if str(proc).endswith('.py'):
          filename = _find_script(proc)
          with open(filename) as f:
              proc = f.read()
          raise NotImplementedError
  
      if isinstance(proc, (list, tuple)):
  
          if len(proc) == 1:
              f, args, kw = (proc[0], (), {})
          elif len(proc) == 2:
              f, args, kw = (proc[0], proc[1], {})
          elif len(proc) == 3:
              f, args, kw = (proc[0], proc[1], proc[2])
          else:
              raise ValueError
          try:
              import multiprocessing
          except ImportError:
              print ('WARNING: cannot import module `multiprocessing`. Forcing to'
                     ' run inplace.')
              # force inplace
              run_in_place = True
          if run_in_place:
              import threading
              main_thread = threading.Thread(target=f, args=args, kwargs=kw)
          else:
              main_thread = multiprocessing.Process(target=f, args=args, kwargs=kw)
          i = 0
          main_thread.start()
          pid = getattr(main_thread, 'pid', os.getpid())
          while i < max_iter and main_thread.is_alive():
              m = _get_memory(pid)
              ret.append(m)
              time.sleep(interval)
              i += 1
          main_thread.join()
      else:
          # external process
          if proc == -1:
              proc = os.getpid()
          if max_iter == -1:
              max_iter = 1
          for _ in range(max_iter):
              ret.append(_get_memory(proc))
              time.sleep(interval)
      return ret