()
| 22 | |
| 23 | |
| 24 | def Main(): |
| 25 | # Parse arguments. |
| 26 | args = [] |
| 27 | samplerate_secs = kDefaultSamplerateSecs |
| 28 | idx = 1 |
| 29 | while idx < len(sys.argv): |
| 30 | arg = sys.argv[idx] |
| 31 | if arg == "--": |
| 32 | args += sys.argv[(idx + 1):] |
| 33 | break |
| 34 | if arg in ("-h", "--help", "help"): |
| 35 | PrintHelp(0) |
| 36 | elif arg in ("--interval", "-I"): |
| 37 | if idx + 1 >= len(sys.argv): |
| 38 | PrintHelp(1) |
| 39 | samplerate_secs = int(sys.argv[idx + 1]) / 1000 |
| 40 | idx += 1 # Skip the value. |
| 41 | elif arg in ("--freq", "-F"): |
| 42 | if idx + 1 >= len(sys.argv): |
| 43 | PrintHelp(1) |
| 44 | samplerate_secs = 1 / float(sys.argv[idx + 1]) |
| 45 | idx += 1 # Skip the value. |
| 46 | else: |
| 47 | # No match for known parameter; assume it's part of the command to run. |
| 48 | args.append(arg) |
| 49 | idx += 1 # Go to next arg. |
| 50 | |
| 51 | cmd = " ".join(args) |
| 52 | print(f"sample rate: {samplerate_secs}") |
| 53 | print(f"command: {cmd}") |
| 54 | |
| 55 | # Run the child process and observe it. |
| 56 | process = subprocess.Popen(cmd, shell=True) |
| 57 | pid = process.pid |
| 58 | print(f"pid: {pid}") |
| 59 | statusfile = f"/proc/{pid}/status" |
| 60 | vmsum = 0 |
| 61 | observed_max = 0 |
| 62 | reported_max = 0 |
| 63 | sample_count = 0 |
| 64 | while process.poll() is None: |
| 65 | with open(statusfile, 'r') as f: |
| 66 | for line in f.read().splitlines(): |
| 67 | if line.startswith("VmRSS"): |
| 68 | rss = int(line.split()[1]) |
| 69 | vmsum += rss |
| 70 | if rss > observed_max: |
| 71 | observed_max = rss |
| 72 | elif line.startswith("VmHWM"): |
| 73 | peak = int(line.split()[1]) |
| 74 | if peak > reported_max: |
| 75 | reported_max = peak |
| 76 | sample_count += 1 |
| 77 | time.sleep(samplerate_secs) |
| 78 | |
| 79 | # Report findings. |
| 80 | print("\n") |
| 81 | # TODO(jkummerow): See if this is accurate enough in practice. |
no test coverage detected
searching dependent graphs…