Skip to content

⚡️ Speed up method LuaInstance.getLuaValue by 7%#102

Open
codeflash-ai[bot] wants to merge 1 commit intofix/add-mockito-test-dependencyfrom
codeflash/optimize-LuaInstance.getLuaValue-mmbslsyq
Open

⚡️ Speed up method LuaInstance.getLuaValue by 7%#102
codeflash-ai[bot] wants to merge 1 commit intofix/add-mockito-test-dependencyfrom
codeflash/optimize-LuaInstance.getLuaValue-mmbslsyq

Conversation

@codeflash-ai
Copy link
Copy Markdown

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

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

⏱️ Runtime : 237 microseconds 221 microseconds (best of 149 runs)

📝 Explanation and details

This change cuts getLuaValue runtime from 237µs to 221µs (≈7% speedup) by replacing repeated instanceof checks with a single cls = obj.getClass() and fast exact-class comparisons (cls == X.class) and by switching wrapper-object handling to primitive accessors (intValue(), longValue(), etc.). Exact-class checks avoid repeated virtual instanceof/type resolution and are significantly cheaper for final types and arrays, and hoisting getClass eliminates duplicated class lookup on the hot path. Using the primitive accessors removes extra boxing/unboxing and redundant casts, allowing the LuaInteger/LuaDouble valueOf overloads to be invoked with primitives instead of re-wrapping objects. There is no behavioral change for final JVM wrapper types (Integer, Long, Double, Float, Boolean) or byte[]; the only trade-off is a small, intentional narrowing of checks to exact classes (which is safe here) and a minor increase in code-specificity for a measurable per-call speed gain.

Correctness verification report:

Test Status
⚙️ Existing Unit Tests 🔘 None Found
🌀 Generated Regression Tests 33 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.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import com.aerospike.client.Value;

import org.luaj.vm2.LuaBoolean;
import org.luaj.vm2.LuaDouble;
import org.luaj.vm2.LuaInteger;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
// Performance comparison:
// LuaInstanceTest.testString_ReturnsLuaString#5: 0.000ms -> 0.000ms (11.7% faster)
// LuaInstanceTest.testLong_ReturnsLuaIntegerForLongs#7: 0.001ms -> 0.001ms (29.3% faster)
// LuaInstanceTest.testInteger_ReturnsLuaInteger#6: 0.001ms -> 0.000ms (25.8% faster)
// LuaInstanceTest.testMap_ReturnsLuaTableWithKeyValues#14: 0.004ms -> 0.004ms (-6.4% faster)
// LuaInstanceTest.testList_ReturnsLuaTableWithIndexedValues#12: 0.002ms -> 0.002ms (-0.5% faster)
// LuaInstanceTest.testFloat_ReturnsLuaDoubleForFloat#9: 0.001ms -> 0.001ms (-15.4% faster)
// LuaInstanceTest.testBoolean_ReturnsLuaBoolean#10: 0.000ms -> 0.000ms (-7.5% faster)
// LuaInstanceTest.testBoolean_ReturnsLuaBoolean#11: 0.000ms -> 0.000ms (-31.5% faster)
// LuaInstanceTest.testEmptyMap_ReturnsEmptyLuaTable#15: 0.002ms -> 0.002ms (3.1% faster)
// LuaInstanceTest.testDouble_ReturnsLuaDouble#8: 0.001ms -> 0.001ms (-4.9% faster)
// LuaInstanceTest.testByteArray_ReturnsLuaBytesInstance#4: 0.001ms -> 0.001ms (13.7% faster)
// LuaInstanceTest.testNullValue_ReturnsNil#1: 0.000ms -> 0.000ms (-4.5% faster)
// LuaInstanceTest.testLargeList_ConversionMaintainsOrderAndSize#17: 0.110ms -> 0.097ms (11.9% faster)
// LuaInstanceTest.testLuaValuePassthrough_ReturnsSameInstance#2: 0.000ms -> 0.000ms (2.7% faster)
// LuaInstanceTest.testUnknownObject_ReturnsNil#16: 0.000ms -> 0.000ms (-17.5% faster)
// LuaInstanceTest.testAerospikeValueString_ReturnsLuaString#3: 0.000ms -> 0.000ms (0.0% faster)
// LuaInstanceTest.testEmptyList_ReturnsEmptyLuaTable#13: 0.001ms -> 0.001ms (-8.7% faster)
// LuaInstanceTest.testLongInput_ReturnsLuaInteger#8: 0.000ms -> 0.000ms (34.1% faster)
// LuaInstanceTest.testListInput_ReturnsLuaTable_WithCorrectElements#13: 0.001ms -> 0.001ms (7.9% faster)
// LuaInstanceTest.testFloatInput_ReturnsLuaDouble#10: 0.000ms -> 0.000ms (-23.4% faster)
// LuaInstanceTest.testValueStringInput_ReturnsLuaString#3: 0.000ms -> 0.000ms (-0.9% faster)
// LuaInstanceTest.testStringInput_ReturnsLuaString#6: 0.000ms -> 0.000ms (-6.0% faster)
// LuaInstanceTest.testUnsupportedObject_ReturnsNil#15: 0.000ms -> 0.000ms (21.2% faster)
// LuaInstanceTest.testMapInput_ReturnsLuaTable_WithCorrectKeyValue#14: 0.002ms -> 0.002ms (10.8% faster)
// LuaInstanceTest.testIntegerInput_ReturnsLuaInteger#7: 0.000ms -> 0.000ms (19.8% faster)
// LuaInstanceTest.testLuaValueInput_ReturnsSameInstance#2: 0.000ms -> 0.000ms (2.8% faster)
// LuaInstanceTest.testLargeList_ConversionPreservesSizeAndSampleElements#16: 0.106ms -> 0.104ms (1.8% faster)
// LuaInstanceTest.testValueByteArrayInput_ReturnsUserdataLikeValue#5: 0.001ms -> 0.001ms (-3.6% faster)
// LuaInstanceTest.testDoubleInput_ReturnsLuaDouble#9: 0.000ms -> 0.000ms (3.0% faster)
// LuaInstanceTest.testNullInput_ReturnsNil#1: 0.000ms -> 0.000ms (7.7% faster)
// LuaInstanceTest.testBooleanInput_ReturnsLuaBoolean#11: 0.000ms -> 0.000ms (-5.4% faster)
// LuaInstanceTest.testBooleanInput_ReturnsLuaBoolean#12: 0.000ms -> 0.000ms (3.7% faster)
// LuaInstanceTest.testByteArrayInput_ReturnsUserdataLikeValue#4: 0.001ms -> 0.000ms (6.4% faster)

