Skip to content

Commit bfb89ee

Browse files
Instrument IPhoneBuilder to break down build time statistics (#4313)
Added a Stopwatch helper class to IPhoneBuilder.java and instrumented the build() method to log the duration of individual build steps (Setup, Extensions, Hints, Stubs, ParparVM, CocoaPods, etc.) separately. This allows for identifying performance bottlenecks in the iOS build process, specifically isolating the time spent on CocoaPods installation versus VM translation. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent aebaf39 commit bfb89ee

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/IPhoneBuilder.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ private int getDeploymentTargetInt(BuildRequest request) {
213213

214214
@Override
215215
public boolean build(File sourceZip, BuildRequest request) throws BuildException {
216+
Stopwatch stopwatch = new Stopwatch();
216217
addMinDeploymentTarget(DEFAULT_MIN_DEPLOYMENT_VERSION);
217218
detectJailbreak = request.getArg("ios.detectJailbreak", "false").equals("true");
218219
defaultEnvironment.put("LANG", "en_US.UTF-8");
@@ -346,7 +347,7 @@ public boolean build(File sourceZip, BuildRequest request) throws BuildException
346347
} catch (IOException ex) {
347348
throw new BuildException("Failed to unzip source Zip file.", ex);
348349
}
349-
350+
stopwatch.split("Setup & Unzip");
350351

351352

352353
// We allow devs to add local podspecs inside a folder called "podspecs". This will
@@ -479,6 +480,7 @@ public boolean build(File sourceZip, BuildRequest request) throws BuildException
479480

480481
}
481482
}
483+
stopwatch.split("Extract Extensions");
482484

483485
File podSpecs = new File(tmpFile, "podspecs");
484486
podSpecs.mkdirs();
@@ -563,6 +565,7 @@ public boolean build(File sourceZip, BuildRequest request) throws BuildException
563565

564566

565567
}
568+
stopwatch.split("Google Services Setup");
566569

