From e13d50527253635bab51abe6bd886ae1beff161f Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 16:33:55 +0000 Subject: [PATCH 1/2] Optimize config.ini updates by batching shell executions - Reduce up to 5 separate shell executions to 1 for AVD configuration - Improves performance by eliminating redundant process spawns - Add comprehensive efficiency report documenting all identified improvements - All existing tests pass, no functional changes Co-Authored-By: Yang --- EFFICIENCY_REPORT.md | 59 +++++++++++++++++++++++++++++++++++++++++ src/emulator-manager.ts | 37 +++++++++++++++----------- 2 files changed, 80 insertions(+), 16 deletions(-) create mode 100644 EFFICIENCY_REPORT.md diff --git a/EFFICIENCY_REPORT.md b/EFFICIENCY_REPORT.md new file mode 100644 index 000000000..8c1de4585 --- /dev/null +++ b/EFFICIENCY_REPORT.md @@ -0,0 +1,59 @@ +# Android Emulator Runner - Efficiency Improvements Report + +## Overview +This report documents efficiency improvements identified in the Android Emulator Runner codebase. The analysis focused on finding opportunities to reduce redundant operations, optimize I/O, and improve overall performance. + +## Identified Inefficiencies + +### 1. Multiple Shell Executions for Config.ini Updates (HIGH IMPACT) ⚡ +**File:** `src/emulator-manager.ts` (Lines 40-58) +**Issue:** The code executes up to 5 separate shell commands to append configuration entries to the AVD config.ini file. +**Impact:** Each shell execution spawns a new process, which is expensive. When multiple config options are set, this results in 5 separate process spawns. +**Solution:** Batch all configuration entries into a single shell command. +**Performance Gain:** Reduces shell executions from 5 to 1 (up to 80% reduction in process spawns). + +### 2. Inefficient Channel Mapping (MEDIUM IMPACT) +**File:** `src/channel-id-mapper.ts` (Lines 1-13) +**Issue:** Uses if-else chain instead of a lookup table/map for channel name to ID mapping. +**Impact:** O(n) lookup time instead of O(1), though with only 4 channels the impact is minimal. +**Solution:** Replace with a Map or object lookup. +**Performance Gain:** Constant time lookup instead of linear search. + +### 3. Repeated Number Conversions (LOW IMPACT) +**File:** `src/input-validator.ts` (Lines 79, 92, 97) +**Issue:** The `checkEmulatorBuild` and `checkDiskSize` functions call `Number()` multiple times on the same string. +**Impact:** Unnecessary computation overhead. +**Solution:** Store the converted number in a variable and reuse it. +**Performance Gain:** Eliminates redundant type conversions. + +### 4. Regex Creation on Every Function Call (LOW IMPACT) +**File:** `src/script-parser.ts` (Line 7) +**Issue:** Creates regex `/\r\n|\n|\r/` on every `parseScript` function call. +**Impact:** Regex compilation overhead on each invocation. +**Solution:** Define regex as a module-level constant. +**Performance Gain:** Eliminates regex recompilation. + +### 5. Redundant Boolean Validation Functions (LOW IMPACT) +**File:** `src/input-validator.ts` (Lines 39-76) +**Issue:** Multiple similar validation functions that all use the same `isValidBoolean` helper. +**Impact:** Code duplication and maintenance overhead. +**Solution:** Create a generic boolean validator function. +**Performance Gain:** Reduced code size and improved maintainability. + +## Implementation Priority + +1. **HIGH PRIORITY:** Config.ini shell execution batching (implemented in this PR) +2. **MEDIUM PRIORITY:** Channel mapping optimization +3. **LOW PRIORITY:** Number conversion optimization +4. **LOW PRIORITY:** Regex constant optimization +5. **LOW PRIORITY:** Boolean validation consolidation + +## Performance Impact Summary + +The primary fix implemented in this PR (batching config.ini updates) provides the most significant performance improvement by reducing shell process spawns from up to 5 to 1. This is particularly beneficial when multiple AVD configuration options are specified, which is a common use case. + +The other identified inefficiencies have lower impact but could be addressed in future optimization efforts for marginal performance gains and improved code maintainability. + +## Testing + +All existing tests pass with the implemented changes, ensuring no functional regressions while providing performance benefits. diff --git a/src/emulator-manager.ts b/src/emulator-manager.ts index 14684dede..44633319a 100644 --- a/src/emulator-manager.ts +++ b/src/emulator-manager.ts @@ -37,24 +37,29 @@ export async function launchEmulator( ); } - if (cores) { - await exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } - - if (ramSize) { - await exec.exec(`sh -c \\"printf 'hw.ramSize=${ramSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } + if (cores || ramSize || heapSize || enableHardwareKeyboard || diskSize) { + const configEntries: string[] = []; - if (heapSize) { - await exec.exec(`sh -c \\"printf 'hw.heapSize=${heapSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } - - if (enableHardwareKeyboard) { - await exec.exec(`sh -c \\"printf 'hw.keyboard=yes\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } + if (cores) { + configEntries.push(`hw.cpu.ncore=${cores}`); + } + if (ramSize) { + configEntries.push(`hw.ramSize=${ramSize}`); + } + if (heapSize) { + configEntries.push(`hw.heapSize=${heapSize}`); + } + if (enableHardwareKeyboard) { + configEntries.push('hw.keyboard=yes'); + } + if (diskSize) { + configEntries.push(`disk.dataPartition.size=${diskSize}`); + } - if (diskSize) { - await exec.exec(`sh -c \\"printf 'disk.dataPartition.size=${diskSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); + if (configEntries.length > 0) { + const configContent = configEntries.join('\\n') + '\\n'; + await exec.exec(`sh -c \\"printf '${configContent}' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini"`); + } } // turn off hardware acceleration on Linux From 5f92008c15cf952fa6f3451522840115e91972bb Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Sat, 14 Jun 2025 16:46:12 +0000 Subject: [PATCH 2/2] Add compiled JS files and remove standalone efficiency report - Include built lib/emulator-manager.js with batched config optimization - Remove EFFICIENCY_REPORT.md as requested - Efficiency report content will be moved to PR description Co-Authored-By: Yang --- EFFICIENCY_REPORT.md | 59 ----------------------------------------- lib/emulator-manager.js | 35 ++++++++++++++---------- 2 files changed, 21 insertions(+), 73 deletions(-) delete mode 100644 EFFICIENCY_REPORT.md diff --git a/EFFICIENCY_REPORT.md b/EFFICIENCY_REPORT.md deleted file mode 100644 index 8c1de4585..000000000 --- a/EFFICIENCY_REPORT.md +++ /dev/null @@ -1,59 +0,0 @@ -# Android Emulator Runner - Efficiency Improvements Report - -## Overview -This report documents efficiency improvements identified in the Android Emulator Runner codebase. The analysis focused on finding opportunities to reduce redundant operations, optimize I/O, and improve overall performance. - -## Identified Inefficiencies - -### 1. Multiple Shell Executions for Config.ini Updates (HIGH IMPACT) ⚡ -**File:** `src/emulator-manager.ts` (Lines 40-58) -**Issue:** The code executes up to 5 separate shell commands to append configuration entries to the AVD config.ini file. -**Impact:** Each shell execution spawns a new process, which is expensive. When multiple config options are set, this results in 5 separate process spawns. -**Solution:** Batch all configuration entries into a single shell command. -**Performance Gain:** Reduces shell executions from 5 to 1 (up to 80% reduction in process spawns). - -### 2. Inefficient Channel Mapping (MEDIUM IMPACT) -**File:** `src/channel-id-mapper.ts` (Lines 1-13) -**Issue:** Uses if-else chain instead of a lookup table/map for channel name to ID mapping. -**Impact:** O(n) lookup time instead of O(1), though with only 4 channels the impact is minimal. -**Solution:** Replace with a Map or object lookup. -**Performance Gain:** Constant time lookup instead of linear search. - -### 3. Repeated Number Conversions (LOW IMPACT) -**File:** `src/input-validator.ts` (Lines 79, 92, 97) -**Issue:** The `checkEmulatorBuild` and `checkDiskSize` functions call `Number()` multiple times on the same string. -**Impact:** Unnecessary computation overhead. -**Solution:** Store the converted number in a variable and reuse it. -**Performance Gain:** Eliminates redundant type conversions. - -### 4. Regex Creation on Every Function Call (LOW IMPACT) -**File:** `src/script-parser.ts` (Line 7) -**Issue:** Creates regex `/\r\n|\n|\r/` on every `parseScript` function call. -**Impact:** Regex compilation overhead on each invocation. -**Solution:** Define regex as a module-level constant. -**Performance Gain:** Eliminates regex recompilation. - -### 5. Redundant Boolean Validation Functions (LOW IMPACT) -**File:** `src/input-validator.ts` (Lines 39-76) -**Issue:** Multiple similar validation functions that all use the same `isValidBoolean` helper. -**Impact:** Code duplication and maintenance overhead. -**Solution:** Create a generic boolean validator function. -**Performance Gain:** Reduced code size and improved maintainability. - -## Implementation Priority - -1. **HIGH PRIORITY:** Config.ini shell execution batching (implemented in this PR) -2. **MEDIUM PRIORITY:** Channel mapping optimization -3. **LOW PRIORITY:** Number conversion optimization -4. **LOW PRIORITY:** Regex constant optimization -5. **LOW PRIORITY:** Boolean validation consolidation - -## Performance Impact Summary - -The primary fix implemented in this PR (batching config.ini updates) provides the most significant performance improvement by reducing shell process spawns from up to 5 to 1. This is particularly beneficial when multiple AVD configuration options are specified, which is a common use case. - -The other identified inefficiencies have lower impact but could be addressed in future optimization efforts for marginal performance gains and improved code maintainability. - -## Testing - -All existing tests pass with the implemented changes, ensuring no functional regressions while providing performance benefits. diff --git a/lib/emulator-manager.js b/lib/emulator-manager.js index 56a6d119b..ab84717f9 100644 --- a/lib/emulator-manager.js +++ b/lib/emulator-manager.js @@ -50,20 +50,27 @@ function launchEmulator(systemImageApiLevel, target, arch, profile, cores, ramSi console.log(`Creating AVD.`); yield exec.exec(`sh -c \\"echo no | avdmanager create avd --force -n "${avdName}" --abi '${target}/${arch}' --package 'system-images;android-${systemImageApiLevel};${target};${arch}' ${profileOption} ${sdcardPathOrSizeOption}"`); } - if (cores) { - yield exec.exec(`sh -c \\"printf 'hw.cpu.ncore=${cores}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } - if (ramSize) { - yield exec.exec(`sh -c \\"printf 'hw.ramSize=${ramSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } - if (heapSize) { - yield exec.exec(`sh -c \\"printf 'hw.heapSize=${heapSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } - if (enableHardwareKeyboard) { - yield exec.exec(`sh -c \\"printf 'hw.keyboard=yes\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); - } - if (diskSize) { - yield exec.exec(`sh -c \\"printf 'disk.dataPartition.size=${diskSize}\n' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini`); + if (cores || ramSize || heapSize || enableHardwareKeyboard || diskSize) { + const configEntries = []; + if (cores) { + configEntries.push(`hw.cpu.ncore=${cores}`); + } + if (ramSize) { + configEntries.push(`hw.ramSize=${ramSize}`); + } + if (heapSize) { + configEntries.push(`hw.heapSize=${heapSize}`); + } + if (enableHardwareKeyboard) { + configEntries.push('hw.keyboard=yes'); + } + if (diskSize) { + configEntries.push(`disk.dataPartition.size=${diskSize}`); + } + if (configEntries.length > 0) { + const configContent = configEntries.join('\\n') + '\\n'; + yield exec.exec(`sh -c \\"printf '${configContent}' >> ${process.env.ANDROID_AVD_HOME}/"${avdName}".avd"/config.ini"`); + } } // turn off hardware acceleration on Linux if (process.platform === 'linux' && disableLinuxHardwareAcceleration) {