Can access by local method variables be faster then access by member variables ?

Charles Oliver Nutter charles.nutter at sun.com
Fri Aug 15 15:44:12 PDT 2008


I'll be interested to hear from the HotSpot engineers, but a few things 
I know might help:

- local variables will be allocated on the stack and will be much hotter 
in the cache
- obviously member variables are going to need to load and dereference 
for every access, which would be slower than just retrieving a local 
variable, with or without pushes and pops
- fields can obviously incur some cross-thread perf penalty if they 
result in memory caches getting wacked, which you would not have 
accessing local vars
- When we're able to move Ruby local variables from a heap-based 
structure to local variables (stack-based) in JRuby, we see a tremendous 
improvement in performance. It's probably the single largest perf boost 
we get from compilation.

- Charlie

Ulf Zibis wrote:
> Hi experts,
> 
> to avoid stack push + pop of src, dst I have refactored my code in 
> moving the local method variables (sp, ...) to member variables (srcPos, 
> ...).
> 
> After this I have experienced that my code was little slower.
> 
> For full source code see:
> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/trunk/src/sun/nio/cs/SingleByteEncoder.java?rev=291&view=markup 
> 
> https://java-nio-charset-enhanced.dev.java.net/source/browse/java-nio-charset-enhanced/trunk/src/sun/nio/cs/SingleByteEncoder.java?rev=302&view=markup 
> 
> 
> ======================================== revisions 291 
> ========================================
> 
>    private CoderResult encodeArraysLoop(CharBuffer src, ByteBuffer dst) {
>        char[] sa = src.array();
>        int sp = src.arrayOffset() + src.position();
>        int sl = src.arrayOffset() + src.limit();
>        assert (sp <= sl);
>        byte[] da = dst.array();
>        int dp = dst.arrayOffset() + dst.position();
>        int dl = dst.arrayOffset() + dst.limit();
>        assert (dp <= dl);
>        try {
>            for (; sp < sl; sp++) {
>                current = sa[sp];
>                byte b = encodeSingle();
>                if (dp >= dl)
>                    return CoderResult.OVERFLOW;
>                da[dp++] = b;
>            }
>            return CoderResult.UNDERFLOW;
>        } catch (UnmappableCharacterException e) {
>            if (Surrogate.isLow(current) || current >= '\uFFFE')
>                return CODERRESULT_MALFORMED;
>            if (Surrogate.isHigh(current))
>                try {
>                    if (sp+1 >= sl)
>                        return CoderResult.UNDERFLOW;
>                    encodeSurrogate(sa[sp+1]);
>                } catch (UnmappableCharacterException e2) {
>                    return CODERRESULT_UNMAPPABLE2;
>                } catch (MalformedInputException e2) {
>                    return CODERRESULT_MALFORMED2;
>                }
>            return CODERRESULT_UNMAPPABLE;
>        } finally {
>            src.position(sp - src.arrayOffset());
>            dst.position(dp - dst.arrayOffset());
>        }
>    }
> 
> ======================================== revisions 302 
> ========================================
> 
>    private CoderResult encodeArraysLoop() throws RuntimeException, 
> UnmappableCharacterException {
>        for (; srcPos < srcLimit; srcPos++) {
>            current = srcArray[srcPos];
>            byte b = encodeSingle();
>            if (dstPos < dstLimit)
>                dstArray[dstPos++] = b;
>            else
>                return CoderResult.OVERFLOW;
>        }
>        return CoderResult.UNDERFLOW;
>    }
> 
> =============================================================================================== 
> 
> 
> 
> Thanks for your explanations,
> 
> Ulf
> 
> 
> 
> 




More information about the hotspot-dev mailing list