Skip to content

⚡️ Speed up method LuaBytes.getBigInt32 by 7%#104

Open
codeflash-ai[bot] wants to merge 1 commit intofix/add-mockito-test-dependencyfrom
codeflash/optimize-LuaBytes.getBigInt32-mmbya6r9
Open

⚡️ Speed up method LuaBytes.getBigInt32 by 7%#104
codeflash-ai[bot] wants to merge 1 commit intofix/add-mockito-test-dependencyfrom
codeflash/optimize-LuaBytes.getBigInt32-mmbya6r9

Conversation

@codeflash-ai
Copy link
Copy Markdown

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

📄 7% (0.07x) speedup for LuaBytes.getBigInt32 in client/src/com/aerospike/client/lua/LuaBytes.java

⏱️ Runtime : 45.8 microseconds 42.6 microseconds (best of 159 runs)

📝 Explanation and details

The change yields a 7% runtime improvement (45.8 µs → 42.6 µs) by caching this.bytes and this.length into local variables and inlining Buffer.bytesToInt with explicit byte-wise bit shifts to build the 32-bit value. Inlining removes a method call and caching eliminates repeated instance-field dereferences, reducing call/dispatch and array-index overhead on the hot path so the JVM/JIT can generate tighter code. This is why the per-call cost drops even though the algorithm is functionally identical. The trade-off is a small, intentional duplication of the byte-decoding logic and slightly denser code in exchange for the measurable latency gain on this hot path.

Correctness verification report:

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

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

import java.util.Random;

import com.aerospike.client.command.Buffer;
import com.aerospike.client.lua.LuaBytes;
import com.aerospike.client.lua.LuaInstance;
// Performance comparison:
// LuaBytesTest.testOffsetLessThanZero_returnZero#4: 0.000ms -> 0.000ms (2.2% faster)
// LuaBytesTest.testEmptyBytes_returnZero#6: 0.000ms -> 0.000ms (-28.9% faster)
// LuaBytesTest.testTypicalBigEndian_returnCorrectInteger#1: 0.000ms -> 0.000ms (4.5% faster)
// LuaBytesTest.testNegativeIntegerBytes_returnNegativeValue#3: 0.000ms -> 0.000ms (14.1% faster)
// LuaBytesTest.testNullBytes_throwNullPointerException#7: 0.042ms -> 0.038ms (8.1% faster)
// LuaBytesTest.testNonZeroOffset_returnCorrectInteger#2: 0.000ms -> 0.000ms (2.1% faster)
// LuaBytesTest.testOffsetTooLarge_returnZero#5: 0.000ms -> 0.000ms (-30.6% faster)
// LuaBytesTest.testLargeArray_returnCorrectInteger#8: 0.000ms -> 0.000ms (-38.9% faster)
// LuaBytesTest.testGetBigInt32_LargeArray_PerformanceAndCorrectness#8: 0.001ms -> 0.001ms (2.2% faster)
// LuaBytesTest.testGetBigInt32_AllOnesBytes_ReturnsMinusOne#6: 0.000ms -> 0.000ms (-18.3% faster)
// LuaBytesTest.testGetBigInt32_NegativeOffset_ReturnsZero#3: 0.000ms -> 0.000ms (-33.9% faster)
// LuaBytesTest.testGetBigInt32_OffsetTooLarge_ReturnsZero#4: 0.000ms -> 0.000ms (25.4% faster)
// LuaBytesTest.testGetBigInt32_EmptyBytes_ReturnsZero#5: 0.000ms -> 0.000ms (-30.1% faster)
// LuaBytesTest.testGetBigInt32_OffsetBoundary_ReturnsCorrectInt#2: 0.000ms -> 0.000ms (7.2% faster)
// LuaBytesTest.testGetBigInt32_TypicalBytes_ReturnsCorrectInt#1: 0.000ms -> 0.000ms (-32.0% faster)

/**
 * Unit tests for com.aerospike.client.lua.LuaBytes#getBigInt32
 */
public class LuaBytesTest {
    private LuaInstance luaInstance;

