class_docstr: Allows easy observation of a given PID for resource usage
class_docstr_tok: ["Allows","easy","observation","of","a","given","PID","for","resource","usage"]
docstr: Perform the actual measurement
docstr_tok: ["Perform","the","actual","measurement"]
code: def _update_record(self):
      """Perform the actual measurement"""
      import psutil
  
      # Memory measurements
      rss, vms, uss, pss = 0, 0, 0, 0
      # I/O measurements
      io_in, io_out = 0, 0
      check_io = True
      # CPU seconds
      cpu_usages = 0
      # CPU usage time
      cpu_time = 0
  
      data_collected = False
      # Iterate over process and all children
      try:
          this_time = time.time()
          for proc in chain(
              (self.main,), self.main.children(recursive=True)
          ):
              proc = self.procs.setdefault(proc.pid, proc)
              with proc.oneshot():
                  if self.bench_record.prev_time:
                      cpu_usages += proc.cpu_percent() * (
                          this_time - self.bench_record.prev_time
                      )
                  # Makes it possible to summarize information about the process even
                  # if the benchmark has tried to access a process that the user does
                  # not have access to.
                  try:
                      meminfo = proc.memory_full_info()
                  except psutil.Error:
                      # Continue to fetch information about the remaining processes
                      # save skipped processes pid and name for debugging
                      self.bench_record.skipped_procs.add(
                          (proc.pid, proc.name())
                      )
                      continue
                  rss += meminfo.rss
                  vms += meminfo.vms
                  uss += meminfo.uss
                  pss += meminfo.pss
  
                  if check_io:
                      try:
                          ioinfo = proc.io_counters()
                          io_in += ioinfo.read_bytes
                          io_out += ioinfo.write_bytes
                      except NotImplementedError as nie:
                          # OS doesn't track IO
                          check_io = False
  
                  cpu_times = proc.cpu_times()
                  self.bench_record.processed_procs[
                      (proc.pid, proc.name())
                  ] = (cpu_times.user + cpu_times.system)
  
          cpu_time = sum(self.bench_record.processed_procs.values())
  
          self.bench_record.prev_time = this_time
          if not self.bench_record.first_time:
              self.bench_record.prev_time = this_time
  
          rss /= 1024 * 1024
          vms /= 1024 * 1024
          uss /= 1024 * 1024
          pss /= 1024 * 1024
  
          if check_io:
              io_in /= 1024 * 1024
              io_out /= 1024 * 1024
          else:
              io_in = None
              io_out = None
          data_collected = True
      except psutil.Error as e:
          return
  
      # Update benchmark record's RSS and VMS
      if data_collected:
          self.bench_record.data_collected = True
          self.bench_record.max_rss = max(
              self.bench_record.max_rss or 0, rss
          )
          self.bench_record.max_vms = max(
              self.bench_record.max_vms or 0, vms
          )
          self.bench_record.max_uss = max(
              self.bench_record.max_uss or 0, uss
          )
          self.bench_record.max_pss = max(
              self.bench_record.max_pss or 0, pss
          )
  
          self.bench_record.io_in = io_in
          self.bench_record.io_out = io_out
  
          self.bench_record.cpu_usages += cpu_usages
          self.bench_record.cpu_time = cpu_time
  
imports: import contextlib
  import datetime
  from itertools import chain
  import os
  import time
  import threading
  from snakemake.logging import logger
label_desc: Use image node_id 3 for calling the BenchmarkTimer obj's underlying member method code with example usage: obj._update_record() without return types