Производительность Java7 System.identityHashCode

Сцена:

  • Я использую XStream, который часто использует System.identityHashCode.
  • Я перешел с IBM Java 1.5 на Oracle Java 7.

Проблема:

Я вижу проблему с производительностью и определил, что System.identityHashCode может быть моей проблемой.

Вопросы:

  • Есть ли хорошее объяснение, почему я наблюдаю такое снижение производительности с более новой Java (и переход от IBM к Oracle)?
  • Как обойти это узкое место?

Ниже приведены мои тесты (все работают на одном и том же оборудовании):

32 bit Oracle Java 7

System.identityHashCode: 517669471 - 51ns
Object.hashCode: 491220730 - 49ns

64 bit Oracle Java 7:

System.identityHashCode: 353134647 - 35ns
Object.hashCode: 339331774 - 33ns

IBM Java 1.5

System.identityHashCode: 19241979 - 1ns
Object.hashCode: 89621026 - 8ns

Исходник программы бенчмарка:

import java.util.*;

public class HashCodeTest
{
  static int ITS = 10000000;
  static Object O = new Object();

  public static void main(String[] args)
  {
    TreeSet<Integer> large = new TreeSet<Integer>();
    Random ran = new Random();
    for (int i=0; i<10000; i++) {
      large.add(ran.nextInt());
    }

    testIdentityHashCode(large);
    testHashCode(large);
    testIdentityHashCode(large);
    testHashCode(large);
  }

  protected static void testIdentityHashCode(TreeSet<Integer> large)
  {
    long start = System.nanoTime();
    for (int i=0; i<ITS; i++) {
      Object o = new Container(large);
      System.identityHashCode(o);
    }
    long end = System.nanoTime();
    System.out.println("System.identityHashCode: " + (end-start) + " - " + (end-start)/ITS + "ns");
  }

  protected static void testHashCode(TreeSet<Integer> large)
  {
    long start = System.nanoTime();
    for (int i=0; i<ITS; i++) {
      Object o = new Container(large);
      o.hashCode();
    }
    long end = System.nanoTime();

    System.out.println("Object.hashCode: " + (end-start) + " - " + (end-start)/ITS + "ns");
  }

  private static class Container {
    private final Object o;

    public Container(Object o)
    {
      this.o = o;
    }
  }
}

person lillesoe    schedule 24.04.2013    source источник


Ответы (1)


Вы видите эту разницу, вероятно, потому, что System.identityHashCode требуется некоторое время для встраивания и/или Object.hashCode для встраивания в ваш метод. Кроме того, вы фактически измеряете время выделения, поскольку создаете экземпляр объекта на каждом этапе цикла.

Попробуй это:

public class HCTests {

static int ITS = 1000;

@Test
public void run() {

    Object[] o = newArray(1000);

    for (int i = 0; i < 10; i++) {
        timeHash(o);
    }

    System.out.println("----------------");

    for (int i = 0; i < 10; i++) {
        timeHash(newArray(1000));
    }

}

private Object[] newArray(int max) {
    Object[] o = new Object[max];

    for (int i = 0; i < o.length; i++) {
        o[i] = new Object();
    }

    return o;
}

private void timeHash(Object[] o) {
    //store the hashes to avoid possible dead-code elimination
    int[] hashes=new int[o.length];
    long start = System.nanoTime();

    for (int j = 0; j < ITS; j++) {
        for (int i = 0; i < o.length; i++) {
            hashes[i]=System.identityHashCode(o);
        }
    }

    long elapsed = System.nanoTime() - start;

    System.out.println("Elapsed " + elapsed + "(ns). Avg: " + (float)elapsed
            / (o.length * ITS));

    for (int i : hashes) {
        if(i==0) {
            System.out.println("Ooops, got 0 hashCode!!!");
        }
    }
}}

Для вывода первого шлейфа у меня получился (Старый Intel Core 2 Duo 2.1GHz)

Прошло 7557271(ns). Среднее: 7,557271
Прошедшее 18508470(нс). Среднее значение: 18,50847

...
Прошло 2026678(нс). Среднее: 2,026678

На второй петле я получил

Истекший 2142041 (ns). Среднее: 2,142041
Прошедшее 1951888(нс). Среднее: 1,951888
Прошедшее 1929891(нс). Среднее: 1,929891
Истекшее 1934779(нс). Среднее: 1,934779
Истекшее 1993438(нс). Среднее: 1,993438
Истекшее 2133732(нс). Среднее значение: 2,133732
Прошедшее 1995882(нс). Среднее: 1,995882
Истекшее 2326329(ns). Среднее: 2,326329
Прошедшее 1939178(ns). Среднее: 1,939178
Прошедшее 2275980(нс). Среднее значение: 2,275981

person user3406200    schedule 11.03.2014