
Sometimes a Chromium build will be serialized such that only a few commands are running. This can be analyzed after the fact with post_build_ninja_summary.py from depot_tools or with ninjatracing, but it is also nice to be able to find out in the moment what commands are running. Running buildstate will find all running ninja.exe commands and will print their child processes (direct children only). This was used to find that this target: gen/content/browser/devtools/devtools_resources_grit.d.stamp takes almost a minute to build and can serialize the build. Bug: 1162467 Change-Id: I3ac6406b1284dfa58ce243e7d8a89f79a0634af8 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2645638 Reviewed-by: Sébastien Marchand <sebmarchand@chromium.org> Commit-Queue: Bruce Dawson <brucedawson@chromium.org> Cr-Commit-Position: refs/heads/master@{#850909}
103 lines
3.2 KiB
Python
Executable File
103 lines
3.2 KiB
Python
Executable File
#!/usr/bin/env vpython
|
|
# Copyright 2021 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
"""
|
|
This script checks to see what build commands are currently running by printing
|
|
the command lines of any processes that are the children of ninja processes.
|
|
|
|
The idea is that if the build is serialized (not many build steps running) then
|
|
you can run this to see what it is serialized on.
|
|
|
|
This uses python3 on Linux and vpython elsewhere (for psutil).
|
|
"""
|
|
|
|
# [VPYTHON:BEGIN]
|
|
# wheel: <
|
|
# name: "infra/python/wheels/psutil/${vpython_platform}"
|
|
# version: "version:5.6.2"
|
|
# >
|
|
# [VPYTHON:END]
|
|
|
|
from __future__ import print_function
|
|
|
|
import sys
|
|
|
|
|
|
def main():
|
|
parents = []
|
|
processes = []
|
|
|
|
print('Gathering process data...')
|
|
# Ninja's name on Linux is ninja-linux64, presumably different elsewhere, so
|
|
# we look for a matching prefix.
|
|
ninja_prefix = 'ninja.exe' if sys.platform in ['win32', 'cygwin'] else 'ninja'
|
|
|
|
if sys.platform in ['win32', 'cygwin']:
|
|
# psutil handles short-lived ninja descendants poorly on Windows (it misses
|
|
# most of them) so use wmic instead.
|
|
import subprocess
|
|
cmd = 'wmic process get Caption,ParentProcessId,ProcessId,CommandLine'
|
|
lines = subprocess.check_output(cmd, universal_newlines=True).splitlines()
|
|
|
|
# Find the offsets for the various data columns by looking at the labels in
|
|
# the first line of output.
|
|
CAPTION_OFF = 0
|
|
COMMAND_LINE_OFF = lines[0].find('CommandLine')
|
|
PARENT_PID_OFF = lines[0].find('ParentProcessId')
|
|
PID_OFF = lines[0].find(' ProcessId') + 1
|
|
|
|
for line in lines[1:]:
|
|
# Ignore blank lines
|
|
if not line.strip():
|
|
continue
|
|
command = line[:COMMAND_LINE_OFF].strip()
|
|
command_line = line[COMMAND_LINE_OFF:PARENT_PID_OFF].strip()
|
|
parent_pid = int(line[PARENT_PID_OFF:PID_OFF].strip())
|
|
pid = int(line[PID_OFF:].strip())
|
|
processes.append((command, command_line, parent_pid, pid))
|
|
|
|
else:
|
|
# Portable process-collection code, but works badly on Windows.
|
|
import psutil
|
|
for proc in psutil.process_iter(['pid', 'ppid', 'name', 'cmdline']):
|
|
try:
|
|
cmdline = proc.cmdline()
|
|
# Convert from list to a single string.
|
|
cmdline = ' '.join(cmdline)
|
|
except psutil.AccessDenied:
|
|
cmdline = "Access denied"
|
|
processes.append(
|
|
(proc.name()[:], cmdline, int(proc.ppid()), int(proc.pid)))
|
|
|
|
# Scan the list of processes to find ninja.
|
|
for process in processes:
|
|
command, command_line, parent_pid, pid = process
|
|
if command.startswith(ninja_prefix):
|
|
parents.append(pid)
|
|
|
|
if not parents:
|
|
print('No interesting parent processes found.')
|
|
return 1
|
|
|
|
print('Tracking the children of these PIDs:')
|
|
print(', '.join(map(lambda x: str(x), parents)))
|
|
|
|
print()
|
|
|
|
# Print all the processes that have parent-processes of interest.
|
|
count = 0
|
|
for process in processes:
|
|
command, command_line, parent_pid, pid = process
|
|
if parent_pid in parents:
|
|
if not command_line:
|
|
command_line = command
|
|
print('%5d: %s' % (pid, command_line[:160]))
|
|
count += 1
|
|
print('Found %d children' % count)
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|