Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3343880
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T01:00:19+00:00 2026-05-18T01:00:19+00:00

Maybe I’m being misled by my profiler (Netbeans), but I’m seeing some odd behavior,

  • 0

Maybe I’m being misled by my profiler (Netbeans), but I’m seeing some odd behavior, hoping maybe someone here can help me understand it.

I am working on an application, which makes heavy use of rather large hash tables (keys are longs, values are objects). The performance with the built in java hash table (HashMap specifically) was very poor, and after trying some alternatives — Trove, Fastutils, Colt, Carrot — I started working on my own.

The code is very basic using a double hashing strategy. This works fine and good and shows the best performance of all the other options I’ve tried thus far.

The catch is, according to the profiler, lookups into the hash table are the single most expensive method in the entire application — despite the fact that other methods are called many more times, and/or do a lot more logic.

What really confuses me is the lookups are called only by one class; the calling method does the lookup and processes the results. Both are called nearly the same number of times, and the method that calls the lookup has a lot of logic in it to handle the result of the lookup, but is about 100x faster.

Below is the code for the hash lookup. It’s basically just two accesses into an array (the functions that compute the hash codes, according to profiling, are virtually free). I don’t understand how this bit of code can be so slow since it is just array access, and I don’t see any way of making it faster.

Note that the code simply returns the bucket matching the key, the caller is expected to process the bucket. ‘size’ is the hash.length/2, hash1 does lookups in the first half of the hash table, hash2 does lookups in the second half. key_index is a final int field on the hash table passed into the constructor, and the values array on the Entry objects is a small array of longs usually of length 10 or less.

Any thoughts people have on this are much appreciated.

Thanks.

public final Entry get(final long theKey) {
    Entry aEntry = hash[hash1(theKey, size)];

    if (aEntry != null && aEntry.values[key_index] != theKey) {
        aEntry = hash[hash2(theKey, size)];

        if (aEntry != null && aEntry.values[key_index] != theKey) {
            return null;
        }
    }

    return aEntry;
}

Edit, the code for hash1 & hash2

