Agent & runtime performance overhaul
Custom dependency injection framework and Spring Boot → Micronaut migration cut job startup from 6–8 seconds to 1–2 seconds and memory by 50–60%.
Startup: 6–8s → 1–2s · Memory: 500MB → 250MB
The problem
ACCELQ's test execution jobs were taking 6–8 seconds to start and consuming 500–600 MB of memory at job process startup. The AQExecutionManager (agent) itself consumed 400–600 MB. As the platform grew in features and supported libraries, startup time was getting progressively worse.
Root cause: Weld CDI — the dependency injection framework — generates proxy classes and subclasses for every @Command annotation at startup. Each new library or command on BaseWebElement and TextBasedWebElement added ~1 second to startup. There was no way to cache these generated classes across restarts within Weld's model.
What I built
Designed and implemented a custom dependency injection framework that caches generated proxy classes and subclasses for Library and Context classes across restarts. This eliminates Weld's per-startup generation while requiring zero changes to the runtime's existing @Command API surface.
Replaced Spring Boot in AQExecutionManager with Micronaut — an AOT-compiled, startup-optimised framework — reducing agent memory from 400–600 MB to 150–200 MB with minimal code changes.
Also built a custom FileManager using a lightweight XOR-based encoding algorithm: the server sends encoded source files, which are decoded in memory and fed directly to javac. The encoding is not reversible by any automated tool or AI, protecting proprietary compilation logic.
Approaches considered
Architecture
Custom DI: on first startup, scans all Library/Context classes → generates and caches proxy/subclass bytecode to disk → subsequent startups load from cache, skipping Weld entirely for cached classes. Micronaut agent: AOT-compiled at build time, no runtime scanning. XOR FileManager: server sends XOR-encoded source → decoded in-memory → piped to javac tool.
Result
Job startup: 6–8 seconds → 1–2 seconds. Job process startup memory: 500–600 MB → 250–300 MB. Agent (AQExecutionManager) memory: 400–600 MB → 150–200 MB. Playback job pickup wait (previously up to 5 seconds) eliminated. The system scales better as the platform adds new libraries — the cache absorbs new entries without affecting cold-start time for unchanged classes.