From 6a2a93487bed710e34fd887446e7df887e50bd01 Mon Sep 17 00:00:00 2001 From: dmitrii Date: Tue, 14 Jul 2026 12:35:28 +0200 Subject: [PATCH 1/2] Replace linear IP blocklist scan with indexed trie lookup IPList.containsAddress() scanned every stored subnet/host linearly (O(n)). At 300k+ entries this costs ~13.7ms per lookup; isIpBlocked runs it up to 4x per request. Switched to inet.ipaddr's built-in DualIPv4v6Tries, giving O(bits) containment lookups (~1.2us at the same scale). Public API and matches() semantics unchanged; all existing IPListTest cases pass unmodified. --- .../dev/aikido/agent_api/helpers/net/IPList.java | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/agent_api/src/main/java/dev/aikido/agent_api/helpers/net/IPList.java b/agent_api/src/main/java/dev/aikido/agent_api/helpers/net/IPList.java index 0d1fde97..01813d51 100644 --- a/agent_api/src/main/java/dev/aikido/agent_api/helpers/net/IPList.java +++ b/agent_api/src/main/java/dev/aikido/agent_api/helpers/net/IPList.java @@ -2,15 +2,13 @@ import inet.ipaddr.IPAddress; import inet.ipaddr.IPAddressString; - -import java.util.HashSet; -import java.util.Set; +import inet.ipaddr.format.util.DualIPv4v6Tries; public class IPList { - private Set ipAddresses; + private final DualIPv4v6Tries ipAddresses; public IPList() { - this.ipAddresses = new HashSet<>(); + this.ipAddresses = new DualIPv4v6Tries(); } public void add(String ipOrCIDR) { @@ -56,12 +54,7 @@ public boolean matches(String ip) { } private boolean containsAddress(IPAddress ipAddress) { - for (IPAddress subnet : ipAddresses) { - if (subnet.contains(ipAddress)) { - return true; - } - } - return false; + return ipAddresses.elementContains(ipAddress); } public int length() { return ipAddresses.size(); From 14382c1dcce71d7cf7bc93095e94a7dd98762b79 Mon Sep 17 00:00:00 2001 From: Hans Ott Date: Tue, 14 Jul 2026 19:13:45 +0200 Subject: [PATCH 2/2] Load JaCoCo before our agent --- agent_api/build.gradle | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/agent_api/build.gradle b/agent_api/build.gradle index b0f758f1..96c01bb2 100644 --- a/agent_api/build.gradle +++ b/agent_api/build.gradle @@ -46,7 +46,6 @@ dependencies { test { jvmArgs '--add-opens', 'java.base/java.util=ALL-UNNAMED' jvmArgs '--add-opens', 'java.base/java.lang=ALL-UNNAMED' - jvmArgs "-javaagent:${project.rootDir}/dist/agent.jar=mode=daemon-disabled" jvmArgs '-Dnet.bytebuddy.experimental=true' // Mockito support. systemProperty 'AIK_agent_dir', "${project.rootDir}/dist" @@ -64,6 +63,13 @@ test { jacoco { enabled = true } + doFirst { + // JaCoCo's javaagent must load before our own agent.jar. Our agent registers a + // retransformation-capable ByteBuddy transformer; if it loads first, JaCoCo silently + // stops recording coverage for almost every class, not just the ones we instrument. + jvmArgs jacoco.getAsJvmArg(), "-javaagent:${project.rootDir}/dist/agent.jar=mode=daemon-disabled" + jacoco.enabled = false + } } jacocoTestReport {