Мне было любопытно, если мы наконец получим быструю библиотеку datetime с JDK8. Почти все вычисления LocalDate
используют toEpochDay
, поэтому я посмотрел на source, и большое количество подразделений и филиалов мне с любопытством, если бы я мог сделать лучше.Странное падение производительности JDK8 LocalDate.toEpochDay
Я устранил некоторые ветвление и все, но одно деление, однако убыстрение хуже, чем ожидалось. Поэтому мой первый вопрос: как возможно, что алгоритм с использованием множественного деления занимает всего около 30 циклов (пропускная способность). Комментарии Хольгера, кажется, ответили на это: Подразделение по небольшой константе получает JIT-ed для умножения. Я сделал это вручную, и теперь я постоянно избивая первоначальную реализацию с коэффициентом 2.
benchmark довольно просто, просто итерация хотя массив случайных LocalDate
с и преобразования каждого из них toEpochDay
. Несмотря на случайность, results довольно последовательны. Размер массива - это параметр, и мой главный вопрос: , где большое замедление между 2000 и 30000 происходит от. Должно быть некоторое замедление, поскольку данные больше не вписываются в кеш-память L1, но обращения к памяти обоих алгоритмов абсолютно одинаковы (т. Е. Нет, но выбор date
из массива).
Вопрос по-прежнему открытым: Как получается, что поведение двух простых реализаций без доступа к памяти с той же функцией изменяется при итерации по массиву? Исходный алгоритм страдает гораздо более сильным замедлением, чем мой.
В байтекоде нет такой оптимизации (javac ничего не делает в этом отношении). В общем случае '/ 4' не может быть заменено на' >> 2' (потому что это странная семантика разделения округления к нулю, здесь она может быть. Иногда вы можете заменить целочисленное деление на умножение и округление с плавающей запятой, m не уверен, если это поможет.Для общего длинного операнда это, скорее всего, невозможно, потому что 'double' имеет только 56-битную мантиссу. – maaartinus
@maaartinus: если вы посмотрите на код, вы увидите' if (y> = 0) ' прямо перед делениями. Таким образом, JVM может доказать, что дивиденд не является отрицательным в одном случае, поэтому замена '/ 4' на' >> 2' применима, и даже в другом случае он может генерировать правильный код для его исправления, например a '- ((- y) >> 2)' будет делать, если вы знаете, что 'y' является отрицательным. – Holger
Для деления на' 100' нет необходимости использовать с плавающей запятой.Поскольку исходные значения являются «int» и «short», а деление выполняется в «длинном» диапазоне, могут применяться оптимизации «целочисленное деление небольших чисел». [Википедия] (http://en.wikipedia.org/wiki/Division_algorithm#Division_by_a_constant) содержит краткое объяснение концепции. Проще говоря, '/ 100' заменяется на' * X/Y' на 'X' и' Y', так что 'Y' является степенью' 2' и, следовательно, '/ Y' заменяется сдвигом и' X/Y' * достаточно близко * к '0.01' для целых результатов. – Holger