На assert явным образом есть отсылка в авторском разборе:
Вадим же человек аккуратный (вы посмотрите, сколько assertов!), значит, комментарий к методу он тоже написал аккуратно, а там указано, что метод вернет число в интервале от 0 до partitions исключительно.
У читателей может сложиться ложное впечатление, что это best practice, не так ли?
А вот тут
Другая, более серьезная проблема Вадима гораздо менее очевидна. Способ, который он выбрал, чтобы распределять данные по серверам, неконсистентен: при изменении количества партиций (например, при добавлении серверов) все треки перераспределяются по кластеру практически полностью.
ничего нет про поведение Object.hashCode(), а именно про его невоспроизводимость. Последнее, опять же на мой взгляд, куда большая проблема, чем изменение количество шардов, т.к. их количество может измениться либо вследствие сбоев, либо намеренного изменения (см. отсылки к Elasticsearch или MongoDB), в то время как hashCode на разных серверах для одних и тех же объектов уже будет давать разные результаты. Это важно.
Первая книга выпускалась издательством со своими заморочками по цензуре, редактуре. Плюс ко всему прочему — издательство получает определённые права на книгу, например, её нельзя будет просто так взять и переиздать в другом издательстве или опубликовать в свободный доступ (Milfgard об этом как раз писал либо в постах по ссылкам выше, либо в комментариях к этим же статьям).
Я же пишу про альтернативный вариант, который сложнее для автора, но имеет ряд преимуществ.
Только не связывайтесь с издательствами — зачем лишняя головная боль с цензурой и правами, которые отходят издателю?
В компании же есть хорошие дизайнеры, которые смогут самостоятельно сверстать книгу?
А печать уже делать в типографии. Был опыт издания книг небольшим тиражом в Екатеринбурге (за отдельную плату можно получить ISBN) — могу рассказать, как это происходит.
Отправил соответствующий баг в Oracle по странному различию в производительности по сути идентичного кода (см. FinalOrNotFinalBenchmark). Сегодня подтвердили баг: JDK-8200412.
В общем случае, когда операнды типа float/double, FPU прекрасно посчитает x^y как 2^(y*log(x)) (при условии, что x > 0). Правда, FYL2X (y*log(x)) раз в 20-40 дороже умножения/деления в зависимости от архитектуры. Но выигрыш будет заметен на больших степенях.
Насколько мне известно, цепочка получается подлиннее (даже без учёта перекомпиляции из C1 в C2): java -> bytecode -> IR -> native code (~ машинные коды).
И еще одно — лобовая реализация описанного в ассемблере скорее всего будет эффективнее
В конкретном примере из статьи (и во многих других) — да. Но не стоит недооценивать умение JIT-компилятора учитывать собираемый профиль (= учитывать реальное исполнение кода, реальные данные в нашем приложении).
К сожалению, у меня нет под рукой этой книги, но готов поспорить, что там нет ничего про интринсики в Java, как и нет информации о том, как реализовано возведение в степень в HotSpot 7 / 8 / 9.
Впрочем, всё это не отменяет того факта, что
в 90% случаев достаточно использовать подходящие структуры данных и алгоритмы.
Видимо, принцип «скомпилируй, посмотри сгенерированный код» до сих пор актуален.
И ещё мини вывод: знание ассемблера нужно.
Это в полной мере справедливо для C++, т.к. AOT-компилятор. С Java всё намного сложнее, т.к. в JIT-компиляторе огромное количество оптимизаций, а их применение зависит от собранного профиля. Последнее означает, что результат JIT-компиляции может отличаться не только между кодом реального приложения и бенчмарка, так и в разные запуски приложения, да даже в разные моменты времени в одном запущенном приложении.
Пример:
В некотором коде может произойти NullPointerException, но в течение сбора профиля оно ни разу не случалось, поэтому JIT-компилятор C2 скомпилировал только так называемый common case — код, который исполняется часто, а остальную часть кода (обработка NPE в данном случае) не скомпилировал вовсе, оставив так называемую uncommon trap. Если в какой-то момент возникнет NullPointerException, то HotSpot вынужден будет откатиться в режим интерпретатора для этого участка кода, а в результате получить деоптимизацию всего метода. Когда JIT-компилятор вновь решится компилировать код и как он это сделает — предсказать мне невозможно.
Кажется, что в 90% случаев достаточно использовать подходящие структуры данных и алгоритмы. В связи с чем могу порекомендовать книги Лафоре (Структуры данных и алгоритмы в Java) и Седжвика (Алгоритмы на Java).
Ещё в 9% случаев нужно копать в сторону эффективности используемых фреймворков и тулкитов.
Оставшийся 1% бизнесу, как правило, не интересен.
Конечно, всё зависит от задач. Но если брать среднюю температуру по больнице, предположение выше не так уж далеко от истины.
Такой исходный код:
компилируется в
У читателей может сложиться ложное впечатление, что это best practice, не так ли?
А вот тут
ничего нет про поведение
Object.hashCode()
, а именно про его невоспроизводимость. Последнее, опять же на мой взгляд, куда большая проблема, чем изменение количество шардов, т.к. их количество может измениться либо вследствие сбоев, либо намеренного изменения (см. отсылки к Elasticsearch или MongoDB), в то время какhashCode
на разных серверах для одних и тех же объектов уже будет давать разные результаты. Это важно.Вызов принят! Лучшие-нелучшие, но есть, что обсуждать. :)
Спасибо!
Надо будет поизучать этот вопрос. Неспроста же есть ключик
-XX:UseAVX
...К тому же много кто предпочитает бумажные книги.
Попробовал ещё в SIMD (независимые вычисления, простые циклы) — тоже безрезультатно.
Вывод: либо JIT-компилятор в это не умеет, либо я неправильно его готовлю.
Я же пишу про альтернативный вариант, который сложнее для автора, но имеет ряд преимуществ.
В компании же есть хорошие дизайнеры, которые смогут самостоятельно сверстать книгу?
А печать уже делать в типографии. Был опыт издания книг небольшим тиражом в Екатеринбурге (за отдельную плату можно получить ISBN) — могу рассказать, как это происходит.
FinalOrNotFinalBenchmark
). Сегодня подтвердили баг: JDK-8200412.Android — это вообще отдельный мир со своим байткодом и VM (Dalvik / ART) со своим JIT'ом.
Нет. В Java вычисления с плавающей точкой реализованы в соответствии со стандартом IEEE 754. Это явно указано в javadoc к
java.lang.StrictMath
.Напротив,
--ffast-math
допускает использование оптимизаций, нарушающих указанный стандарт.В какую именно? Заменять
a * a * ... * a
, как это сделано в примере? Так это не совсем законно (нарушает лево-ассоциативность операции умножения).Насколько дорого ходить в JNI — можно прикинуть, если сравнить бенчмарки с интринсиком и без (последний бенчмарк).
float/double
, FPU прекрасно посчитаетx^y
как2^(y*log(x))
(при условии, чтоx > 0
). Правда,FYL2X
(y*log(x)
) раз в 20-40 дороже умножения/деления в зависимости от архитектуры. Но выигрыш будет заметен на больших степенях.В конкретном примере из статьи (и во многих других) — да. Но не стоит недооценивать умение JIT-компилятора учитывать собираемый профиль (= учитывать реальное исполнение кода, реальные данные в нашем приложении).
Впрочем, всё это не отменяет того факта, что
Это в полной мере справедливо для C++, т.к. AOT-компилятор. С Java всё намного сложнее, т.к. в JIT-компиляторе огромное количество оптимизаций, а их применение зависит от собранного профиля. Последнее означает, что результат JIT-компиляции может отличаться не только между кодом реального приложения и бенчмарка, так и в разные запуски приложения, да даже в разные моменты времени в одном запущенном приложении.
Пример:
В некотором коде может произойти
NullPointerException
, но в течение сбора профиля оно ни разу не случалось, поэтому JIT-компилятор C2 скомпилировал только так называемый common case — код, который исполняется часто, а остальную часть кода (обработкаNPE
в данном случае) не скомпилировал вовсе, оставив так называемую uncommon trap. Если в какой-то момент возникнетNullPointerException
, то HotSpot вынужден будет откатиться в режим интерпретатора для этого участка кода, а в результате получить деоптимизацию всего метода. Когда JIT-компилятор вновь решится компилировать код и как он это сделает — предсказать мне невозможно.Ещё в 9% случаев нужно копать в сторону эффективности используемых фреймворков и тулкитов.
Оставшийся 1% бизнесу, как правило, не интересен.
Конечно, всё зависит от задач. Но если брать среднюю температуру по больнице, предположение выше не так уж далеко от истины.