Add timing to archive.py
Change-Id: I7fd70c922da538c5db3eb0ea489483a4d1f495b1
diff --git a/tools/archive.py b/tools/archive.py
index 6746ff9..ee6f5ec 100755
--- a/tools/archive.py
+++ b/tools/archive.py
@@ -9,6 +9,7 @@
import create_maven_release
import gradle
+from timing import Timing
try:
import resource
@@ -112,16 +113,44 @@
def SetRLimitToMax():
+ if not utils.is_bot() or utils.IsWindows():
+ return
(soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
resource.setrlimit(resource.RLIMIT_NOFILE, (hard, hard))
def PrintResourceInfo():
+ if utils.IsWindows():
+ return
(soft, hard) = resource.getrlimit(resource.RLIMIT_NOFILE)
print('INFO: Open files soft limit: %s' % soft)
print('INFO: Open files hard limit: %s' % hard)
+# Ensure all archived artifacts has been built before archiving.
+# The target tasks postfixed by 'lib' depend on the actual target task so
+# building it invokes the original task first.
+# The '-Pno_internal' flag is important because we generate the lib based on uses in tests.
+def RunGradleBuild(options, timing):
+ if options.skip_gradle_build:
+ return
+ timing.begin("Run gradle build")
+ gradle.RunGradle([
+ utils.GRADLE_TASK_CONSOLIDATED_LICENSE,
+ utils.GRADLE_TASK_KEEP_ANNO_JAR,
+ utils.GRADLE_TASK_KEEP_ANNO_DOC,
+ utils.GRADLE_TASK_KEEP_ANNO_LEGACY_JAR,
+ utils.GRADLE_TASK_KEEP_ANNO_ANDROIDX_JAR,
+ utils.GRADLE_TASK_R8,
+ utils.GRADLE_TASK_R8LIB, utils.GRADLE_TASK_R8LIB_NO_DEPS,
+ utils.GRADLE_TASK_THREADING_MODULE_BLOCKING,
+ utils.GRADLE_TASK_THREADING_MODULE_SINGLE_THREADED,
+ utils.GRADLE_TASK_SOURCE_JAR,
+ utils.GRADLE_TASK_SWISS_ARMY_KNIFE, '-Pno_internal'
+ ])
+ timing.end()
+
+
def RSyncDir(src_dir, version_or_path, dst_dir, is_main, options):
destination = GetUploadDestination(version_or_path, dst_dir, is_main)
print(f'RSyncing {src_dir} to {destination}')
@@ -165,41 +194,24 @@
not os.path.isdir(options.dry_run_output))):
raise Exception(options.dry_run_output +
' does not exist or is not a directory')
- if (options.skip_gradle_build and not options.dry_run):
+ if options.skip_gradle_build and not options.dry_run:
raise Exception(
'Using --skip-gradle-build only supported with --dry-run')
- if utils.is_bot() and not utils.IsWindows():
- SetRLimitToMax()
- if not utils.IsWindows():
- PrintResourceInfo()
+ timing = Timing()
+ SetRLimitToMax()
+ PrintResourceInfo()
+ RunGradleBuild(options, timing)
+
+ version = GetVersion()
+ is_main = IsMain(version)
+ if is_main:
+ # On main we use the git hash to archive with
+ print('On main, using git hash for archiving')
+ version = GetGitHash()
with utils.TempDir() as temp:
- # Ensure all archived artifacts has been built before archiving.
- # The target tasks postfixed by 'lib' depend on the actual target task so
- # building it invokes the original task first.
- # The '-Pno_internal' flag is important because we generate the lib based on uses in tests.
- if (not options.skip_gradle_build):
- gradle.RunGradle([
- utils.GRADLE_TASK_CONSOLIDATED_LICENSE,
- utils.GRADLE_TASK_KEEP_ANNO_JAR,
- utils.GRADLE_TASK_KEEP_ANNO_DOC,
- utils.GRADLE_TASK_KEEP_ANNO_LEGACY_JAR,
- utils.GRADLE_TASK_KEEP_ANNO_ANDROIDX_JAR,
- utils.GRADLE_TASK_R8,
- utils.GRADLE_TASK_R8LIB, utils.GRADLE_TASK_R8LIB_NO_DEPS,
- utils.GRADLE_TASK_THREADING_MODULE_BLOCKING,
- utils.GRADLE_TASK_THREADING_MODULE_SINGLE_THREADED,
- utils.GRADLE_TASK_SOURCE_JAR,
- utils.GRADLE_TASK_SWISS_ARMY_KNIFE, '-Pno_internal'
- ])
- version = GetVersion()
- is_main = IsMain(version)
- if is_main:
- # On main we use the git hash to archive with
- print('On main, using git hash for archiving')
- version = GetGitHash()
-
+ timing.begin("Generate r8 maven zip")
version_file = os.path.join(temp, 'r8-version.properties')
with open(version_file, 'w') as version_writer:
version_writer.write('version.sha=' + GetGitHash() + '\n')
@@ -218,9 +230,11 @@
utils.MAVEN_ZIP_LIB,
version_file=version_file,
skip_gradle_build=options.skip_gradle_build)
+ timing.end()
- # Create maven release of the desuage_jdk_libs configuration. This require
+ # Create maven release of the desugar_jdk_libs configuration. This requires
# an r8.jar with dependencies to have been built.
+ timing.begin("Generate desugar configuration maven zip")
create_maven_release.generate_desugar_configuration_maven_zip(
utils.DESUGAR_CONFIGURATION_MAVEN_ZIP, utils.DESUGAR_CONFIGURATION,
utils.DESUGAR_IMPLEMENTATION,
@@ -246,6 +260,7 @@
utils.DESUGAR_CONFIGURATION_JDK11_NIO,
utils.DESUGAR_IMPLEMENTATION_JDK11,
utils.LIBRARY_DESUGAR_CONVERSIONS_ZIP)
+ timing.end()
destination = GetVersionDestination('gs://', version, is_main)
@@ -254,6 +269,7 @@
destination)
# Create pom file for our maven repository that we build for testing.
+ timing.begin("Create pom file")
default_pom_file = os.path.join(temp, 'r8.pom')
create_maven_release.write_default_r8_pom_file(default_pom_file,
version)
@@ -262,21 +278,27 @@
'-PspdxVersion=' + version,
'-PspdxRevision=' + GetGitHash()
])
+ time.end()
# Upload keep-anno javadoc to a fixed "docs" location.
+ timing.begin("Uploade keep-anno Javadoc")
if is_main:
version_or_path = 'docs'
dst_dir = 'keepanno/javadoc'
RSyncDir(utils.KEEPANNO_ANNOTATIONS_DOC, version_or_path, dst_dir, is_main, options)
+ timing.end()
# Upload directories.
+ timing.begin("Upload directories")
dirs_for_archiving = [
(utils.KEEPANNO_ANNOTATIONS_DOC, 'keepanno/javadoc'),
]
for (src_dir, dst_dir) in dirs_for_archiving:
UploadDir(src_dir, version, dst_dir, is_main, options)
+ timing.end()
# Upload files.
+ timing.begin("Upload files")
for_archiving = [
utils.R8_JAR, utils.R8LIB_JAR, utils.R8LIB_JAR + '.map',
utils.R8LIB_JAR + '_map.zip', utils.R8_FULL_EXCLUDE_DEPS_JAR,
@@ -422,6 +444,9 @@
utils.upload_file_to_cloud_storage(
desugar_jdk_libs_configuration_jar, jar_destination)
+ timing.end()
+ timing.report()
+
if __name__ == '__main__':
sys.exit(Main())
diff --git a/tools/timing.py b/tools/timing.py
new file mode 100644
index 0000000..2c3a2c3
--- /dev/null
+++ b/tools/timing.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python3
+# Copyright (c) 2025, the R8 project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+from argparse import Namespace
+import time
+
+class Timing:
+
+ def __init__(self):
+ self.active_timing = None
+ self.committed = []
+ self.created_ns = time.time_ns()
+
+ def begin(self, title):
+ assert self.active_timing is None
+ self.active_timing = Namespace(title=title, start_ns=time.time_ns())
+
+ def end(self):
+ assert self.active_timing is not None
+ self.committed.append(Namespace(
+ title=self.active_timing.title,
+ duration_ns= time.time_ns() - self.active_timing.start_ns))
+ self.active_timing = None
+
+ def report(self):
+ assert self.active_timing is None
+ total_duration_ns = self.time_ns() - self.created_ns
+ timed_duration_ns = 0
+ for timing in self.committed:
+ print(f'{timing.title}: {timing.duration_ns // 1_000_000}ms')
+ timed_duration_ns = timed_duration_ns + timing.duration_ns
+ unaccounted_ns = total_duration_ns - timed_duration_ns
+ print(f'Unaccounted: {unaccounted_ns // 1_000_000}ms')