Created
October 27, 2025 22:03
-
-
Save dallonf/29367e4e0375c04ba3b03b65ef70d40b to your computer and use it in GitHub Desktop.
Binary search of required memory to run TypeScript on a codebase
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env node | |
| const { execSync } = require('child_process'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| /** | |
| * Tests if TypeScript can run with the given memory amount | |
| * @param {number} memoryMB - Memory in megabytes | |
| * @returns {boolean} - True if successful, false if out of memory | |
| */ | |
| function testMemory(memoryMB) { | |
| console.log(`Testing with ${memoryMB} MB...`); | |
| try { | |
| execSync(`npx tsc --noEmit --incremental false`, { | |
| stdio: 'pipe', | |
| cwd: __dirname, | |
| env: { | |
| PATH: process.env.PATH, | |
| NODE_OPTIONS: `--max-old-space-size=${memoryMB}`, | |
| }, | |
| }); | |
| console.log(`✓ Success with ${memoryMB} MB`); | |
| return true; | |
| } catch (error) { | |
| const exitCode = error.status; | |
| // Exit codes in the 130s indicate memory issues | |
| if (exitCode == null || (exitCode >= 130 && exitCode < 140)) { | |
| console.log( | |
| `✗ Out of memory with ${memoryMB} MB (exit code: ${exitCode})`, | |
| ); | |
| return false; | |
| } | |
| // Other errors might be compilation errors, which we consider as success | |
| // (it compiled enough to find errors) | |
| console.log( | |
| `✓ Completed with ${memoryMB} MB (exit code: ${exitCode}, non-memory error: ${error.output.toString().trim()})`, | |
| ); | |
| return true; | |
| } | |
| } | |
| /** | |
| * Find the upper bound by doubling from a known lower bound | |
| */ | |
| function findUpperBound(lowerBound) { | |
| console.log('\n=== Finding upper bound ==='); | |
| let current = lowerBound; | |
| while (true) { | |
| current *= 2; | |
| if (testMemory(current)) { | |
| console.log(`Found upper bound: ${current} MB\n`); | |
| return current; | |
| } | |
| } | |
| } | |
| /** | |
| * Find the lower bound by halving from a known upper bound | |
| */ | |
| function findLowerBound(upperBound) { | |
| console.log('\n=== Finding lower bound ==='); | |
| let current = upperBound; | |
| while (true) { | |
| current = Math.floor(current / 2); | |
| if (current < 128) { | |
| console.log(`Reached minimum reasonable memory: ${current} MB\n`); | |
| return current; | |
| } | |
| if (!testMemory(current)) { | |
| console.log(`Found lower bound: ${current} MB\n`); | |
| return current; | |
| } | |
| } | |
| } | |
| /** | |
| * Binary search to find the exact point where it starts failing | |
| */ | |
| function binarySearch(lowerBound, upperBound) { | |
| console.log('\n=== Binary search ==='); | |
| console.log(`Searching between ${lowerBound} MB and ${upperBound} MB`); | |
| let low = lowerBound; | |
| let high = upperBound; | |
| while (high - low > 32) { | |
| const mid = Math.floor((low + high) / 2); | |
| if (testMemory(mid)) { | |
| // Success means we can try lower | |
| high = mid; | |
| } else { | |
| // Failure means we need more memory | |
| low = mid; | |
| } | |
| } | |
| return { failsAt: low, succeedsAt: high }; | |
| } | |
| // Main execution | |
| console.log('=== TypeScript Memory Requirements Test ===\n'); | |
| const initialTest = 2048; | |
| console.log(`Starting with initial test of ${initialTest} MB\n`); | |
| const initialResult = testMemory(initialTest); | |
| let lowerBound, upperBound; | |
| if (initialResult) { | |
| // It succeeded, so we need to find the lower bound | |
| upperBound = initialTest; | |
| lowerBound = findLowerBound(upperBound); | |
| } else { | |
| // It failed, so we need to find the upper bound | |
| lowerBound = initialTest; | |
| upperBound = findUpperBound(lowerBound); | |
| } | |
| const result = binarySearch(lowerBound, upperBound); | |
| console.log('\n=== RESULTS ==='); | |
| console.log(`TypeScript FAILS at: ${result.failsAt} MB`); | |
| console.log(`TypeScript SUCCEEDS at: ${result.succeedsAt} MB`); | |
| console.log(`\nMinimum required memory: ~${result.succeedsAt} MB`); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment