Я написал макрос, который сообщает время, необходимое для выполнения данной операции. Он запускает его несколько раз и выводит время для каждого запуска в наносекундах. Первый запуск всегда занимает значительно больше времени, чем последующие. Почему это так?
Вот результаты 10 x 10 прогонов, время Thread.yield()
:
> (dotimes [x 10] (prn (times 10 (Thread/yield))))
[55395 1659 622 561 591 702 795 719 742 624]
[3255 772 884 677 787 634 605 664 629 657]
[3431 789 965 671 774 767 627 627 521 717]
[2653 780 619 632 616 614 606 602 629 667]
[2373 759 700 676 557 639 659 654 659 676]
[2884 929 627 604 689 614 614 666 588 596]
[2796 749 672 769 667 852 629 589 627 802]
[1308 514 395 321 352 345 411 339 436 315]
[1390 363 328 337 330 321 324 347 333 342]
[1461 416 410 320 414 381 380 388 388 396]
Первый запуск первого пакета происходит очень медленно, я думаю, это связано с тем, что JIT впервые видит код - достаточно честно. Но первые запуски во всех последующих пакетах также значительно медленнее, чем последующие запуски. Почему?
Код макроса times
:
(defmacro time
[expr]
`(let [t1# (System/nanoTime)]
~expr
(- (System/nanoTime) t1#)))
(defmacro times
[reps expr]
`(loop [reps# ~reps times# []]
(if (zero? reps#)
times#
(recur (dec reps#) (conj times# (time ~expr))))))
Декомпиляция приводит к следующему результату, поэтому System.nanoTime()
, кажется, вызывается непосредственно перед и после Thread.yield()
, как и предполагалось:
> (decompile (dotimes [x 10] (prn (times 10 (Thread/yield)))))
...
public Object invoke() {
long reps__1952__auto__2355 = 10L;
Object times__1953__auto__2356 = PersistentVector.EMPTY;
while (reps__1952__auto__2355 != 0L) {
final long dec = Numbers.dec(reps__1952__auto__2355);
final IFn fn = (IFn)const__3.getRawRoot();
final Object o = times__1953__auto__2356;
times__1953__auto__2356 = null;
final long t1__1946__auto__2354 = System.nanoTime();
Thread.yield();
times__1953__auto__2356 = fn.invoke(o, Numbers.num(Numbers.minus(System.nanoTime(), t1__1946__auto__2354)));
reps__1952__auto__2355 = dec;
}
final Object o2 = times__1953__auto__2356;
times__1953__auto__2356 = null;
return o2;
}
yield
. - person apangin   schedule 12.02.2018