    @Before
    public void setUp() {
        // LuaInstance is part of the same package. Use a real instance.
        // This test suite assumes LuaInstance has a public no-arg constructor.
        luaInstance = new LuaInstance();
    }

    @Test
    public void testGetBigInt32_TypicalBytes_ReturnsCorrectInt() {
        byte[] bytes = new byte[] { 1, 2, 3, 4 }; // should map to 0x01020304
        LuaBytes lb = new LuaBytes(luaInstance, bytes);
        int expected = Buffer.bytesToInt(bytes, 0);
        assertEquals(expected, lb.getBigInt32(0));
    }

    @Test
    public void testGetBigInt32_OffsetBoundary_ReturnsCorrectInt() {
        byte[] bytes = new byte[] { 0, 1, 2, 3, 4, 5 };
        LuaBytes lb = new LuaBytes(luaInstance, bytes);
        // read bytes at offset 2 -> {2,3,4,5}
        int expected = Buffer.bytesToInt(bytes, 2);
        assertEquals(expected, lb.getBigInt32(2));
    }

    @Test
    public void testGetBigInt32_NegativeOffset_ReturnsZero() {
        byte[] bytes = new byte[] { 10, 11, 12, 13 };
        LuaBytes lb = new LuaBytes(luaInstance, bytes);
        assertEquals(0, lb.getBigInt32(-1));
    }

    @Test
    public void testGetBigInt32_OffsetTooLarge_ReturnsZero() {
        byte[] bytes = new byte[] { 10, 11, 12, 13 };
        LuaBytes lb = new LuaBytes(luaInstance, bytes);
        // offset 1 => 1+4 = 5 > length(4) -> invalid
        assertEquals(0, lb.getBigInt32(1));
    }

    @Test
    public void testGetBigInt32_EmptyBytes_ReturnsZero() {
        // Use the capacity constructor to create zero-length byte array
        LuaBytes lb = new LuaBytes(luaInstance, 0);
        assertEquals(0, lb.getBigInt32(0));
    }

    @Test
    public void testGetBigInt32_AllOnesBytes_ReturnsMinusOne() {
        byte[] bytes = new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF };
        LuaBytes lb = new LuaBytes(luaInstance, bytes);
        // 0xFFFFFFFF as signed int is -1
        assertEquals(-1, lb.getBigInt32(0));
    }

    @Test(expected = NullPointerException.class)
    public void testConstructor_NullBytes_ThrowsNullPointerException() {
        // Passing null to constructor should result in NPE when accessing bytes.length
        new LuaBytes(luaInstance, (byte[]) null);
    }

    @Test
    public void testGetBigInt32_LargeArray_PerformanceAndCorrectness() {
        // Large but reasonable size for unit test execution
        final int size = 200_000;
        byte[] large = new byte[size];
        Random r = new Random(12345L);
        r.nextBytes(large);

        LuaBytes lb = new LuaBytes(luaInstance, large);

        // Check a few offsets: beginning, some random positions, and last valid offset
        int[] offsets = new int[] { 0, 1, 10, 100, 1000, 10_000, size - 4 };
        for (int offset : offsets) {
            int expected = Buffer.bytesToInt(large, offset);
            assertEquals("Mismatch at offset " + offset, expected, lb.getBigInt32(offset));
        }
    }
}

To edit these changes git checkout codeflash/optimize-LuaBytes.getBigInt32-mmbya6r9 and push.

Codeflash Static Badge

The change yields a 7% runtime improvement (45.8 µs → 42.6 µs) by caching this.bytes and this.length into local variables and inlining Buffer.bytesToInt with explicit byte-wise bit shifts to build the 32-bit value. Inlining removes a method call and caching eliminates repeated instance-field dereferences, reducing call/dispatch and array-index overhead on the hot path so the JVM/JIT can generate tighter code. This is why the per-call cost drops even though the algorithm is functionally identical. The trade-off is a small, intentional duplication of the byte-decoding logic and slightly denser code in exchange for the measurable latency gain on this hot path.
@codeflash-ai codeflash-ai bot requested a review from misrasaurabh1 March 4, 2026 11:25
@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