Skip to content

Commit 4186cc8

Browse files
authored
feat: optimize brownfield-gradle-plugin (#237)
* feat: first approach - fails at not calling bundleRelaseAar for TPL * feat: second approach by exposing custom tasks - WIP * feat: migrate manifest-merger and move others to explode-aar task * feat: migrate processResources and processAssets * feat: migrate jni libs processor * feat: migrate proguard processor * feat: migrate data binding and cleanup * refactor: cleanup * refactor: cleanup * fix: library namespace resolution * perf: optimize explodeAarTask * feat: improvements * fix: add task dependency for JSBundle * refactor: cleanup * refactor: remove duplicates * refactor: early return * fix: add explode as task dependency on preBuild * feat: remove resolve during config phase OR needing another task * fix: right place for evaluation dependency * fix: expo published projects are now added in exploded aar * fix: reduce duplication and fixed namespace resolution * refactor: cleanup * refactor: cleanup * refactor: cleanup * perf: add gradle-profiler benchmarks and docs * chore: bump BGP to alpha * chore: changeset * refactor: remove unused plugin * refactor: throw error * refactor: code review * refactor: guard artifact file * refactor: code review * refactor: code review * fix: errors after merge conflict * fix: resolve after merge conflicts * fix: update after merge resolve
1 parent a07db9e commit 4186cc8

42 files changed

Lines changed: 1083 additions & 1153 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.changeset/red-plants-roll.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@callstack/react-native-brownfield': minor
3+
---
4+
5+
Bump brownfield-gradle-plugin

apps/RNApp/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,7 @@ yarn-error.log
7777
# Brownfield
7878
android/BrownfieldLib/libsDebug/
7979
android/BrownfieldLib/libsRelease/
80+
81+
# Benchmarks
82+
android/gradle-user-home/
83+
android/profile-out/

apps/RNApp/android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ buildscript {
1616
classpath("com.android.tools.build:gradle")
1717
classpath("com.facebook.react:react-native-gradle-plugin")
1818
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin")
19-
classpath("com.callstack.react:brownfield-gradle-plugin:1.1.0-SNAPSHOT")
19+
classpath("com.callstack.react:brownfield-gradle-plugin:2.0.0-alpha01-SNAPSHOT")
2020
}
2121
}
2222

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
### Gradle Profiler
2+
3+
Repo: https://github.com/gradle/gradle-profiler
4+
Android docs: https://developer.android.com/build/profile-your-build
5+
6+
### Pre-Requisites
7+
- Ensure gradle-profiler is installed, [instructions](https://github.com/gradle/gradle-profiler#installing)
8+
- Change your working directory to `RNApp/android/gradle-profiler`
9+
10+
### Steps:
11+
- Checkout to main or baseline branch
12+
- Adjust the scenarios to suit your use-case OR create a new scenarios file
13+
- Run the following command:
14+
```bash
15+
gradle-profiler --benchmark --project-dir ../ --scenario-file ./scenarios.txt
16+
```
17+
- Once the run finishes, copy the items in `profile-out/benchmark.csv` to `benchmarks/old.txt` OR create a new file
18+
- Checkout to the current branch
19+
- Use the same scenarios from above and run the benchmark command
20+
- Once the run finishes, copy the items in `profile-out/benchmark.csv` to `benchmarks/new.txt` OR create a new file
21+
22+
> [NOTE]
23+
> Clear the `profile-out` folder before a next run, otherwise a new folder `profile-out2` will be created.
24+
> The changes to scenarios.txt or new file creation, similarly under benchmarks folder, will required to be
25+
> tracked to version control.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
measured build #1,77705.66
2+
measured build #2,73437.54
3+
measured build #3,82706.11
4+
measured build #4,75284.93
5+
measured build #5,75479.56
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
scenario,on_clean_build
2+
version,Gradle 9.3.1
3+
tasks,:brownfield:assembleRelease
4+
value,total execution time
5+
warm-up build #1,162130.94
6+
warm-up build #2,94060.00
7+
measured build #1,104519.90
8+
measured build #2,104545.84
9+
measured build #3,90355.22
10+
measured build #4,90874.80
11+
measured build #5,104207.60
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#!/bin/bash
2+
3+
# --- Colors for Output ---
4+
RED='\033[0;31m'
5+
GREEN='\033[0;32m'
6+
CYAN='\033[0;36m'
7+
YELLOW='\033[1;33m'
8+
BOLD='\033[1m'
9+
NC='\033[0m' # No Color
10+
11+
# --- Configuration & Args ---
12+
OLD_FILE=${1:-"benchmarks/old.txt"}
13+
NEW_FILE=${2:-"benchmarks/new.txt"}
14+
15+
# Validation
16+
if [[ ! -f "$OLD_FILE" || ! -f "$NEW_FILE" ]]; then
17+
echo "${RED}${BOLD}Error:${NC} Files not found."
18+
echo "Usage: $0 [old_file] [new_file]"
19+
exit 1
20+
fi
21+
22+
# --- Extraction Logic ---
23+
# Extract metadata from the first file (assuming they are for the same scenario)
24+
SCENARIO=$(grep "^scenario," "$OLD_FILE" | cut -d',' -f2)
25+
TASKS=$(grep "^tasks," "$OLD_FILE" | cut -d',' -f2)
26+
27+
# Calculation Function via AWK
28+
# Returns: avg|count
29+
process_data() {
30+
awk -F',' '/^measured build/ { sum += $2; count++ } END { if (count > 0) print sum/count "|" count; else print "0|0" }' "$1"
31+
}
32+
33+
OLD_DATA=$(process_data "$OLD_FILE")
34+
NEW_DATA=$(process_data "$NEW_FILE")
35+
36+
OLD_AVG=$(echo "$OLD_DATA" | cut -d'|' -f1)
37+
OLD_CNT=$(echo "$OLD_DATA" | cut -d'|' -f2)
38+
NEW_AVG=$(echo "$NEW_DATA" | cut -d'|' -f1)
39+
NEW_CNT=$(echo "$NEW_DATA" | cut -d'|' -f2)
40+
41+
# --- Verbose Pretty Print ---
42+
echo "${CYAN}${BOLD}=============================================================="
43+
echo " GRADLE BENCHMARK COMPARISON"
44+
echo "==============================================================${NC}"
45+
printf "${BOLD}%-12s${NC} %s\n" "Scenario:" "$SCENARIO"
46+
printf "${BOLD}%-12s${NC} %s\n" "Tasks:" "$TASKS"
47+
echo "--------------------------------------------------------------"
48+
49+
# Table Header
50+
printf "${BOLD}%-15s | %-12s | %-15s | %-10s${NC}\n" "Target" "Builds" "Average (ms)" "Minutes"
51+
echo "----------------|--------------|-----------------|------------"
52+
53+
# Row function for reuse
54+
print_row() {
55+
local label=$1
56+
local cnt=$2
57+
local avg=$3
58+
# Calculate minutes/seconds inside AWK for the row
59+
local min_fmt=$(awk -v ms="$avg" 'BEGIN { printf "%dm %05.2fs", int(ms/60000), (ms%60000)/1000 }')
60+
printf "%-15s | %-12s | %-15.2f | %-10s\n" "$label" "$cnt" "$avg" "$min_fmt"
61+
}
62+
63+
print_row "Main" "$OLD_CNT" "$OLD_AVG"
64+
print_row "Optimized" "$NEW_CNT" "$NEW_AVG"
65+
66+
echo "----------------|--------------|-----------------|------------"
67+
68+
# Final Comparison Logic
69+
awk -v old="$OLD_AVG" -v new="$NEW_AVG" \
70+
-v red="$RED" -v grn="$GREEN" -v yel="$YELLOW" -v bld="$BOLD" -v nc="$NC" '
71+
BEGIN {
72+
diff = new - old
73+
pct = (old > 0) ? (diff / old) * 100 : 0
74+
abs_diff = (diff < 0) ? -diff : diff
75+
76+
# Format diff to minutes
77+
diff_min = sprintf("%dm %05.2fs", int(abs_diff/60000), (abs_diff%60000)/1000)
78+
79+
if (diff < -1) {
80+
printf "\n%sRESULT: IMPROVEMENT%s\n\n", grn bld, nc
81+
printf "The new build is %s%.2f ms (%s) faster%s\n", grn, abs_diff, diff_min, nc
82+
printf "Speedup: %s%.2f%%%s\n", grn, -pct, nc
83+
} else if (diff > 1) {
84+
printf "\n%sRESULT: REGRESSION%s\n", red bld, nc
85+
printf "The new build is %s%.2f ms (%s) slower%s\n", red, diff, diff_min, nc
86+
printf "Slowdown: %s+%.2f%%%s\n", red, pct, nc
87+
} else {
88+
printf "\n%sRESULT: NEGLIGIBLE CHANGE%s\n", yel, nc
89+
}
90+
print ""
91+
}'
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
on_clean_build {
2+
tasks = [":brownfield:assembleRelease"] // Replace with your task
3+
cleanup-tasks = ["clean"]
4+
# Disables caching to ensure an "absolute" clean run
5+
gradle-args = ["--no-build-cache", "--no-configuration-cache"]
6+
warm-ups = 2
7+
iterations = 5
8+
}

apps/scripts/prepare-android-build-gradle-for-ci.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ if (!projectDirName) {
99

1010
const __filename = fileURLToPath(import.meta.url);
1111
const __dirname = path.dirname(__filename);
12-
const SNAPSHOT_VERSION = '1.1.0-SNAPSHOT';
12+
const SNAPSHOT_VERSION = '2.0.0-alpha01-SNAPSHOT';
1313
const targetPath = path.resolve(
1414
__dirname,
1515
'..',

gradle-plugins/react/brownfield/build.gradle.kts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,6 @@ publishing {
6666
distribution.set("repo")
6767
}
6868
}
69-
developers {
70-
developer {
71-
id.set("callstack")
72-
name.set("Callstack Team")
73-
email.set("it-admin@callstack.com")
74-
}
75-
}
76-
scm {
77-
connection.set(property("SCM_CONNECTION").toString())
78-
developerConnection.set(property("SCM_DEV_CONNECTION").toString())
79-
url.set(property("GITHUB_URL").toString())
80-
}
8169
}
8270
}
8371
}

0 commit comments

Comments
 (0)