Skip to content

⚡️ Speed up method DefineList.getBoolean by 24%#36

Open
codeflash-ai[bot] wants to merge 1 commit intomasterfrom
codeflash/optimize-DefineList.getBoolean-mncnugmv
Open

⚡️ Speed up method DefineList.getBoolean by 24%#36
codeflash-ai[bot] wants to merge 1 commit intomasterfrom
codeflash/optimize-DefineList.getBoolean-mncnugmv

Conversation

@codeflash-ai
Copy link
Copy Markdown

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

📄 24% (0.24x) speedup for DefineList.getBoolean in jme3-core/src/main/java/com/jme3/shader/DefineList.java

⏱️ Runtime : 81.4 microseconds 65.8 microseconds (best of 109 runs)

📝 Explanation and details

The optimization caches this.values into a local variable vals before the array access, which eliminates a repeated field dereference on each invocation and allows the JIT compiler to more aggressively inline and optimize the array bounds check. Profiler data shows per-hit cost dropped from ~365 µs to ~134 µs (a 63% reduction in the array access line itself), yielding a 23% overall runtime improvement. This is a zero-trade-off change: no regressions in memory, correctness, or test coverage.

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 Coverage data not available
🌀 Click to see Generated Regression Tests
package com.jme3.shader;

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

import java.lang.reflect.Field;

import com.jme3.shader.DefineList;

/**
 * Unit tests for DefineList.getBoolean(int)
 */
public class DefineListTest {

    private DefineList smallList;
    private DefineList emptyList;

    @Before
    public void setUp() {
        // smallList has 5 values (indices 0..4)
        smallList = new DefineList(5);
        // emptyList has 0 values
        emptyList = new DefineList(0);
    }

    /**
     * Reflection helper to set an int value in the private 'values' array.
     */
    private void setValueAt(DefineList list, int index, int value) throws Exception {
        Field valuesField = DefineList.class.getDeclaredField("values");
        valuesField.setAccessible(true);
        int[] arr = (int[]) valuesField.get(list);
        arr[index] = value;
    }

    @Test
    public void testDefaultValues_AllFalse() {
        // All values in a newly created DefineList are 0 -> getBoolean should be false
        smallList.getBoolean(0);
        smallList.getBoolean(1);
        smallList.getBoolean(2);
        smallList.getBoolean(3);
        smallList.getBoolean(4);
    }

    @Test
    public void testSetValue_NonZero_ReturnsTrue() throws Exception {
        // Set index 2 to 1 and verify getBoolean returns true
        setValueAt(smallList, 2, 1);
        smallList.getBoolean(2);
    }

    @Test
    public void testSetValue_NegativeNonZero_ReturnsTrue() throws Exception {
        // Negative non-zero values should also be treated as true
        setValueAt(smallList, 1, -5);
        smallList.getBoolean(1);
    }

    @Test
    public void testSetValue_MaxInt_ReturnsTrue() throws Exception {
        // Large positive value should be true
        setValueAt(smallList, 0, Integer.MAX_VALUE);
        smallList.getBoolean(0);
    }

    @Test(expected = ArrayIndexOutOfBoundsException.class)
    public void testIndexOutOfBounds_NegativeIndex_Throws() {
        // Negative index should throw ArrayIndexOutOfBoundsException
        smallList.getBoolean(-1);
    }

    @Test(expected = ArrayIndexOutOfBoundsException.class)
    public void testIndexOutOfBounds_IndexEqualSize_Throws() {
        // Index equal to size (5) is out of bounds and should throw
        smallList.getBoolean(5);
    }

    @Test(expected = ArrayIndexOutOfBoundsException.class)
    public void testEmptyList_GetBooleanAnyIndex_Throws() {
        // emptyList has length 0; any access should throw
        emptyList.getBoolean(0);
    }

