Skip to content

Commit bfddc08

Browse files
Enhance iOS build/test reporting with detailed execution timings (#4315)
- Modified `IPhoneBuilder.java` to write `Stopwatch` stats to a file specified by `CN1_BUILD_STATS_FILE` env var. - Updated `scripts/build-ios-app.sh` to capture Maven overhead and `pod install` duration. - Updated `scripts/run-ios-ui-tests.sh` to measure Simulator boot, app install, launch, and test execution times. - Updated `scripts/lib/cn1ss.sh` and `RenderScreenshotReport.java` to parse these stats files and include a "Detailed Performance Metrics" table in the PR comment. Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
1 parent 4e4086a commit bfddc08

File tree

5 files changed

+117
-9
lines changed

5 files changed

+117
-9
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,6 +2194,20 @@ public void stop() {
21942194
summary.append("----------------------\n");
21952195
summary.append(String.format("%-40s : %d ms", "Total Time", totalDuration));
21962196
log(summary.toString());
2197+
String statsFile = System.getenv("CN1_BUILD_STATS_FILE");
2198+
if (statsFile != null && statsFile.length() > 0) {
2199+
try {
2200+
File f = new File(statsFile);
2201+
if (f.getParentFile() != null) {
2202+
f.getParentFile().mkdirs();
2203+
}
2204+
try (FileOutputStream fos = new FileOutputStream(f)) {
2205+
fos.write(summary.toString().getBytes("UTF-8"));
2206+
}
2207+
} catch (Exception ex) {
2208+
log("Failed to write build stats to file " + statsFile + ": " + ex.getMessage());
2209+
}
2210+
}
21972211
}
21982212
}
21992213

scripts/build-ios-app.sh

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ xcodebuild -version
6363
bia_log "Building iOS Xcode project using Codename One port"
6464
cd $APP_DIR
6565
VM_START=$(date +%s)
66+
67+
ARTIFACTS_DIR="${ARTIFACTS_DIR:-$REPO_ROOT/artifacts}"
68+
mkdir -p "$ARTIFACTS_DIR"
69+
70+
export CN1_BUILD_STATS_FILE="$ARTIFACTS_DIR/iphone-builder-stats.txt"
71+
6672
./mvnw package \
6773
-DskipTests \
6874
-Dcodename1.platform=ios \
@@ -73,11 +79,19 @@ VM_END=$(date +%s)
7379
VM_TIME=$((VM_END - VM_START))
7480
cd ../..
7581

76-
ARTIFACTS_DIR="${ARTIFACTS_DIR:-$REPO_ROOT/artifacts}"
77-
mkdir -p "$ARTIFACTS_DIR"
7882
echo "$VM_TIME" > "$ARTIFACTS_DIR/vm_time.txt"
7983
bia_log "VM translation time: ${VM_TIME}s (saved to $ARTIFACTS_DIR/vm_time.txt)"
8084

85+
# Calculate Maven overhead if stats file exists
86+
if [ -f "$ARTIFACTS_DIR/iphone-builder-stats.txt" ]; then
87+
TOTAL_BUILDER_TIME_MS=$(grep "Total Time" "$ARTIFACTS_DIR/iphone-builder-stats.txt" | awk -F ':' '{print $2}' | tr -d ' ms')
88+
if [ -n "$TOTAL_BUILDER_TIME_MS" ]; then
89+
TOTAL_BUILDER_TIME_SEC=$((TOTAL_BUILDER_TIME_MS / 1000))
90+
MAVEN_OVERHEAD=$((VM_TIME - TOTAL_BUILDER_TIME_SEC))
91+
echo "Maven Overhead : ${MAVEN_OVERHEAD}000 ms" >> "$ARTIFACTS_DIR/iphone-builder-stats.txt"
92+
fi
93+
fi
94+
8195
IOS_TARGET_DIR="$APP_DIR/ios/target"
8296
if [ ! -d "$IOS_TARGET_DIR" ]; then
8397
bia_log "iOS target directory not found at $IOS_TARGET_DIR" >&2
@@ -101,13 +115,17 @@ bia_log "Found generated iOS project at $PROJECT_DIR"
101115
# CocoaPods (project contains a Podfile but usually empty — fine)
102116
if [ -f "$PROJECT_DIR/Podfile" ]; then
103117
bia_log "Installing CocoaPods dependencies"
118+
POD_START=$(date +%s)
104119
(
105120
cd "$PROJECT_DIR"
106121
if ! pod install --repo-update; then
107122
bia_log "pod install --repo-update failed; retrying without repo update"
108123
pod install
109124
fi
110125
)
126+
POD_END=$(date +%s)
127+
POD_TIME=$((POD_END - POD_START))
128+
echo "CocoaPods Install (Script) : ${POD_TIME}000 ms" >> "$ARTIFACTS_DIR/iphone-builder-stats.txt"
111129
else
112130
bia_log "Podfile not found in generated project; skipping pod install"
113131
fi

