如何避免同步和对象创建?

时间:2013-11-08 21:11:24

标签: java performance concurrency logic

  1. 我使用JOGL在Java中编写OpenGL应用程序。我试图完全避免在主应用程序阶段创建对象,因为它可能导致GC导致的小周期延迟。

  2. 我想用自己的方法包装一些JOGL的方法。想象一个方法void method(int[] result, int offset),它接收指向数组和偏移量的指针,并在指定的索引处将一个整数值放入其中。我想用简单的int getResult()

  3. 来包装它
  4. 所以我需要在某处创建一个临时数组,我必须提前做到(根据1)。

  5. 但是如果它将存储在包含此包装器方法的类的字段中,这将迫使我创建包装器方法synchronized。我知道大多数单线程访问的时间同步不应该产生很大的开销,但我仍然想知道它是否有更好的解决方案。

  6. 注意:

    • 同步不是答案,3.000.000的同步块,只需monitorenter-monitorexit需要17 ms。你只有16(6)如果你想保持60 fps。

    由于我没有足够的权力投票,我发现欣赏Dave的唯一方法就是写一个演示:

    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();
        }
    }
    
    在我的机器上

    结果是:

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

    再次感谢,戴夫!

1 个答案:

答案 0 :(得分:4)

如果没有太多线程,可以使用ThreadLocal:

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

使用此代码的代码:

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

您可以通过将ThreadLocal封装在另一个类中来清理代码。