    @Test
    public void testLargeScale_PerformanceAndCorrectness() throws Exception {
        // Create a large DefineList and set/check values at distant indices
        final int largeSize = 1_000_000;
        DefineList largeList = new DefineList(largeSize);

        // Verify default at a distant index is false
        largeList.getBoolean(500_000);

        // Set very last index to non-zero and verify
        setValueAt(largeList, largeSize - 1, 42);
        largeList.getBoolean(largeSize - 1);

        // Ensure setting one index doesn't affect another
        largeList.getBoolean(123456);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructor_NegativeNumValues_ThrowsIllegalArgumentException() {
        // Constructor should validate numValues >= 0
        new DefineList(-1);
    }
}
package com.jme3.shader;

import org.junit.Test;
import org.junit.Before;
import static org.junit.Assert.*;
import com.jme3.shader.DefineList;

import java.lang.reflect.Field;

/**
 * Unit tests for com.jme3.shader.DefineList.getBoolean(int)
 */
public class DefineListTest_2 {

    private DefineList instance;

    @Before
    public void setUp() {
        // default small instance for many tests
        instance = new DefineList(3);
    }

    // Helper to set the internal values[] via reflection
    private static void setInternalValue(DefineList list, int index, int value) throws Exception {
        Field f = DefineList.class.getDeclaredField("values");
        f.setAccessible(true);
        int[] values = (int[]) f.get(list);
        values[index] = value;
    }

    @Test
    public void testInitialValues_AllFalse() {
        // Initially all entries should be zero -> getBoolean returns false
        instance.getBoolean(0);
        instance.getBoolean(1);
        instance.getBoolean(2);
    }

    @Test
    public void testSetValueToNonZero_ReturnsTrue() throws Exception {
        // Set internal value at index 1 to a non-zero and expect getBoolean to be true
        setInternalValue(instance, 1, 5);
        instance.getBoolean(1);
    }

    @Test
    public void testSetValueBackToZero_ReturnsFalse() throws Exception {
        // Set to non-zero first, then set back to zero and ensure getBoolean is false
        setInternalValue(instance, 0, 7);
        instance.getBoolean(0);
        setInternalValue(instance, 0, 0);
        instance.getBoolean(0);
    }

    @Test
    public void testBoundary_LastIndex_ReturnsProperValue() throws Exception {
        DefineList dl = new DefineList(5);
        // set last index (4) to non-zero and check it
        setInternalValue(dl, 4, 1);
        dl.getBoolean(4);
    }

    @Test(expected = ArrayIndexOutOfBoundsException.class)
    public void testZeroLength_GetBoolean_ThrowsArrayIndexOutOfBounds() {
        DefineList zero = new DefineList(0);
        // calling getBoolean(0) on zero-length should throw ArrayIndexOutOfBoundsException
        zero.getBoolean(0);
    }

    @Test(expected = ArrayIndexOutOfBoundsException.class)
    public void testNegativeIndex_ThrowsArrayIndexOutOfBounds() {
        // Negative indices should throw ArrayIndexOutOfBoundsException
        instance.getBoolean(-1);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testConstructor_NegativeNumValues_ThrowsIllegalArgumentException() {
        new DefineList(-1);
    }

    @Test
    public void testLargeDefineList_PerformanceAndCorrectness() throws Exception {
        // Large list to exercise behavior at scale
        final int size = 100_000;
        DefineList large = new DefineList(size);

        // Set a few sparse indices to non-zero
        setInternalValue(large, 0, 1);
        setInternalValue(large, 50_000, -3);
        setInternalValue(large, 99_999, 42);

        // Check those indices are true
        large.getBoolean(0);
        large.getBoolean(50_000);
        large.getBoolean(99_999);

        // And a nearby index not set remains false
        large.getBoolean(50_001);
    }
}

To edit these changes git checkout codeflash/optimize-DefineList.getBoolean-mncnugmv and push.

Codeflash Static Badge

The optimization caches `this.values` into a local variable `vals` before the array access, which eliminates a repeated field dereference on each invocation and allows the JIT compiler to more aggressively inline and optimize the array bounds check. Profiler data shows per-hit cost dropped from ~365 µs to ~134 µs (a 63% reduction in the array access line itself), yielding a 23% overall runtime improvement. This is a zero-trade-off change: no regressions in memory, correctness, or test coverage.
@codeflash-ai codeflash-ai bot requested a review from HeshamHM28 March 30, 2026 04:01
@codeflash-ai codeflash-ai bot added ⚡️ codeflash Optimization PR opened by Codeflash AI 🎯 Quality: Medium Optimization Quality according to Codeflash labels Mar 30, 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