scripts/common/java/RenderScreenshotReport.java

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,40 @@ public static void main(String[] args) throws Exception {
3232

3333
CoverageSummary coverage = loadCoverage(arguments.coverageSummary, arguments.coverageHtmlUrl);
3434

35-
SummaryAndComment output = buildSummaryAndComment(data, title, marker, successMessage, coverage, arguments.vmTime, arguments.compilationTime);
35+
Map<String, String> extraStats = new LinkedHashMap<>();
36+
if (arguments.extraStats != null) {
37+
for (Path p : arguments.extraStats) {
38+
if (Files.isRegularFile(p)) {
39+
parseStatsFile(p, extraStats);
40+
}
41+
}
42+
}
43+
44+
SummaryAndComment output = buildSummaryAndComment(data, title, marker, successMessage, coverage, arguments.vmTime, arguments.compilationTime, extraStats);
3645
writeLines(arguments.summaryOut, output.summaryLines);
3746
writeLines(arguments.commentOut, output.commentLines);
3847
}
3948

49+
private static void parseStatsFile(Path p, Map<String, String> extraStats) {
50+
try {
51+
List<String> lines = Files.readAllLines(p, StandardCharsets.UTF_8);
52+
for (String line : lines) {
53+
line = line.trim();
54+
if (line.isEmpty() || line.startsWith("-")) {
55+
continue;
56+
}
57+
int colon = line.indexOf(':');
58+
if (colon > 0) {
59+
String key = line.substring(0, colon).trim();
60+
String val = line.substring(colon + 1).trim();
61+
extraStats.put(key, val);
62+
}
63+
}
64+
} catch (IOException e) {
65+
System.err.println("Failed to read stats file " + p + ": " + e.getMessage());
66+
}
67+
}
68+
4069
private static void writeLines(Path path, List<String> lines) throws IOException {
4170
StringBuilder sb = new StringBuilder();
4271
for (int i = 0; i < lines.size(); i++) {
@@ -51,7 +80,7 @@ private static void writeLines(Path path, List<String> lines) throws IOException
5180
Files.writeString(path, sb.toString(), StandardCharsets.UTF_8);
5281
}
5382

54-
private static SummaryAndComment buildSummaryAndComment(Map<String, Object> data, String title, String marker, String successMessage, CoverageSummary coverage, Long vmTime, Long compilationTime) {
83+
private static SummaryAndComment buildSummaryAndComment(Map<String, Object> data, String title, String marker, String successMessage, CoverageSummary coverage, Long vmTime, Long compilationTime, Map<String, String> extraStats) {
5584
List<String> summaryLines = new ArrayList<>();
5685
List<String> commentLines = new ArrayList<>();
5786
Object resultsObj = data.get("results");
@@ -161,7 +190,7 @@ private static SummaryAndComment buildSummaryAndComment(Map<String, Object> data
161190
}
162191

163192
// Add benchmark results at the end
164-
appendBenchmarkResults(commentLines, vmTime, compilationTime);
193+
appendBenchmarkResults(commentLines, vmTime, compilationTime, extraStats);
165194

166195
if (commentLines.isEmpty() || (commentLines.size() == 1 && commentLines.get(0).isEmpty())) {
167196
// This fallback block might be redundant now, but kept for safety.
@@ -231,8 +260,8 @@ private static void appendCoverageSummary(List<String> summaryLines, CoverageSum
231260
}
232261
}
233262

234-
private static void appendBenchmarkResults(List<String> commentLines, Long vmTime, Long compilationTime) {
235-
if (vmTime == null && compilationTime == null) {
263+
private static void appendBenchmarkResults(List<String> commentLines, Long vmTime, Long compilationTime, Map<String, String> extraStats) {
264+
if (vmTime == null && compilationTime == null && (extraStats == null || extraStats.isEmpty())) {
236265
return;
237266
}
238267
if (!commentLines.isEmpty() && !commentLines.get(commentLines.size() - 1).isEmpty()) {
@@ -246,6 +275,15 @@ private static void appendBenchmarkResults(List<String> commentLines, Long vmTim
246275
if (compilationTime != null) {
247276
commentLines.add(String.format("- **Compilation Time:** %d seconds", compilationTime));
248277
}
278+
if (extraStats != null && !extraStats.isEmpty()) {
279+
commentLines.add("");
280+
commentLines.add("#### Detailed Performance Metrics");
281+
commentLines.add("| Metric | Duration |");
282+
commentLines.add("| --- | --- |");
283+
for (Map.Entry<String, String> entry : extraStats.entrySet()) {
284+
commentLines.add(String.format("| %s | %s |", entry.getKey(), entry.getValue()));
285+
}
286+
}
249287
commentLines.add("");
250288
}
251289

@@ -450,8 +488,9 @@ private static class Arguments {
450488
final String coverageHtmlUrl;
451489
final Long vmTime;
452490
final Long compilationTime;
491+
final List<Path> extraStats;
453492

454-
private Arguments(Path compareJson, Path commentOut, Path summaryOut, String marker, String title, String successMessage, Path coverageSummary, String coverageHtmlUrl, Long vmTime, Long compilationTime) {
493+
private Arguments(Path compareJson, Path commentOut, Path summaryOut, String marker, String title, String successMessage, Path coverageSummary, String coverageHtmlUrl, Long vmTime, Long compilationTime, List<Path> extraStats) {
455494
this.compareJson = compareJson;
456495
this.commentOut = commentOut;
457496
this.summaryOut = summaryOut;
@@ -462,6 +501,7 @@ private Arguments(Path compareJson, Path commentOut, Path summaryOut, String mar
462501
this.coverageHtmlUrl = coverageHtmlUrl;
463502
this.vmTime = vmTime;
464503
this.compilationTime = compilationTime;
504+
this.extraStats = extraStats;
465505
}
466506

467507
static Arguments parse(String[] args) {
@@ -475,6 +515,7 @@ static Arguments parse(String[] args) {
475515
String coverageHtmlUrl = null;
476516
Long vmTime = null;
477517
Long compilationTime = null;
518+
List<Path> extraStats = new ArrayList<>();
478519
for (int i = 0; i < args.length; i++) {
479520
String arg = args[i];
480521
switch (arg) {
@@ -558,6 +599,13 @@ static Arguments parse(String[] args) {
558599
return null;
559600
}
560601
}
602+
case "--extra-stats" -> {
603+
if (++i >= args.length) {
604+
System.err.println("Missing value for --extra-stats");
605+
return null;
606+
}
607+
extraStats.add(Path.of(args[i]));
608+
}
561609
default -> {
562610
System.err.println("Unknown argument: " + arg);
563611
return null;
@@ -568,7 +616,7 @@ static Arguments parse(String[] args) {
568616
System.err.println("--compare-json, --comment-out, and --summary-out are required");
569617
return null;
570618
}
571-
return new Arguments(compare, comment, summary, marker, title, successMessage, coverageSummary, coverageHtmlUrl, vmTime, compilationTime);
619+
return new Arguments(compare, comment, summary, marker, title, successMessage, coverageSummary, coverageHtmlUrl, vmTime, compilationTime, extraStats);
572620
}
573621
}
574622

scripts/lib/cn1ss.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,15 @@ cn1ss_process_and_report() {
361361
render_args+=(--compilation-time "$CN1SS_COMPILATION_TIME")
362362
fi
363363

364+
# Pass any stats files found in artifacts
365+
if [ -n "$artifacts_dir" ] && [ -d "$artifacts_dir" ]; then
366+
for stats_file in "$artifacts_dir"/iphone-builder-stats.txt "$artifacts_dir"/ios-test-stats.txt; do
367+
if [ -f "$stats_file" ]; then
368+
render_args+=(--extra-stats "$stats_file")
369+
fi
370+
done
371+
fi
372+
364373
if ! cn1ss_java_run "$CN1SS_RENDER_CLASS" "${render_args[@]}"; then
365374
cn1ss_log "FATAL: Failed to render screenshot summary/comment"
366375
return 14

scripts/run-ios-ui-tests.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,11 @@ SIM_DESTINATION="$(normalize_destination "$SIM_DESTINATION")"
335335
SIM_UDID="$(printf '%s\n' "$SIM_DESTINATION" | sed -n 's/.*id=\([^,]*\).*/\1/p' | tr -d '\r[:space:]')"
336336
if [ -n "$SIM_UDID" ]; then
337337
ri_log "Booting simulator $SIM_UDID"
338+
BOOT_START=$(date +%s)
338339
xcrun simctl boot "$SIM_UDID" >/dev/null 2>&1 || true
339340
xcrun simctl bootstatus "$SIM_UDID" -b
341+
BOOT_END=$(date +%s)
342+
echo "Simulator Boot : $(( (BOOT_END - BOOT_START) * 1000 )) ms" >> "$ARTIFACTS_DIR/ios-test-stats.txt"
340343
SIM_DESTINATION="id=$SIM_UDID"
341344
fi
342345
ri_log "Running DeviceRunner on destination '$SIM_DESTINATION'"
@@ -435,8 +438,11 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
435438

436439
if [ -n "$SIM_DEVICE_ID" ]; then
437440
ri_log "Booting simulator $SIM_DEVICE_ID"
441+
BOOT_START=$(date +%s)
438442
xcrun simctl boot "$SIM_DEVICE_ID" >/dev/null 2>&1 || true
439443
xcrun simctl bootstatus "$SIM_DEVICE_ID" -b
444+
BOOT_END=$(date +%s)
445+
echo "Simulator Boot (Run) : $(( (BOOT_END - BOOT_START) * 1000 )) ms" >> "$ARTIFACTS_DIR/ios-test-stats.txt"
440446
else
441447
ri_log "Warning: simulator UDID not resolved; relying on default booted device"
442448
xcrun simctl bootstatus booted -b || true
@@ -470,25 +476,36 @@ APP_PROCESS_NAME="${WRAPPER_NAME%.app}"
470476
sleep 2
471477

472478
ri_log "Installing simulator app bundle"
479+
INSTALL_START=$(date +%s)
473480
if [ -n "$SIM_DEVICE_ID" ]; then
474481
if ! xcrun simctl install "$SIM_DEVICE_ID" "$APP_BUNDLE_PATH"; then
475482
ri_log "FATAL: simctl install failed"
476483
exit 11
477484
fi
485+
INSTALL_END=$(date +%s)
486+
487+
LAUNCH_START=$(date +%s)
478488
if ! xcrun simctl launch "$SIM_DEVICE_ID" "$BUNDLE_IDENTIFIER" >/dev/null 2>&1; then
479489
ri_log "FATAL: simctl launch failed"
480490
exit 11
481491
fi
492+
LAUNCH_END=$(date +%s)
482493
else
483494
if ! xcrun simctl install booted "$APP_BUNDLE_PATH"; then
484495
ri_log "FATAL: simctl install failed"
485496
exit 11
486497
fi
498+
INSTALL_END=$(date +%s)
499+
500+
LAUNCH_START=$(date +%s)
487501
if ! xcrun simctl launch booted "$BUNDLE_IDENTIFIER" >/dev/null 2>&1; then
488502
ri_log "FATAL: simctl launch failed"
489503
exit 11
490504
fi
505+
LAUNCH_END=$(date +%s)
491506
fi
507+
echo "App Install : $(( (INSTALL_END - INSTALL_START) * 1000 )) ms" >> "$ARTIFACTS_DIR/ios-test-stats.txt"
508+
echo "App Launch : $(( (LAUNCH_END - LAUNCH_START) * 1000 )) ms" >> "$ARTIFACTS_DIR/ios-test-stats.txt"
492509

493510
END_MARKER="CN1SS:SUITE:FINISHED"
494511
TIMEOUT_SECONDS=300
@@ -506,6 +523,8 @@ while true; do
506523
fi
507524
sleep 5
508525
done
526+
END_TIME=$(date +%s)
527+
echo "Test Execution : $(( (END_TIME - START_TIME) * 1000 )) ms" >> "$ARTIFACTS_DIR/ios-test-stats.txt"
509528

510529
sleep 3
511530

0 commit comments

Comments
 (0)