0
  1. I write an OpenGL app in Java using JOGL. I am trying to completely avoid the creation of objects during the main app's phase as it could lead to the small periodic lag caused by GC.

  2. I want to wrap some JOGL's methods with my own. Imagine a method void method(int[] result, int offset) which receives the pointer to an array and an offset and puts one integer value into it at the specified index. I want to wrap it with simple int getResult()

  3. So I need to create a temporary array somewhere and I must do that in advance (according to 1).

  4. But if it will be stored in a field of the class containing this wrapper method, this will force me to make the wrapper method synchronized. I know that sychronization in time of mostly single-thread access shouldn't produce a big overhead but I still want to know is it there a better solution for this.

Notes:

  • Synchronized is not the answer, 3.000.000 of empty synchronized blocks, just monitorenter-monitorexit take 17 ms. You have only 16.(6) if you want to keep 60 fps.

As I haven't enough power for voting up the only way I found to appreciate Dave's answer is writting a demo:

class Test {
    private static final int CYCLES = 1000000000;

    int[] global = new int[1];
    ThreadLocal<int[]> local = new ThreadLocal<int[]>();

                 void _fastButIncorrect() { global[0] = 1; }
    synchronized void _slowButCorrect()   { global[0] = 1; }

    void _amazing()   {
        int[] tmp = local.get();
        if( tmp == null ){
            tmp = new int[1];
            local.set(tmp);
        }
        tmp[0] = 1;
    }

    long fastButIncorrect() {
        long l = System.currentTimeMillis();
        for (int i = 0; i < CYCLES; i++) _fastButIncorrect();
        return System.currentTimeMillis() - l;
    }
    long slowButCorrect() {
        long l = System.currentTimeMillis();
        for (int i = 0; i < CYCLES; i++) _slowButCorrect();
        return System.currentTimeMillis() - l;
    }
    long amazing() {
        long l = System.currentTimeMillis();
        for (int i = 0; i < CYCLES; i++) _amazing();
        return System.currentTimeMillis() - l;
    }
    void test() {
        System.out.println(
                        "fastButIncorrect cold: " + fastButIncorrect() + "\n" +
                        "slowButCorrect   cold: " + slowButCorrect()   + "\n" +
                        "amazing          cold: " + amazing()          + "\n" +
                        "fastButIncorrect  hot: " + fastButIncorrect() + "\n" +
                        "slowButCorrect    hot: " + slowButCorrect()   + "\n" +
                        "amazing           hot: " + amazing()          + "\n"
        );
    }
    public static void main(String[] args) {
        new Test().test();
    }
}

on my machine the results are:

fastButIncorrect cold: 40
slowButCorrect   cold: 8871
amazing          cold: 46
fastButIncorrect  hot: 38
slowButCorrect    hot: 9165
amazing           hot: 41

Thanks again, Dave!

7
  • 3
    1. sounds like a seriously premature concern. Commented Nov 8, 2013 at 21:12
  • @MattBall's comment is spot on. Do you have profiler output that shows the GC lag? Unless you have a decent level of object bandwidth, that should not be an issue. Commented Nov 8, 2013 at 21:14
  • Please avoid discussing the nature of the question. Isn't there a solution for doing this without synchronization and without object creation? Commented Nov 8, 2013 at 21:22
  • Why not create one wrapper per thread? Is this a problem at all -- is the rendering itself multi-threaded? Does Jogl support this at all? Commented Nov 8, 2013 at 21:44
  • @StefanHaustein Probably it is the best solution but it will slightly change the architecture. Commented Nov 8, 2013 at 21:55

1 Answer 1

4

If you don't have too many threads, you can use a ThreadLocal:

ThreadLocal<int[]> tmpArrayThreadLocal = new ThreadLocal<int[]>();

code to use this:

int[] tmpArray = tmpArrayThreadLocal.get();
if( tmpArray == null ){
   tmpArray = new int[100];
   tmpArrayThreadLocal.set(tmpArray);
}
method(tmpArray, 5)

You could clean up the code by encapsulating the ThreadLocal in another class.

Sign up to request clarification or add additional context in comments.

3 Comments

Do you know how the performance impact? You'd need to do this for each call, right?
I have tested and the performance is great! I've checked how did they implement that and seems that they are storing the data in the Thread itself and using fixed simple offset in the array. So it is what I wanted! Thank you very much for the answer, I am googling about that class - never heard about it but it looks very useful and promising.
Just be careful about the number of threads you create as this data wouldn't be garbage collected until the thread ends.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.