private static int hash1(final long key, final int hashTableSize) { 
    return (int)(key&(hashTableSize-1)); 
}
private static int hash2(final long key, final int hashTableSize) { 
    return (int)(hashTableSize+((key^(key>>3))&(hashTableSize-1))); 
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T01:00:20+00:00Added an answer on May 18, 2026 at 1:00 am

    Nothing in your implementation strikes me as particularly inefficient. I’ll admit I don’t really follow your hashing/lookup strategy, but if you say it’s performant in your circumstances, I’ll believe you.

    The only thing that I would expect might make some difference is to move the key out of the values array of Entry.

    Instead of having this:

    class Entry {
        long[] values;
    }
    
    //...
    if ( entry.values[key_index] == key ) { //...
    

    Try this:

    class Entry {
        long key;
        long values[];
    }
    
    //...
    if ( entry.key == key ) { //...
    

    Instead of incurring the cost of accessing a member, plus doing bounds checking, then getting a value of the array, you should just incur the cost of accessing the member.

    Is there a random-access data type faster than an array?

    I was interested in the answer to this question, so I set up a test environment. This is my Array interface:

    interface Array {
        long get(int i);
        void set(int i, long v);
    }
    

    This “Array” has undefined behaviour when indices are out of bounds. I threw together the obvious implementation:

    class NormalArray implements Array {
        private long[] data;
    
        public NormalArray(int size) {
            data = new long[size];
        }
    
        @Override
        public long get(int i) {
            return data[i];
        }
    
        @Override
        public void set(int i, long v) {
            data[i] = v;
        }
    }
    

    And then a control:

    class NoOpArray implements Array {
        @Override
        public long get(int i) {
            return 0;
        }
        @Override
        public void set(int i, long v) {
        }
    }
    

    Finally, I designed an “array” where the first 10 indices are hardcoded members. The members are set/selected through a switch:

    class TenArray implements Array {
        private long v0;
        private long v1;
        private long v2;
        private long v3;
        private long v4;
        private long v5;
        private long v6;
        private long v7;
        private long v8;
        private long v9;
        private long[] extras;
    
        public TenArray(int size) {
            if (size > 10) {
                extras = new long[size - 10];
            }
        }
    
        @Override
        public long get(final int i) {
            switch (i) {
            case 0:
                return v0;
            case 1:
                return v1;
            case 2:
                return v2;
            case 3:
                return v3;
            case 4:
                return v4;
            case 5:
                return v5;
            case 6:
                return v6;
            case 7:
                return v7;
            case 8:
                return v8;
            case 9:
                return v9;
            default:
                return extras[i - 10];
            }
        }
    
        @Override
        public void set(final int i, final long v) {
            switch (i) {
            case 0:
                v0 = v; break;
            case 1:
                v1 = v; break;
            case 2:
                v2 = v; break;
            case 3:
                v3 = v; break;
            case 4:
                v4 = v; break;
            case 5:
                v5 = v; break;
            case 6:
                v6 = v; break;
            case 7:
                v7 = v; break;
            case 8:
                v8 = v; break;
            case 9:
                v9 = v; break;
            default:
                extras[i - 10] = v;
            }
        }
    }
    

    I tested it with this harness:

    import java.util.Random;
    
    public class ArrayOptimization {
        public static void main(String[] args) {
            int size = 10;
            long[] data = new long[size];
            Random r = new Random();
            for ( int i = 0; i < data.length; i++ ) {
                data[i] = r.nextLong();
            }
    
            Array[] a = new Array[] {
                    new NoOpArray(),
                    new NormalArray(size),
                    new TenArray(size)
            };
    
            for (;;) {
                for ( int i = 0; i < a.length; i++ ) {
                    testSet(a[i], data, 10000000);
                    testGet(a[i], data, 10000000);
                }
            }
        }
    
        private static void testGet(Array a, long[] data, int iterations) {
                long nanos = System.nanoTime();
            for ( int i = 0; i < iterations; i++ ) {
                for ( int j = 0; j < data.length; j++ ) {
                    data[j] = a.get(j);
                }
            }
            long stop = System.nanoTime();
            System.out.printf("%s/get took %fms%n", a.getClass().getName(), 
                    (stop - nanos) / 1000000.0);
        }
    
        private static void testSet(Array a, long[] data, int iterations) {
            long nanos = System.nanoTime();
            for ( int i = 0; i < iterations; i++ ) {
                for ( int j = 0; j < data.length; j++ ) {
                    a.set(j, data[j]);
                }
            }
            long stop = System.nanoTime();
            System.out.printf("%s/set took %fms%n", a.getClass().getName(), 
                    (stop - nanos) / 1000000.0);
    
        }
    }
    

    The results were somewhat surprising. The TenArray performs non-trivially faster than a NormalArray does (for sizes <= 10). Subtracting the overhead (using the NoOpArray average) you get TenArray as taking ~65% of the time of the normal array. So if you know the likely max size of your array, I suppose it is possible to exceed the speed of an array. I would imagine switch uses either less bounds checking or more efficient bounds checking than does an array.

    NoOpArray/set took 953.272654ms
    NoOpArray/get took 891.514622ms
    NormalArray/set took 1235.694953ms
    NormalArray/get took 1148.091061ms
    TenArray/set took 1149.833109ms
    TenArray/get took 1054.040459ms
    NoOpArray/set took 948.458667ms
    NoOpArray/get took 888.618223ms
    NormalArray/set took 1232.554749ms
    NormalArray/get took 1120.333771ms
    TenArray/set took 1153.505578ms
    TenArray/get took 1056.665337ms
    NoOpArray/set took 955.812843ms
    NoOpArray/get took 893.398847ms
    NormalArray/set took 1237.358472ms
    NormalArray/get took 1125.100537ms
    TenArray/set took 1150.901231ms
    TenArray/get took 1057.867936ms
    

    Now whether you can in practice get speeds faster than an array I’m not sure; obviously this way you incur any overhead associated with the interface/class/methods.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Maybe this is just obvious to everyone but can someone explain where XOR (or
Maybe this is a dumb question, but I have the following behavior in Visual
Maybe this cannot be done, but please help or suggest how this can be
Maybe this is something obvious, but here is what I have. I need to
Maybe, i'm duplicating some existing theme (close this one if it's true) but i'm
maybe this is a noob question, but I'm receiving some data over TCP and
Maybe there's no simple answer to this question, but I ask in case someone
maybe this question is a little too general but maybe someone has experience the
Maybe I just don't know .NET well enough yet, but I have yet to
Maybe the need to do this is a 'design smell' but thinking about another

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.