mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-28 00:06:09 +03:00
155 lines
4.8 KiB
Python
155 lines
4.8 KiB
Python
|
#!/usr/bin/env python
|
||
|
# Copyright 2020 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.
|
||
|
"""Downloads pgo profiles for optimizing official Chrome.
|
||
|
|
||
|
This script has the following responsibilities:
|
||
|
1. Download a requested profile if necessary.
|
||
|
2. Return a path to the current profile to feed to the build system.
|
||
|
3. Removed stale profiles (2 days) to save disk spaces because profiles are
|
||
|
large (~1GB) and updated frequently (~4 times a day).
|
||
|
"""
|
||
|
|
||
|
from __future__ import print_function
|
||
|
|
||
|
import argparse
|
||
|
import os
|
||
|
import sys
|
||
|
import time
|
||
|
|
||
|
_SRC_ROOT = os.path.abspath(
|
||
|
os.path.join(os.path.dirname(__file__), os.path.pardir))
|
||
|
sys.path.append(os.path.join(_SRC_ROOT, 'third_party', 'depot_tools'))
|
||
|
import download_from_google_storage
|
||
|
|
||
|
sys.path.append(os.path.join(_SRC_ROOT, 'build'))
|
||
|
import gn_helpers
|
||
|
|
||
|
# Absolute path to the directory that stores pgo related state files, which
|
||
|
# specifcies which profile to update and use.
|
||
|
_PGO_DIR = os.path.join(_SRC_ROOT, 'chrome', 'build')
|
||
|
|
||
|
# Absolute path to the directory that stores pgo profiles.
|
||
|
_PGO_PROFILE_DIR = os.path.join(_PGO_DIR, 'pgo_profiles')
|
||
|
|
||
|
|
||
|
def _read_profile_name(target):
|
||
|
"""Read profile name given a target.
|
||
|
|
||
|
Args:
|
||
|
target(str): The target name, such as win32, mac.
|
||
|
|
||
|
Returns:
|
||
|
Name of the profile to update and use, such as:
|
||
|
chrome-win32-master-67ad3c89d2017131cc9ce664a1580315517550d1.profdata.
|
||
|
"""
|
||
|
state_file = os.path.join(_PGO_DIR, '%s.pgo.txt' % target)
|
||
|
with open(state_file, 'r') as f:
|
||
|
profile_name = f.read().strip()
|
||
|
|
||
|
return profile_name
|
||
|
|
||
|
|
||
|
def _remove_unused_profiles(current_profile_name):
|
||
|
"""Removes unused profiles, except the current one, to save disk space."""
|
||
|
days = 2
|
||
|
expiration_duration = 60 * 60 * 24 * days
|
||
|
for f in os.listdir(_PGO_PROFILE_DIR):
|
||
|
if f == current_profile_name:
|
||
|
continue
|
||
|
|
||
|
p = os.path.join(_PGO_PROFILE_DIR, f)
|
||
|
age = time.time() - os.path.getmtime(p)
|
||
|
if age > expiration_duration:
|
||
|
print('Removing profile %s as it hasn\'t been used in the past %d days' %
|
||
|
(p, days))
|
||
|
os.remove(p)
|
||
|
|
||
|
|
||
|
def _update(args):
|
||
|
"""Update profile if necessary according to the state file.
|
||
|
|
||
|
Args:
|
||
|
args(dict): A dict of cmd arguments, such as target and gs_url_base.
|
||
|
|
||
|
Raises:
|
||
|
RuntimeError: If failed to download profiles from gcs.
|
||
|
"""
|
||
|
profile_name = _read_profile_name(args.target)
|
||
|
profile_path = os.path.join(_PGO_PROFILE_DIR, profile_name)
|
||
|
if os.path.isfile(profile_path):
|
||
|
os.utime(profile_path, None)
|
||
|
return
|
||
|
|
||
|
gsutil = download_from_google_storage.Gsutil(
|
||
|
download_from_google_storage.GSUTIL_DEFAULT_PATH)
|
||
|
gs_path = 'gs://' + args.gs_url_base.strip('/') + '/' + profile_name
|
||
|
code = gsutil.call('cp', gs_path, profile_path)
|
||
|
if code != 0:
|
||
|
raise RuntimeError('gsutil failed to download "%s"' % gs_path)
|
||
|
|
||
|
_remove_unused_profiles(profile_name)
|
||
|
|
||
|
|
||
|
def _get_profile_path(args):
|
||
|
"""Returns an absolute path to the current profile.
|
||
|
|
||
|
Args:
|
||
|
args(dict): A dict of cmd arguments, such as target and gs_url_base.
|
||
|
|
||
|
Raises:
|
||
|
RuntimeError: If the current profile is missing.
|
||
|
"""
|
||
|
profile_path = os.path.join(_PGO_PROFILE_DIR, _read_profile_name(args.target))
|
||
|
if not os.path.isfile(profile_path):
|
||
|
raise RuntimeError(
|
||
|
'requested profile "%s" doesn\'t exist, please make sure '
|
||
|
'"checkout_pgo_profiles" is set to True in the "custom_vars" section '
|
||
|
'of your .gclient file, e.g.: \n'
|
||
|
'solutions = [ \n'
|
||
|
' { \n'
|
||
|
' "name": "src", \n'
|
||
|
' # ... \n'
|
||
|
' "custom_vars": { \n'
|
||
|
' "checkout_pgo_profiles": True, \n'
|
||
|
' }, \n'
|
||
|
' }, \n'
|
||
|
'], \n'
|
||
|
'and then run "gclient runhooks" to download it. You can also simply '
|
||
|
'disable the PGO optimizations by setting |chrome_pgo_phase = 0| in '
|
||
|
'your GN arguments.'%
|
||
|
profile_path)
|
||
|
|
||
|
os.utime(profile_path, None)
|
||
|
profile_path.rstrip(os.sep)
|
||
|
print(gn_helpers.ToGNString(profile_path))
|
||
|
|
||
|
|
||
|
def main():
|
||
|
parser = argparse.ArgumentParser(
|
||
|
description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||
|
parser.add_argument(
|
||
|
'--target',
|
||
|
required=True,
|
||
|
choices=['win32', 'win64', 'mac', 'mac-arm', 'linux'],
|
||
|
help='Identifier of a specific target platform + architecture.')
|
||
|
subparsers = parser.add_subparsers()
|
||
|
|
||
|
parser_update = subparsers.add_parser('update')
|
||
|
parser_update.add_argument(
|
||
|
'--gs-url-base',
|
||
|
required=True,
|
||
|
help='The base GS URL to search for the profile.')
|
||
|
parser_update.set_defaults(func=_update)
|
||
|
|
||
|
parser_get_profile_path = subparsers.add_parser('get_profile_path')
|
||
|
parser_get_profile_path.set_defaults(func=_get_profile_path)
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
return args.func(args)
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
sys.exit(main())
|