A long
в основном бесплатно.JVM с JIT-компилятором может хранить его в регистре, и, поскольку он является инвариантом цикла, он может даже оптимизировать ваше условие цикла до -timestamp < 600000L - time
или timestamp > time - 600000L
.то есть условие цикла становится тривиальным сравнением между итератором и константой, инвариантной к циклу в регистре.
Так что, да, очевидно, более эффективно вывести вызов функции из цикла и сохранить результат в переменной,особенно когда оптимизатор не может сделать это за вас, и особенно, когда результатом является примитивный тип, а не Object.
Предполагается, что ваш код работает на JVM, который JITs машинный код x86, System.currentTimeMillis()
, вероятно, будет включать по крайней мере инструкцию rdtsc
и некоторое масштабирование этого результата 1 .Таким образом, самое дешевое, что может быть , возможно, (на Skylake, например), - это микрокодированная инструкция с 20 моп с пропускной способностью один на 25 тактов (http://agner.org/optimize/).
Если ваш // Do something
прост, например, несколько обращений к памяти, которые обычно попадают в кэш, или более простые вычисления, или что-то еще, с чем может сработать неправильное выполнение, что может быть большей частью стоимости вашего цикла.Если каждая итерация цикла обычно занимает несколько микросекунд (т. Е. Время для тысяч инструкций на суперскалярном процессоре 4 ГГц), выведение System.currentTimeMillis()
из цикла может, вероятно, иметь ощутимую разницу. Маленькие и огромные будут зависеть от того, насколько просты вашитело цикла имеет вид.
Если вы можете доказать, что удаление его из вашего цикла не вызовет проблем с корректностью, то сделайте это.
Даже если оно находится внутри вашего цикла, вашпоток все еще может бездействовать в течение неограниченного промежутка времени между вызовом его и выполнением работы для этой итерации. Но вывод его из цикла делает его болеевполне вероятно, что вы могли реально наблюдать такой эффект на практике;запускать итерации «слишком поздно».
Сноска 1 : В современном x86 счетчик меток времени работает с фиксированной скоростью, поэтому он полезен в качестве источника времени с низкими издержкамии менее полезен для точного цикла микробенчмаркинга.(Для этого используйте счетчики производительности или отключите турбо / энергосбережение, чтобы тактовая частота ядра = эталонные часы.)
IDK, если JVM фактически столкнется с проблемой реализации собственной функции времени.Он может просто использовать предоставленную ОС функцию времени.В Linux gettimeofday
и clock_gettime
реализованы в пользовательском пространстве (с данными кода + масштабного коэффициента, экспортируемыми ядром в пользовательскую память, в области VDSO ).Так что оболочка glibc просто вызывает это, вместо фактического syscall
.
Так что clock_gettime
может быть очень дешевым по сравнению с реальным системным вызовом, который переключается в режим ядра и обратно.Это может занять не менее 1800 тактов на Skylake в ядре с включенным смягчением Spectre + Meltdown.
Так что да, можно надеяться, можно предположить, что System.currentTimeMillis()
"очень оптимизирован и легок"", но даже rdtsc
само по себе дорого по сравнению с некоторыми телами петель.