/**
 * Unit tests for com.aerospike.client.lua.LuaInstance#getLuaValue
 */
public class LuaInstanceTest {
    private LuaInstance instance;

    @Before
    public void setUp() throws Exception {
        // LuaInstance constructor can throw AerospikeException; allow test framework to handle it.
        instance = new LuaInstance();
    }

    @Test
    public void testNullInput_ReturnsNil() {
        LuaValue result = instance.getLuaValue(null);
        assertTrue("Expected NIL for null input", result.isnil());
    }

    @Test
    public void testLuaValueInput_ReturnsSameInstance() {
        LuaString luaStr = LuaString.valueOf("same");
        LuaValue result = instance.getLuaValue(luaStr);
        assertSame("Should return same LuaValue instance when input is already a LuaValue", luaStr, result);
    }

    @Test
    public void testValueStringInput_ReturnsLuaString() {
        Value v = Value.get("hello");
        LuaValue result = instance.getLuaValue(v);
        assertEquals("Expected Lua string value from Value.get(String)", "hello", result.tojstring());
    }

    @Test
    public void testByteArrayInput_ReturnsUserdataLikeValue() {
        byte[] bytes = new byte[] { 1, 2, 3 };
        LuaValue result = instance.getLuaValue(bytes);
        // LuaBytes is represented as userdata in Luaj; ensure not nil and typename indicates userdata.
        assertFalse("Byte[] input should not produce NIL", result.isnil());
        assertEquals("userdata", result.typename());
    }

    @Test
    public void testValueByteArrayInput_ReturnsUserdataLikeValue() {
        byte[] bytes = new byte[] { 9, 8, 7 };
        Value v = Value.get(bytes);
        LuaValue result = instance.getLuaValue(v);
        // Value.get(byte[]) should convert to the same userdata-like representation
        assertFalse("Value(byte[]) input should not produce NIL", result.isnil());
        assertEquals("userdata", result.typename());
    }

    @Test
    public void testStringInput_ReturnsLuaString() {
        LuaValue result = instance.getLuaValue("a string");
        assertEquals("a string", result.tojstring());
    }

