diff --git a/dev/benchmarks/imitation_game_swiftui/BenchmarkTests/BenchmarkTests.swift b/dev/benchmarks/imitation_game_swiftui/BenchmarkTests/BenchmarkTests.swift new file mode 100644 index 0000000000000..0488c0419c617 --- /dev/null +++ b/dev/benchmarks/imitation_game_swiftui/BenchmarkTests/BenchmarkTests.swift @@ -0,0 +1,10 @@ +import XCTest + +final class BenchmarkTests: XCTestCase { + @MainActor + func testTimeToFirstFrame() throws { + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } +} diff --git a/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui.xcodeproj/project.pbxproj b/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui.xcodeproj/project.pbxproj index b342b85db6d33..1d1194e4ef98e 100644 --- a/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui.xcodeproj/project.pbxproj +++ b/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 70; objects = { /* Begin PBXBuildFile section */ @@ -13,14 +13,29 @@ F241F50D2D08EE8900C053B5 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F241F50C2D08EE8900C053B5 /* Preview Assets.xcassets */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + F28B09D02DB850E60057E55C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = F241F4FA2D08EE8800C053B5 /* Project object */; + proxyType = 1; + remoteGlobalIDString = F241F5012D08EE8800C053B5; + remoteInfo = hello_world_swiftui; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ F241F5022D08EE8800C053B5 /* hello_world_swiftui.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = hello_world_swiftui.app; sourceTree = BUILT_PRODUCTS_DIR; }; F241F5052D08EE8800C053B5 /* hello_world_swiftuiApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = hello_world_swiftuiApp.swift; sourceTree = ""; }; F241F5072D08EE8800C053B5 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; F241F5092D08EE8900C053B5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; F241F50C2D08EE8900C053B5 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + F28B09CA2DB850E60057E55C /* BenchmarkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BenchmarkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedRootGroup section */ + F28B09CB2DB850E60057E55C /* BenchmarkTests */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = BenchmarkTests; sourceTree = ""; }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ F241F4FF2D08EE8800C053B5 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -29,6 +44,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F28B09C72DB850E60057E55C /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -36,6 +58,7 @@ isa = PBXGroup; children = ( F241F5042D08EE8800C053B5 /* hello_world_swiftui */, + F28B09CB2DB850E60057E55C /* BenchmarkTests */, F241F5032D08EE8800C053B5 /* Products */, ); sourceTree = ""; @@ -44,6 +67,7 @@ isa = PBXGroup; children = ( F241F5022D08EE8800C053B5 /* hello_world_swiftui.app */, + F28B09CA2DB850E60057E55C /* BenchmarkTests.xctest */, ); name = Products; sourceTree = ""; @@ -87,6 +111,29 @@ productReference = F241F5022D08EE8800C053B5 /* hello_world_swiftui.app */; productType = "com.apple.product-type.application"; }; + F28B09C92DB850E60057E55C /* BenchmarkTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F28B09D22DB850E60057E55C /* Build configuration list for PBXNativeTarget "BenchmarkTests" */; + buildPhases = ( + F28B09C62DB850E60057E55C /* Sources */, + F28B09C72DB850E60057E55C /* Frameworks */, + F28B09C82DB850E60057E55C /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + F28B09D12DB850E60057E55C /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + F28B09CB2DB850E60057E55C /* BenchmarkTests */, + ); + name = BenchmarkTests; + packageProductDependencies = ( + ); + productName = BenchmarkTests; + productReference = F28B09CA2DB850E60057E55C /* BenchmarkTests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -94,12 +141,16 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1540; + LastSwiftUpdateCheck = 1630; LastUpgradeCheck = 1540; TargetAttributes = { F241F5012D08EE8800C053B5 = { CreatedOnToolsVersion = 15.4; }; + F28B09C92DB850E60057E55C = { + CreatedOnToolsVersion = 16.3; + TestTargetID = F241F5012D08EE8800C053B5; + }; }; }; buildConfigurationList = F241F4FD2D08EE8800C053B5 /* Build configuration list for PBXProject "hello_world_swiftui" */; @@ -116,6 +167,7 @@ projectRoot = ""; targets = ( F241F5012D08EE8800C053B5 /* hello_world_swiftui */, + F28B09C92DB850E60057E55C /* BenchmarkTests */, ); }; /* End PBXProject section */ @@ -130,6 +182,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F28B09C82DB850E60057E55C /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -142,8 +201,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F28B09C62DB850E60057E55C /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + F28B09D12DB850E60057E55C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = F241F5012D08EE8800C053B5 /* hello_world_swiftui */; + targetProxy = F28B09D02DB850E60057E55C /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ F241F5242D08EE8900C053B5 /* Debug */ = { isa = XCBuildConfiguration; @@ -180,7 +254,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; - DEVELOPMENT_TEAM = S8QB4VV633; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -244,7 +317,6 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEVELOPMENT_TEAM = S8QB4VV633; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_USER_SCRIPT_SANDBOXING = YES; @@ -271,7 +343,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"hello_world_swiftui/Preview Content\""; @@ -291,7 +362,6 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "dev.flutter.plugins.hello-world-swiftui"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -303,7 +373,6 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"hello_world_swiftui/Preview Content\""; @@ -323,13 +392,48 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = "dev.flutter.plugins.hello-world-swiftui"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; + F28B09D32DB850E60057E55C /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S8QB4VV633; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.BenchmarkTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = hello_world_swiftui; + }; + name = Debug; + }; + F28B09D42DB850E60057E55C /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = S8QB4VV633; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 16.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.BenchmarkTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = hello_world_swiftui; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -351,6 +455,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F28B09D22DB850E60057E55C /* Build configuration list for PBXNativeTarget "BenchmarkTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F28B09D32DB850E60057E55C /* Debug */, + F28B09D42DB850E60057E55C /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = F241F4FA2D08EE8800C053B5 /* Project object */; diff --git a/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui.xcodeproj/xcshareddata/xcschemes/hello_world_swiftui.xcscheme b/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui.xcodeproj/xcshareddata/xcschemes/hello_world_swiftui.xcscheme new file mode 100644 index 0000000000000..dac2f8eb9b32f --- /dev/null +++ b/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui.xcodeproj/xcshareddata/xcschemes/hello_world_swiftui.xcscheme @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui/ContentView.swift b/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui/ContentView.swift index cfb7b623df2f0..0f3cc21a46e72 100644 --- a/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui/ContentView.swift +++ b/dev/benchmarks/imitation_game_swiftui/hello_world_swiftui/ContentView.swift @@ -10,7 +10,7 @@ struct ContentView: View { private let fetchThreshold = 5 var body: some View { - NavigationView { // Add a NavigationView for better view management + NavigationView { List { ForEach(items.indices, id: \.self) { index in Text(items[index]) @@ -23,10 +23,10 @@ struct ContentView: View { if isLoadingMore { ProgressView() - .frame(maxWidth: .infinity) // Center the indicator + .frame(maxWidth: .infinity) } } - .navigationTitle("Infinite Scroll") // Set a title for clarity + .navigationTitle("Infinite Scroll") } } diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart index 4d8d4e37747bf..872c53cbf75d4 100644 --- a/dev/devicelab/lib/tasks/perf_tests.dart +++ b/dev/devicelab/lib/tasks/perf_tests.dart @@ -8,6 +8,7 @@ import 'dart:ffi' show Abi; import 'dart:io'; import 'dart:math' as math; +import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; import 'package:path/path.dart' as path; import 'package:xml/xml.dart'; @@ -1753,6 +1754,87 @@ class CompileTest { }); } + Future> getMetricsFromXCResults() async { + return inDirectory>(testDirectory, () async { + List resultsJson = []; + const String resultsBundleName = 'benchmarkResults.xcresult'; + // Get ID from Info.plist + final ProcessResult plistIDResult = await Process.run(workingDirectory: testDirectory, 'plutil', [ + '-extract', + 'rootId.hash', + 'raw', + '-o', + '-', + '$resultsBundleName/Info.plist' + ]); + + final String plistID = plistIDResult.stdout.toString().trim(); + + // Next, get the ActionsInvocationRecord and Extract the testsRef ID + String testRefID = ''; + await Process.run(workingDirectory: testDirectory, 'xcrun', [ + 'xcresulttool', + 'get', + '--path', + resultsBundleName, + '--id', + plistID, + '--format', + 'json', + '--legacy' + ]).then((ProcessResult result) { + final dynamic actionsInvocationRecordJSON = json.decode(result.stdout.toString()); + + // ignore: avoid_dynamic_calls + testRefID = actionsInvocationRecordJSON['actions']['_values'][0]['actionResult']['testsRef']['id']['_value'].toString(); + }); + + // Next, grab the ActionTestSummary using our testRefID + String actionTestSummaryID = ''; + await Process.run(workingDirectory: testDirectory, 'xcrun', [ + 'xcresulttool', + 'get', + '--path', + resultsBundleName, + '--id', + testRefID, + '--format', + 'json', + '--legacy' + ]).then((ProcessResult result) { + final dynamic actionTestSummaryJSON = json.decode(result.stdout.toString()); + + // ignore: avoid_dynamic_calls + actionTestSummaryID = actionTestSummaryJSON['summaries']['_values'][0]['testableSummaries']['_values'][0]['tests']['_values'][0]['subtests']['_values'][0]['subtests']['_values'][0]['subtests']['_values'][0]['summaryRef']['id']['_value'] + .toString(); + }); + + dynamic resultMetricsJSON = ''; + + // Finally, grab the metrics. + await Process.run(workingDirectory: testDirectory, 'xcrun', [ + 'xcresulttool', + 'get', + '--path', + resultsBundleName, + '--id', + actionTestSummaryID, + '--format', + 'json', + '--legacy' + ]).then((ProcessResult result) { + resultMetricsJSON = json.decode(result.stdout.toString()); + + // ignore: avoid_dynamic_calls + resultsJson = resultMetricsJSON['performanceMetrics']['_values'][0]['measurements']['_values'] as List; + }); + final List extractedLaunchTimes = []; + resultsJson.map((dynamic item) => extractedLaunchTimes.add(double.parse((item as Map)['_value'] as String))).toList(); + + return extractedLaunchTimes; + }); + } + Future runSwiftUIApp() async { return inDirectory(testDirectory, () async { final Map environment = Platform.environment; @@ -1763,6 +1845,7 @@ class CompileTest { await Process.run('xcodebuild', ['clean', '-allTargets']); + /* Compile Time */ int releaseSizeInBytes = 0; final Stopwatch watch = Stopwatch(); @@ -1791,6 +1874,7 @@ class CompileTest { } }); + /* App Size */ final String appPath = '$testDirectory/hello_world_swiftui.xcarchive/Products/Applications/hello_world_swiftui.app'; @@ -1798,10 +1882,39 @@ class CompileTest { await exec('tar', ['-zcf', 'app.tar.gz', appPath]); releaseSizeInBytes = await file('$testDirectory/app.tar.gz').length(); + /* Time to First Frame */ + await Process.run(workingDirectory: testDirectory, 'rm', [ + '-rf', + '$testDirectory/benchmarkResults.xcresult' + ]).then((ProcessResult results) { + print(results.stdout); + }); + + // Run the benchmarking tests and output the result + await Process.run(workingDirectory: testDirectory, 'xcodebuild', [ + 'test', + '-project', + 'hello_world_swiftui.xcodeproj', + '-scheme', + 'hello_world_swiftui', + '-destination', + 'platform=iOS', + '-only-testing:BenchmarkTests/BenchmarkTests/testTimeToFirstFrame', + '-resultBundlePath', + '$testDirectory/benchmarkResults.xcresult', + '-verbose', + 'DEVELOPMENT_TEAM=$developmentTeam', + 'CODE_SIGN_STYLE=$codeSignStyle', + 'PROVISIONING_PROFILE_SPECIFIER=$provisioningProfile', + ]); + + final List extractedLaunchTimes = await getMetricsFromXCResults(); + final Map metrics = {}; metrics.addAll({ 'release_swiftui_compile_millis': watch.elapsedMilliseconds, 'release_swiftui_size_bytes': releaseSizeInBytes, + 'time_to_first_frame': extractedLaunchTimes.average }); return TaskResult.success(metrics); }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy