2016-11-19 14 views
0

Я собираюсь измерить производительность некоторого кода. Для этой цели я ввел следующий метод:Запишите результат в volatile var, чтобы исключить удаление мертвого кода в тестах

def timed[T](body: => T) = { 
    val start = System.currentTimeMillis 
    blackHole = body 
    val end = System.currentTimeMillis 
    end - start 
} 

В blackHole переменных введено для того, чтобы сохранить body результат. Это делается для предотвращения удаления кода ошибки от JVM.

В некоторых книгах есть утверждение, что blackHole должен быть объявлен следующим образом:

@volatile 
var blackHole: Any = _ 

Почему следует отметить переменную volatile?

+1

Если ваш метод работает в течение> 1сек., Вы, вероятно, должны использовать инфраструктуру microbenchmark, такую ​​как jmh, см. Http://stackoverflow.com/q/504103/1362755 – the8472

+0

Просьба ссылаться на книгу. И в идеале процитируйте все высказывание, которое вы хотели бы уточнить. Также название вашего вопроса не соответствует хорошо спрошенному здесь вопросу – Ivan

+0

@ the8472 Да, я знаю, но в моем конкретном случае я пытаюсь понять, почему здесь волатильность имеет значение. – Aliaxander

ответ

1

Когда вы запускаете код довольно долго, у вас будет компилятор Just In Time (JIT), вызываемый для частей критического кода. Есть несколько оптимизаций, которые он попытается выполнить.

Исключение мертвого кода. Код не имеет видимых побочных эффектов, его можно удалить.

Вы считаете, что, назначив результат переменной экземпляра, вам сложнее доказать, что значение «не используется». Потенциально кто-то из другого класса/потока может использовать это значение позже.

Летучие компоненты не были действительно необходимы в моем тесте. Один из блогов, которые я читал, упоминал, что JIT может записывать записи для переменных без него (link).

+0

# 2 кажется актуальным, но я не могу найти информацию об этом конкретном типе оптимизации. Не могли бы вы предоставить ссылку? – Aliaxander

+0

это особенно применимо, когда все это выполняется в цикле, компилятор может решить использовать только последний результат выполнения цикла, что, в свою очередь, приводит к тому, что все предыдущие итерации подчиняются DCE. – the8472

+0

@Aliaxander re: # 2, который был в блоге, который я читал в какой-то момент. Я создал небольшой тест, чтобы проверить это, и в моем случае ('build 1.8.0_45-b14') волатильность не была необходима. Ответ Димы может иметь некоторые достоинства в этом вопросе. Я обновлю свой ответ, чтобы исключить эту неподтвержденную часть – Ivan

0

Причина в том, что без изменчивости этот код является таким же мертвым, как и без назначения. Когда вы пишете переменную, не зависящую от времени, результат этой операции не гарантируется, если другие потоки получат доступ к этой переменной. Итак, до тех пор, пока вы не читаете результат в том же потоке, писать никогда не было, насколько это касается внешнего мира.

+0

Кто-то здесь имеет вендетту против меня? :) – Dima