    @Test
    public void testIntegerInput_ReturnsLuaInteger() {
        LuaValue result = instance.getLuaValue(Integer.valueOf(42));
        assertEquals(42, result.toint());
    }

    @Test
    public void testLongInput_ReturnsLuaInteger() {
        long value = 1234567890123L;
        LuaValue result = instance.getLuaValue(Long.valueOf(value));
        assertEquals(value, result.tolong());
    }

    @Test
    public void testDoubleInput_ReturnsLuaDouble() {
        double d = 3.14159;
        LuaValue result = instance.getLuaValue(Double.valueOf(d));
        assertEquals(d, result.todouble(), 0.0);
    }

    @Test
    public void testFloatInput_ReturnsLuaDouble() {
        float f = 2.5f;
        LuaValue result = instance.getLuaValue(Float.valueOf(f));
        assertEquals(f, result.todouble(), 0.0);
    }

    @Test
    public void testBooleanInput_ReturnsLuaBoolean() {
        LuaValue resultTrue = instance.getLuaValue(Boolean.TRUE);
        LuaValue resultFalse = instance.getLuaValue(Boolean.FALSE);
        assertTrue(resultTrue.toboolean());
        assertFalse(resultFalse.toboolean());
    }

    @Test
    public void testListInput_ReturnsLuaTable_WithCorrectElements() {
        List<Object> list = Arrays.asList("one", "two", "three");
        LuaValue result = instance.getLuaValue(list);
        assertTrue("Expected a LuaTable for List input", result instanceof LuaTable);
        LuaTable table = (LuaTable) result;
        // Lua tables are 1-indexed for arrays
        assertEquals("one", table.get(1).tojstring());
        assertEquals("two", table.get(2).tojstring());
        assertEquals("three", table.get(3).tojstring());
    }

    @Test
    public void testMapInput_ReturnsLuaTable_WithCorrectKeyValue() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("alpha", 10);
        map.put("beta", "value");
        LuaValue result = instance.getLuaValue(map);
        assertTrue("Expected a LuaTable for Map input", result instanceof LuaTable);
        LuaTable table = (LuaTable) result;
        assertEquals(10, table.get("alpha").toint());
        assertEquals("value", table.get("beta").tojstring());
    }

    @Test
    public void testUnsupportedObject_ReturnsNil() {
        Object unsupported = new Object();
        LuaValue result = instance.getLuaValue(unsupported);
        assertTrue("Unsupported object types should return NIL", result.isnil());
    }

    @Test
    public void testLargeList_ConversionPreservesSizeAndSampleElements() {
        final int size = 2000;
        List<Integer> bigList = new ArrayList<Integer>(size);
        for (int i = 0; i < size; i++) {
            bigList.add(i * 2);
        }
        LuaValue result = instance.getLuaValue(bigList);
        assertTrue("Expected a LuaTable for large List input", result instanceof LuaTable);
        LuaTable table = (LuaTable) result;
        assertEquals("Lua table length should match list size", size, table.length());
        // Verify a few random positions
        Random rnd = new Random(12345);
        for (int i = 0; i < 5; i++) {
            int idx = rnd.nextInt(size) + 1; // 1-based
            assertEquals((idx - 1) * 2, table.get(idx).toint());
        }
    }
}

To edit these changes git checkout codeflash/optimize-LuaInstance.getLuaValue-mmbslsyq and push.

Codeflash Static Badge

This change cuts getLuaValue runtime from 237µs to 221µs (≈7% speedup) by replacing repeated instanceof checks with a single cls = obj.getClass() and fast exact-class comparisons (cls == X.class) and by switching wrapper-object handling to primitive accessors (intValue(), longValue(), etc.). Exact-class checks avoid repeated virtual instanceof/type resolution and are significantly cheaper for final types and arrays, and hoisting getClass eliminates duplicated class lookup on the hot path. Using the primitive accessors removes extra boxing/unboxing and redundant casts, allowing the LuaInteger/LuaDouble valueOf overloads to be invoked with primitives instead of re-wrapping objects. There is no behavioral change for final JVM wrapper types (Integer, Long, Double, Float, Boolean) or byte[]; the only trade-off is a small, intentional narrowing of checks to exact classes (which is safe here) and a minor increase in code-specificity for a measurable per-call speed gain.
@codeflash-ai codeflash-ai bot requested a review from misrasaurabh1 March 4, 2026 08:46
@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