mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Ordering used: 1.) standard library imports 2.) third party imports 3.) local package imports Each group is individually alphabetized.
82 lines
3.3 KiB
Python
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()
|