Skip to content

⚡️ Speed up method Host.parseHosts by 8%#100

Open
codeflash-ai[bot] wants to merge 1 commit intofix/add-mockito-test-dependencyfrom
codeflash/optimize-Host.parseHosts-mmbrx7a9
Open

⚡️ Speed up method Host.parseHosts by 8%#100
codeflash-ai[bot] wants to merge 1 commit intofix/add-mockito-test-dependencyfrom
codeflash/optimize-Host.parseHosts-mmbrx7a9

Conversation

@codeflash-ai
Copy link
Copy Markdown

@codeflash-ai codeflash-ai bot commented Mar 4, 2026

📄 8% (0.08x) speedup for Host.parseHosts in client/src/com/aerospike/client/Host.java

⏱️ Runtime : 408 microseconds 378 microseconds (best of 169 runs)

📝 Explanation and details

parseHosts is ~8% faster (408 µs → 378 µs) after replacing the external HostParser with an inlined single-pass, low-allocation parser. The new implementation scans the input char-by-char, pre-counts commas outside IPv6 brackets to pre-size the ArrayList, trims and extracts fields by index (avoiding split/regex and many temporary substrings), and uses a cheap isDigits check so Integer.parseInt is only invoked for numeric port fields—collectively reducing allocations, repeated scans, and GC churn. Trade-offs are modest: the parsing logic is more manual and slightly larger, and a couple microbenchmarks show tiny variance within noise, but the net reduction in CPU and memory work improves throughput for common and large host lists.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 14 Passed
⏪ Replay Tests 🔘 None Found
🔎 Concolic Coverage Tests 🔘 None Found
📊 Tests Coverage 33.3%
🌀 Click to see Generated Regression Tests
package com.aerospike.client;

import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;

import com.aerospike.client.Host;
import com.aerospike.client.AerospikeException;
// Performance comparison:
// HostTest.testParseHosts_LargeNumberOfHosts_AllParsed#7: 0.236ms -> 0.211ms (10.9% faster)
// HostTest.testParseHosts_NullInput_ThrowsAerospikeException#5: 0.029ms -> 0.026ms (11.7% faster)
// HostTest.testParseHosts_EmptyString_ThrowsAerospikeException#6: 0.001ms -> 0.001ms (-0.1% faster)
// HostTest.testParseHosts_MultipleHosts_CommaSeparated_ParseAll#4: 0.002ms -> 0.002ms (16.8% faster)
// HostTest.testParseHosts_SingleHostWithPort_PortParsed#2: 0.001ms -> 0.001ms (-0.2% faster)
// HostTest.testParseHosts_SingleHost_DefaultPortApplied#1: 0.001ms -> 0.001ms (-25.8% faster)
// HostTest.testParseHosts_SingleHostWithTlsAndPort_TlsAndPortParsed#3: 0.002ms -> 0.002ms (-1.3% faster)
// HostTest.testParseHosts_MalformedHost_ThrowsAerospikeException#7: 0.027ms -> 0.024ms (11.3% faster)
// HostTest.testParseHosts_LargeNumberOfHosts_PerformanceAndCorrectness#8: 0.105ms -> 0.108ms (-2.5% faster)
// HostTest.testParseHosts_EmptyInput_ThrowsAerospikeException#6: 0.000ms -> 0.000ms (-23.4% faster)
// HostTest.testParseHosts_MultipleHosts_MixedFormats#4: 0.002ms -> 0.002ms (11.0% faster)
// HostTest.testParseHosts_SingleHost_WithTlsAndPort#3: 0.001ms -> 0.001ms (34.4% faster)
// HostTest.testParseHosts_SingleHost_DefaultPort#1: 0.001ms -> 0.001ms (28.7% faster)
// HostTest.testParseHosts_SingleHost_WithPort#2: 0.000ms -> 0.001ms (-43.7% faster)

/**
 * Unit tests for com.aerospike.client.Host.parseHosts
 */
public class HostTest {
    private Host instance;

    @Before
    public void setUp() {
        // Create an instance to satisfy the requirement of creating a Host instance.
        instance = new Host("init.example", "initTls", 1000);
    }

