Files
swift-mirror/utils/profdata_merge/process.py
practicalswift 265835fdfc [Python] Use consistent import ordering for Python code
Ordering used:
1.) standard library imports
2.) third party imports
3.) local package imports

Each group is individually alphabetized.
2016-03-07 23:25:16 +01:00

82 lines
3.3 KiB
Python

# utils/profdata_merge/process.py
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See http://swift.org/LICENSE.txt for license information
# See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
# This file contains the worker processes that watch a file queue for files and
# merge profile data in parallel.
import logging
import os
import pipes
import subprocess
from multiprocessing import Process
class ProfdataMergerProcess(Process):
def __init__(self, config, file_queue):
super(ProfdataMergerProcess, self).__init__()
self.config = config
self.file_queue = file_queue
self.filename_buffer = []
self.profdata_path = os.path.join(config.tmp_dir,
"%s.profdata" % self.name)
self.profdata_tmp_path = self.profdata_path + ".copy"
def report(self, msg, level=logging.INFO):
"""Convenience method for reporting status from the workers."""
logging.log(level, "[%s]: %s" % (self.name, msg))
def merge_file_buffer(self):
"""Merge all files in this worker's buffer and clear them.
This method makes a copy of the working merge progress, then
calls llvm-cov merge with up to 10 filenames, plus the current
in-progress merge.
"""
if not self.filename_buffer:
self.report("no files to merge...")
return
if os.path.exists(self.profdata_path):
os.rename(self.profdata_path, self.profdata_tmp_path)
self.filename_buffer.append(self.profdata_tmp_path)
cleaned_files = ' '.join(pipes.quote(f) for f in self.filename_buffer)
# FIXME: This doesn't necessarily always line up with the version
# of clang++ used to build the binaries.
llvm_cmd = ("xcrun llvm-profdata merge -o %s %s"
% (self.profdata_path, cleaned_files))
self.report(llvm_cmd)
ret = subprocess.call(llvm_cmd, shell=True)
if ret != 0:
self.report("llvm profdata command failed -- Exited with code %d"
% ret, level=logging.ERROR)
if self.config.remove_files:
for f in self.filename_buffer:
if os.path.exists(f):
os.remove(f)
self.filename_buffer = []
def run(self):
"""Blocks and waits for the file queue so it can fill its buffer and
execute merges. If it finds None in the queue, then it knows to stop
waiting for the queue, merge its current buffer, and kill itself
"""
while True:
filename = self.file_queue.get()
self.report("received filename: %s" % filename)
if filename is None:
self.report("received sentinel; merging...")
self.merge_file_buffer()
self.file_queue.task_done()
break
self.filename_buffer.append(filename)
self.report("Adding %s to filename_buffer." % filename)
if len(self.filename_buffer) >= 10:
self.merge_file_buffer()
self.file_queue.task_done()