Вопрос

я ранее комментировал этот вопрос («Почему java.lang.Object не является абстрактным?»), заявив, что я слышал об этом, используя byte[0] поскольку замок был немного более эффективным, чем использование java.lang.Object.Я уверен, что где-то это читал, но не могу вспомнить где:Кто-нибудь знает, правда ли это на самом деле?

Я подозреваю, что это связано с созданием экземпляра byte[0] требуя немного меньше байт-кода, чем Object, хотя было указано, что byte[0] требуется дополнительное хранилище для хранения поля длины, и поэтому похоже, что это может свести на нет любую выгоду.

Это было полезно?

Решение

Мне стало достаточно любопытно, чтобы проверить это.Исходный код:

public class Test {
    public static Object returnObject() {
        return new Object();
    }

    public static byte[] returnArray(){
        return new byte[0];
    }
}

Байт-код:

public static java.lang.Object returnObject();
  Code:
   0:   new     #2; //class java/lang/Object
   3:   dup
   4:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   7:   areturn

public static byte[] returnArray();
  Code:
   0:   iconst_0
   1:   newarray byte
   3:   areturn

Итак, вы правы в том, что байт-код для массивов короче, поскольку создание массива имеет собственный код операции JVM.Но что это значит?Не важно.Это виртуальная машина, поэтому нет абсолютно никакой гарантии, что меньшее количество инструкций байт-кода означает меньше работы для реального физического процессора.Конечно, можно было бы начать профилирование, но это было бы совершенно бессмысленно.Если вообще существует разница, независимо от того, в какой степени, она никогда не будет иметь значения.В наши дни создание объектов происходит невероятно быстро.Вероятно, вам придется начать использовать long для вашего индекса цикла, прежде чем вы сможете даже измерить общее время.

Другие советы

Использование java.lang.instrument.Instrumentation для проверки размеров:
Объект использует 8 байт, для byte[0] требуется 16 байт.(не уверен, что размер указан в байтах, не документировано).

У меня также было время создать объект и байт[0] (2 раза):Объект является победителем.

(все тесты проводились на ноутбуке DELL, Intel 2 ГГц, Windows XP)

Используя client ВМ

java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Client VM (build 14.2-b01, mixed mode)

an implementation-specific approximation of the amount of storage
Object  = 8
byte[0] = 16

time to create 1000000000 instances
Object:  elapsed=11,140   cpu=9,766    user=9,703    [seconds]
byte[0]: elapsed=18,248   cpu=15,672   user=15,594   [seconds]

time to create 1000000000 instances
Object:  elapsed=11,135   cpu=9,828    user=9,750    [seconds]
byte[0]: elapsed=18,271   cpu=15,547   user=15,469   [seconds]

Используя server ВМ

java version "1.6.0_16"
Java(TM) SE Runtime Environment (build 1.6.0_16-b01)
Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)

an implementation-specific approximation of the amount of storage
Object  = 8
byte[0] = 16

time to create 1000000000 instances
Object:  elapsed=8,441    cpu=7,156    user=7,125    [seconds]
byte[0]: elapsed=11,237   cpu=8,609    user=8,500    [seconds]

time to create 1000000000 instances
Object:  elapsed=8,501    cpu=7,234    user=7,156    [seconds]
byte[0]: elapsed=11,023   cpu=8,688    user=8,641    [seconds]

я останусь с new Object(), не только из-за читаемости :-)

Код

public class ObjectArrayCompare {

  private static Object o;

  public static void main(String[] args) {
    Instrumentation instr = InstrumentationAgent.getInstrumentation();
    if (instr == null) {
        System.err.println("No Instrumentation, use \"-javaagent:Instrumentation.jar\"");
        return;
    }
    System.out.println();
    System.out.println("an implementation-specific approximation of the amount of storage");
    System.out.println("Object  = " + instr.getObjectSize(new Object()));
    System.out.println("byte[0] = " + instr.getObjectSize(new byte[0]));
    System.out.println();

    final int MAX = (int) 1.0e9;
    Timer timer;
    Times times;

    for (int j = 0; j < 2; j++) {
      System.out.println("time to create " + MAX + " instances"); 
      timer = new Timer();
      for (int i = 0; i < MAX; i++) {
        o = new Object();
      }
      times = timer.times();
      System.out.println("Object:  " + times);

      timer = new Timer();
      for (int i = 0; i < MAX; i++) {
        o = new byte[0];
      }
      times = timer.times();
      System.out.println("byte[0]: " + times);

      System.out.println();
    }
  }
}

Таймер* использует ThreadMXBean чтобы узнать время.

* Таймер — это класс, который я создал для синхронизации. нет один из таймеров Java.

СогласноСпецификация языка Java, «все типы классов и массивов наследуют методы класса Object», поэтому я не знаю, как byte[0] может быть более эффективным.

Кажется, это верно для первое издание спецификации также:«Суперклассом типа массива считается Object».

ИМХО, использование массива скорее запутает читателя.

Создание меньшего количества объектов более эффективно, чем создание большего, поэтому, если когда-либо было создано достаточно объектов, которые имели значение, вы создаете слишком много.

Шаблон использования пустого массива в Java в качестве объекта блокировки имеет мало общего с производительностью.

Пустые массивы (даже new Object[0]) предпочтительнее, поскольку они сериализуемы.Используя new Object() вы отказываетесь от автоматической сериализации.

Я привык делать (никогда не заботясь о производительности):

private final Object lock = new Object[0];

Для создания примитивных массивов требуется меньше байт-кода, так что, возможно, new byte[0] было бы лучше".

Видеть: Можно ли сделать временную блокировку для сериализуемого класса?

В вашем вопросе упоминается «эффективность», но не говорится, какая эффективность вам нужна.Ответы на данный момент касаются размер объектов, но затраты времени выполнения на разыменование и использование встроенной блокировки в любом представлении должны быть одинаковыми.

Вы также можете сравнить накладные расходы на использование встроенных блокировок с использованием java.util.concurrent.locks.ReentrantLock явно или тот, который вы сами пишете поверх AbstractQueuedSynchronizer.Если вы можете допустить дополнительную ссылку на отдельно выделенный объект, для оценки требуется более подробная информация о вашей проблеме, но учитывая, что вы уже рассматриваете возможность byte массивы, вы должны рассмотреть возможность использования внутренней блокировки, отличной от вашей this ссылка.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top