Как правильно сравнить стоимость «&» и «%» с помощью JMH

Итак, вот простая вещь, которую я пытаюсь проверить, что быстрее операция мода или операция И (при условии степени двойки) - это то, что hashMap делает внутри. Это правильно пишется "испытание"? Я должен признать, что внутренности jmh и написать правильный микротест после прохождения всех образцов (думаю, в третий раз) — довольно сложная задача. :)

   @State(Scope.Thread)
@BenchmarkMode(org.openjdk.jmh.annotations.Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MeasureSpeedModuleVsAnd {

    public static void main(String[] args) throws Exception {
        Options opt = new OptionsBuilder()
                .include(MeasureSpeedModuleVsAnd.class.getSimpleName())
                .forks(1)
                .warmupIterations(1)
                .measurementIterations(5)
                .warmupTime(TimeValue.seconds(2))
                .build();

        new Runner(opt).run();

    }

    @Param({ "16", "32", "256", "1048576" /* 2 power of 10 */ })
    public int number_of_buckets;

    @Param({ "345984", "123456", "111", "98653" })
    public int hashcode;

    @Benchmark
    public int benchamark_modulo() {
        return hashcode % number_of_buckets;
    }

    @Benchmark
    public int benchmark_and() {
        return (number_of_buckets - 1) & hashcode;
    }
}

person Eugene    schedule 17.02.2016    source источник
comment
Ну конечно нет, arg % 33 != (arg - 1) & 33. Возьмите 42 в качестве примера...   -  person Aleksey Shipilev    schedule 17.02.2016
comment
Вы хотели написать arg % 32 и arg & (32 - 1)?   -  person Tagir Valeev    schedule 18.02.2016
comment
@AlekseyShipilev полностью мой плохой, скопировал неправильный код.   -  person Eugene    schedule 19.02.2016
comment
@Eugene: извини, но КАКОГО ЧЕРТА. 32453667 % arg это настоящая хэш-функция? (arg - 1) & 32453667 что должен делать? 32453667 не является ни простым числом, ни степенью двойки, ни степенью двойки минус один. Какая. . Ад. Я в замешательстве.   -  person Aleksey Shipilev    schedule 19.02.2016
comment
@AlekseyShipilev Я вообще не говорю о хэш-функции. (n-1) & hash семантически одно и то же hash % n; если n равно степени двойки, результат для положительных чисел будет таким же. вот как выбирается ведро в hashmap, все, что я хотел проверить, это разницу в скорости этих двух. Теперь я тот, кто сбит с толку.   -  person Eugene    schedule 20.02.2016
comment
Но в вашем коде он вызывается как arg, а не по модулю, как это, по-видимому, и есть. А замена операндов на & только добавляет путаницы. hash % modulo = hash & (modulo - 1), если по модулю действительно степень двойки.   -  person Aleksey Shipilev    schedule 21.02.2016
comment
Я также не понимаю, как вы кувыркаетесь между созданием константы по модулю в предыдущей версии и теперь сам хеш является константой? В реальных случаях HashMap ни один из них не является постоянным.   -  person Aleksey Shipilev    schedule 21.02.2016
comment
@AlekseyShipilev это взято из хэш-карты, но не проверяет фактическую хэш-карту. Это простое вычисление разницы скоростей. Меня главным образом интересовала правильность фактической настройки jmh.   -  person Eugene    schedule 21.02.2016
comment
А я вам говорю: тесты с постоянными хэшами отличаются от тестов с постоянными модулями и отличаются от тестов с непостоянными хэшами и модулями. Каждый из этих вариантов верен в том смысле, что он что-то измеряет. Но измеряют ли они то, что вы действительно хотите измерить? Только ты можешь ответить. Если вы не уверены, попробуйте все из них. И под попыткой я подразумеваю измерение и анализ того, что происходит, и почему они дают разные/одинаковые результаты.   -  person Aleksey Shipilev    schedule 21.02.2016
comment
@AlekseyShipilev отличный комментарий! Вы действительно должны сделать это ответом; это то, что я хотел услышать. Благодарю вас!   -  person Eugene    schedule 21.02.2016


Ответы (1)


Подробно об этом рассказывается в этом сообщении в блоге: http://psy-lob-saw.blogspot.co.za/2014/11/the-mythical-modulo-mask.html

Ваш тест не работает (сравнивая то, что кажется нерелевантным количеством), потому что вы сравниваете (non_final_field и константу) с (constant % non_final_field). Замените на (non_final_field1 % non_final_field2) и (non_final_field1 & (non_final_field2-1)) где non_final_field2 — степень числа 2.

В контексте HashMap значение используется для чтения из массива, и сообщение в блоге также охватывает последствия этой стороны.

person Nitsan Wakart    schedule 22.02.2016