    @Test
    public void testParseHosts_SingleHost_DefaultPort() {
        Host[] hosts = Host.parseHosts("localhost", 3000);
        assertNotNull(hosts);
        assertEquals(1, hosts.length);
        assertEquals("localhost", hosts[0].name);
        assertNull(hosts[0].tlsName);
        assertEquals(3000, hosts[0].port);
    }

    @Test
    public void testParseHosts_SingleHost_WithPort() {
        Host[] hosts = Host.parseHosts("localhost:4000", 3000);
        assertNotNull(hosts);
        assertEquals(1, hosts.length);
        assertEquals("localhost", hosts[0].name);
        assertNull(hosts[0].tlsName);
        assertEquals(4000, hosts[0].port);
    }

    @Test
    public void testParseHosts_SingleHost_WithTlsAndPort() {
        Host[] hosts = Host.parseHosts("db.example.com:myTlsName:4242", 3000);
        assertNotNull(hosts);
        assertEquals(1, hosts.length);
        assertEquals("db.example.com", hosts[0].name);
        assertEquals("myTlsName", hosts[0].tlsName);
        assertEquals(4242, hosts[0].port);
    }

    @Test
    public void testParseHosts_MultipleHosts_MixedFormats() {
        Host[] hosts = Host.parseHosts("host1:3000,127.0.0.1:4000,[::1]:5000", 2000);
        assertNotNull(hosts);
        assertEquals(3, hosts.length);

        // host1
        assertEquals("host1", hosts[0].name);
        assertEquals(3000, hosts[0].port);

        // IPv4
        assertEquals("127.0.0.1", hosts[1].name);
        assertEquals(4000, hosts[1].port);

        // IPv6 (Host parser removes brackets; ensure the core address is present)
        assertTrue("IPv6 address should contain ::1", hosts[2].name.contains("::1"));
        assertEquals(5000, hosts[2].port);
    }

    @Test(expected = AerospikeException.class)
    public void testParseHosts_NullInput_ThrowsAerospikeException() {
        Host.parseHosts(null, 3000);
    }

    @Test(expected = AerospikeException.class)
    public void testParseHosts_EmptyInput_ThrowsAerospikeException() {
        Host.parseHosts("", 3000);
    }

    @Test(expected = AerospikeException.class)
    public void testParseHosts_MalformedHost_ThrowsAerospikeException() {
        // Too many colon-separated parts for a single host should be invalid
        Host.parseHosts("badhost:tls:4000:extra", 3000);
    }

    @Test
    public void testParseHosts_LargeNumberOfHosts_PerformanceAndCorrectness() {
        final int count = 1000;
        final int basePort = 5000;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            if (i > 0) {
                sb.append(',');
            }
            // Use explicit ports to avoid ambiguity
            sb.append("host").append(i).append(':').append(basePort + i);
        }
        Host[] hosts = Host.parseHosts(sb.toString(), 1234);
        assertNotNull(hosts);
        assertEquals(count, hosts.length);

        // Spot check first, middle, and last
        assertEquals("host0", hosts[0].name);
        assertEquals(basePort + 0, hosts[0].port);

        assertEquals("host499", hosts[499].name);
        assertEquals(basePort + 499, hosts[499].port);

        assertEquals("host999", hosts[999].name);
        assertEquals(basePort + 999, hosts[999].port);
    }
}

To edit these changes git checkout codeflash/optimize-Host.parseHosts-mmbrx7a9 and push.

Codeflash Static Badge

parseHosts is ~8% faster (408 µs → 378 µs) after replacing the external HostParser with an inlined single-pass, low-allocation parser. The new implementation scans the input char-by-char, pre-counts commas outside IPv6 brackets to pre-size the ArrayList, trims and extracts fields by index (avoiding split/regex and many temporary substrings), and uses a cheap isDigits check so Integer.parseInt is only invoked for numeric port fields—collectively reducing allocations, repeated scans, and GC churn. Trade-offs are modest: the parsing logic is more manual and slightly larger, and a couple microbenchmarks show tiny variance within noise, but the net reduction in CPU and memory work improves throughput for common and large host lists.
@codeflash-ai codeflash-ai bot requested a review from misrasaurabh1 March 4, 2026 08:27
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash labels Mar 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants