Объект против байта [0] как блокировки
-
22-09-2019 - |
Вопрос
я ранее комментировал этот вопрос («Почему 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
ссылка.