567570
if (googleClientId == null && useGoogleSignIn) {
568571
log("GoogleService-Info.plist file specifies that GoogleSignIn should be used but it doesn't provide a client ID. Likely the GoogleService-Info.plist file is not valid. See "+GOOGLE_SIGNIN_TUTORIAL_URL+" for instructions on setting up GoogleSignIn");
@@ -603,7 +606,7 @@ public void usesClassMethod(String cls, String method) {
603606
} catch (Exception ex) {
604607
throw new BuildException("Failed to scan project classes for permissions.", ex);
605608
}
606-
609+
stopwatch.split("Scan Classes");
607610

608611
debug("Local Notifications "+(usesLocalNotifications?"enabled":"disabled"));
609612
try {
@@ -646,6 +649,7 @@ public void usesClassMethod(String cls, String method) {
646649
} catch (IOException ex) {
647650
throw new BuildException("Failed to extract nativeios.jar",ex);
648651
}
652+
stopwatch.split("Extract Libs");
649653

650654
if(request.getArg("noExtraResources", "false").equals("true")) {
651655
new File(buildinRes, "CN1Resource.res").delete();
@@ -910,6 +914,7 @@ public void usesClassMethod(String cls, String method) {
910914
adPadding = " Display.getInstance().setProperty(\"adPaddingBottom\", \"" + adPadding + "\");\n";
911915
}
912916
}
917+
stopwatch.split("Inject Build Hints");
913918

914919
File stubSource = new File(tmpFile, "stub");
915920
stubSource.mkdirs();
@@ -918,6 +923,7 @@ public void usesClassMethod(String cls, String method) {
918923
} catch (Exception ex) {
919924
throw new BuildException("Failed to generate Unit Test Files", ex);
920925
}
926+
stopwatch.split("Generate Unit Tests");
921927

922928
String newStorage = "";
923929
if(request.getArg("ios.newStorageLocation", "true").equals("true")) {
@@ -1005,6 +1011,7 @@ public void usesClassMethod(String cls, String method) {
10051011
} catch (IOException ex) {
10061012
throw new BuildException("Failed to write stub source", ex);
10071013
}
1014+
stopwatch.split("Generate Stubs");
10081015

10091016
Class[] nativeInterfaces = getNativeInterfaces();
10101017
if(nativeInterfaces != null && nativeInterfaces.length > 0) {
@@ -1173,6 +1180,7 @@ public void usesClassMethod(String cls, String method) {
11731180
} catch (Exception ex) {
11741181
throw new BuildException("Failure occurred while compiling native interface stubs", ex);
11751182
}
1183+
stopwatch.split("Compile Stubs");
11761184

11771185

11781186
try {
@@ -1190,6 +1198,7 @@ public void usesClassMethod(String cls, String method) {
11901198
} catch (Exception ex) {
11911199
throw new BuildException("Failed to generate launch screen");
11921200
}
1201+
stopwatch.split("Generate Icons");
11931202

11941203
resultDir = new File(tmpFile, "result");
11951204
resultDir.mkdirs();
@@ -1526,6 +1535,7 @@ public void usesClassMethod(String cls, String method) {
15261535
debug("iosDeploymentTargetMajorVersionInt="+getDeploymentTargetInt(request));
15271536

15281537
debug("Building using addLibs="+addLibs);
1538+
stopwatch.split("Prepare ParparVM");
15291539
try {
15301540
if (!exec(userDir, env, 420000, "java", "-DsaveUnitTests=" + isUnitTestMode(), "-DfieldNullChecks=" + fieldNullChecks, "-DINCLUDE_NPE_CHECKS=" + includeNullChecks, "-DbundleVersionNumber=" + bundleVersionNumber, "-Xmx384m",
15311541
"-jar", parparVMCompilerJar, "ios",
@@ -1543,6 +1553,7 @@ public void usesClassMethod(String cls, String method) {
15431553
} catch (Exception ex) {
15441554
throw new BuildException("Failure while trying to run ByteCodeTranslator of ParparVM", ex);
15451555
}
1556+
stopwatch.split("ParparVM Execution");
15461557
try {
15471558
String orientations = request.getArg("ios.interface_orientation", null);
15481559
if (orientations != null && orientations.split(":").length < 4) {
@@ -1617,6 +1628,7 @@ public void usesClassMethod(String cls, String method) {
16171628
} catch (Exception ex) {
16181629
throw new BuildException("Failed to update infoplist file", ex);
16191630
}
1631+
stopwatch.split("Post-VM Setup");
16201632
if (runPods) {
16211633
try {
16221634
List<File> podSpecFileList = new ArrayList<File>();
@@ -1932,6 +1944,7 @@ public void usesClassMethod(String cls, String method) {
19321944
} catch (Exception ex) {
19331945
throw new BuildException("Failed to generate PodFile", ex);
19341946
}
1947+
stopwatch.split("CocoaPods");
19351948
}
19361949

19371950
try {
@@ -1979,6 +1992,9 @@ public void usesClassMethod(String cls, String method) {
19791992

19801993
}
19811994

1995+
stopwatch.split("Finalize");
1996+
stopwatch.stop();
1997+
19821998
if ("xcode".equals(getBuildTarget()) || getBuildTarget() == null) {
19831999
xcodeProjectDir = new File(tmpFile, "dist");
19842000
return true;
@@ -2151,6 +2167,36 @@ private class GoogleServicePlist {
21512167

21522168
}
21532169

2170+
private class Stopwatch {
2171+
private long startTime;
2172+
private long lastSplitTime;
2173+
private final StringBuilder summary = new StringBuilder();
2174+
2175+
public Stopwatch() {
2176+
startTime = System.currentTimeMillis();
2177+
lastSplitTime = startTime;
2178+
summary.append("Build Time Statistics:\n");
2179+
summary.append("----------------------\n");
2180+
}
2181+
2182+
public void split(String stepName) {
2183+
long now = System.currentTimeMillis();
2184+
long duration = now - lastSplitTime;
2185+
String message = String.format("%-40s : %d ms", stepName, duration);
2186+
log(message);
2187+
summary.append(message).append("\n");
2188+
lastSplitTime = now;
2189+
}
2190+
2191+
public void stop() {
2192+
long now = System.currentTimeMillis();
2193+
long totalDuration = now - startTime;
2194+
summary.append("----------------------\n");
2195+
summary.append(String.format("%-40s : %d ms", "Total Time", totalDuration));
2196+
log(summary.toString());
2197+
}
2198+
}
2199+
21542200
private File[] extractAppExtensions(File sourceDirectory, File targetDirectory) throws IOException {
21552201
if (sourceDirectory == null || !sourceDirectory.isDirectory()) {
21562202
throw new IllegalArgumentException("extractAppExtensions sourceDirectory must be an existing directory but received "+sourceDirectory);

0 commit comments

Comments
 (0)