• Новые темы в этом разделе публикуются автоматически при добавлении файла в менеджер ресурсов.
    Ручное создание новых тем невозможно.
Иконка ресурса

Упрощенная библиотека Rnd 1.2

Нет прав для скачивания

Hackness

Путник
Пользователь
Сообщения
64
Розыгрыши
0
Репутация
446
Реакции
85
Баллы
0
Пользователь Hacky разместил новый ресурс:

Упрощенная библиотека Rnd - На основе Math.random

Упрощенная библиотека псевдо-рандома для сервера ла2, построенная на основе Math.random(). Обязательна к установке, если возникают задержки получения результатов случайных операций; если на сервере используется большое количество калькуляций рандома (например использование фантомов); если шансы умений не соответствуют реальности; если просто хотите оптимизации.

+ Сокращает нагрузку на процессор, по сравнению с RandomGenerator
+ Гораздо меньшая и на много более правильная зависимость от...

Узнать больше об этом ресурсе...
 

Птицы пели за окном, молодые пары кружились на набережной в непонятном веселье, но уж точно не в Вихре Мерсенна
Беззаботный апрель... никто не хотел использовать seed и нормальные форматы для архивации файлов
 
Чтобы получить тру рандом можете в коде заменить Math.random() на ThreadLocalRandom.current().nextDouble() но это будет более затратно по производительности.
 
Последнее редактирование:
  • Мне нравится
Реакции: kick
Мне тут на ушко нашептали, что одобрено математиками сего мира и работает быстрее рандома "из коробки".
 
ThreadLocalRandom в данный момент самый быстрый генератор рандомных чисел в явке. Что в однопоточной среде, что в многопоточной (да, самое классное в ThreadLocalRandomе это что он потокобезопасен из коробки). Так что не вижу смысла использовать какие-то другие генераторы, если только вы не сидите на явке 6.

Чтобы получить тру рандом можете в коде заменить Math.random() на ThreadLocalRandom.current().nextDouble() но это будет более затратно по производительности.
Поспорил бы с этим утверждением, но мне пока лень писать бенчмарки, так что просто поверьте на слово. :)
 
Последнее редактирование:
Самому стало интересно, написал несколько небольших бенчмарков.
Процессор i7 3630qm - 4 физических ядра, 8 логических. Компил и запуск через Intellij Idea 15, Java 8, win 10 x64.

Скорость
Описание: за 1 тест получаем 1 000 000 случайных чисел и считаем миллисы, затраченные на генерацию. В случае однопоточного теста всегда ждем окончание предыдущего потока теста с помощью join(), после чего стартуем новый. В случае мультипоточного все тесты запускаются в отдельном потоке одновременно.
Для каждого участника будет выполнено 100 однопточных и многопоточных тестов, после чего рассчитано их среднее время выполнения, которое будет принято за результат (меньше - лучше).

Math.random() - Получение случайного Double числа от 0 до 1:
Single test of millon calculations = 29.0
One-thread test - avg time of million calculations 100 times = 24.59
Multi-thread test - avg time of million calculations 100 times = 21410.09

ThreadLocalRandom.current().nextDouble() - Получение случайного Double числа от 0 до 1:
Single test of millon calculations = 10.0
One-thread test - avg time of million calculations 100 times = 2.19
Multi-thread test - avg time of million calculations 100 times = 18.07
UPD:
Заметил интересную закономерность - чем больше потоков, тем быстрее обработка, так например среднее время генерации в 10 000 потоках равно 2.0901

MersenneTwister.makeDefault().nextDouble() - Получение случайного Double числа от 0 до 1:
Single test of millon calculations = 2861.0
One-thread test - avg time of million calculations 100 times = 2665.28
Multi-thread test - avg time of million calculations 100 times = 49829.57
UPD: В мульти-тред тесте процесс сначала секунд 40 висел, а потом достаточно быстро все рассчитал

В плане производительности бесспорный победитель ThreadLocalRandom


Качество
Описание: качество псевдо-рандома определяется частотой попадания в каждую часть своего диапазона. Например если мы условно поделим Double диапазон [от 0 до 10] на 10 равных частей, то получим одинаковые промежутки [от 0 до 1], [от 3 до 4] и тд. Чем меньше разница между частотой попадания в каждый из этих условных промежутков, тем точнее будет случайная выборка. Т.е. условно 10% на попадание в каждый промежуток. Соответственно Integer выборка псвевдо-рандома от 0 до 1 с 50% шансом должна выводить 1. А в промежутке от 0 до 3 шанс выпадения определенного числа должен быть равен 25%. Более подробно тут
В тесте будет высчитана средняя частота попадания в каждый из 100 промежутков на основании 10 тестов с 1 000 000 000 генераций рандомного числа. После чего средняя частота будет сравниваться с частотой каждого промежутка для получения средней разницы, которая станет результатом (среднее значение от среднего значения, кек). Так же будет рассчитана простая разница между максимальной и минимальной частотой и еще че нить. Для упрощения сгенерированные числа будут домножаться на 100 и конвертироваться в Integer. Обработка будет идти одним потоком. Погрешность ~5%

Math.random():
Avg rate diff = 25.196
Avg rate = 1000.0
Min rate = 911.8
Max rate = 1077.7
Avg rate diff between min & max = 994.75

ThreadLocalRandom.current().nextDouble():
Avg rate diff = 26.032
Avg rate = 1000.0
Min rate = 921.4
Max rate = 1076.9
Avg rate diff between min & max = 999.15

MersenneTwister.makeDefault().nextDouble():
Avg rate diff = 76.4779
Avg rate = 1000.0
Min rate = 771.8
Max rate = 1260.1
Avg rate diff between min & max = 1015.95

С незначительным перевесом побеждает самый простейший Math.random. Что самое интересное - библиотека одобренная математиками имеет в разы более худшую выборку и гораздо больший разброс по частоте использования промежутков по сравнению со стандартными библиотеками явы. Вполне возможно, что это какой-то очень узко-специализированный рандомайзер, но для сервера ла2 ни в плане производительности, ни в плане качества выборки он не подходит.

Выводы: самым оптимальным вариантом будет использование ThreadLocalRandom т.к. на сервере ла2 его производительность будет в разы выше любого рандомайзера при весьма годной выборке.

P.S. Библиотека переведена на ThreadLocalRandom и обновлена.
 

    ツsmile10ツ

    Баллов: 24
    За сообщение

    6yka

    Баллов: 12
    за налимоненое самолбия жавамэна=)

    kick

    Баллов: 30
    Спасибо за в клад в развитие форума
нихрена не понял, но кажись кому то утерли нос....
 
спасибо Hackness , действительно полезная инфа.
 
Круто, хороший ресерч, поставил бы еще один плюс в репутацию, но чертовы лимиты, не дают этого сделать. И да, ты угадал, данная библиотека используется в специфичных вещах, например, в онлайн-казино.

UPD: Кстати, по возможности, добавь еще тестирование SecureRandom или-как-там-его.
 
Hackness выложи тесты а то что-то не верится что разница в скорости НАСТОЛЬКО огромна.
 
Что касается SecureRandom, то он невероятно медленный. Тесты производительности я проводить не стал, т.к. его окончания я бы дождался только к пенсии :eek:
QualityTest на основе 10 тестов со 100 000 повторениями:
Avg rate diff = 25.536
Avg rate = 1000.0
Min rate = 926.3
Max rate = 1076.3
Avg rate diff between min & max = 1001.3
В общем что-то среднее между Math.random и ThreadLocalRandom, а так же очень медленное.

Прикладываю сурс.
UPD: мульти-тред тест в приложенном сурсе на самом деле не мульти-тред. Перед написанием поста моча в голову ударила. В любом случае завтра перепишу его нормально
 

Вложения

  • Test Project.zip
    4,8 МБ · Просмотры: 50
Последнее редактирование:
  • Мне нравится
Реакции: kick

    ItCry

    Баллов: 4
    Спасибо за в клад в развитие форума

    kick

    Баллов: 30
    Спасибо за в клад в развитие форума
Финальная версия бенчмарка. Запилил полноценную платформу для добавления новых тестов (если захотите продолжить), а так же мульти-тред тест теперь ловит ошибки асинхронности при использовании ThreadLocalRandom.
Требуется ява не ниже 8.
 

Вложения

  • Test Project.zip
    4,8 МБ · Просмотры: 61
  • Мне нравится
Реакции: kick и ItCry

    kick

    Баллов: 30
    За сообщение
Hackness увидел что у тебя бенчмарки не на jmh - решил переписать.

И вот результаты:

Score - кол-во потраченных наносекунд на одну операцию
Score error - погрешность

apacheMersenneTwisterRandom - реализация MersenneTwister с библиотеки commons math3
coltMersenneTwisterRandom - реализация MersenneTwister с библиотеки cern
oldRandom - стандартный явовский рандом (java.util.Random)
threadLocalRandom - новый явовский рандом (java.util.concurrent.ThreadLocalRandom)

В многопоточном бенчмарке все рандомы, кроме ThreadLocalRandom, были обернуты в ThreadLocal для потокобезопасности.

Однопоточный бенчмарк
Код:
Benchmark                                                 Mode  Samples  Score  Score error  Units
j.SingleThreadRndBenchmark.apacheMersenneTwisterRandom    avgt       20  4,791        0,164  ns/op
j.SingleThreadRndBenchmark.coltMersenneTwisterRandom      avgt       20  3,373        0,041  ns/op
j.SingleThreadRndBenchmark.oldRandom                      avgt       20  8,598        0,070  ns/op
j.SingleThreadRndBenchmark.threadLocalRandom              avgt       20  1,734        0,054  ns/op

Многопоточный бенчмарк (32 потока)
Код:
Benchmark                                                Mode  Samples   Score  Score error  Units
j.MultiThreadRndBenchmark.apacheMersenneTwisterRandom    avgt       20  57,296        1,888  ns/op
j.MultiThreadRndBenchmark.coltMersenneTwisterRandom      avgt       20  49,314        0,301  ns/op
j.MultiThreadRndBenchmark.oldRandom                      avgt       20  45,541        0,466  ns/op
j.MultiThreadRndBenchmark.threadLocalRandom              avgt       20  13,690        0,133  ns/op


В итоге можно сделать простой вывод: используйте всегда ThreadLocalRandom и не ебите мозг.


Код:
import org.apache.commons.math3.random.MersenneTwister;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class SingleThreadRndBenchmark
{
    private static final Random oldRandom = new Random();
    private static final MersenneTwister apacheMersenneTwisterRandom = new MersenneTwister();
    private static final cern.jet.random.engine.MersenneTwister coltMersenneTwisterRandom = new cern.jet.random.engine.MersenneTwister();

    @Benchmark
    public void threadLocalRandom(Blackhole bh)
    {
        int nextInt = ThreadLocalRandom.current().nextInt();
        bh.consume(nextInt);
    }

    @Benchmark
    public void oldRandom(Blackhole bh)
    {
        int nextInt = oldRandom.nextInt();
        bh.consume(nextInt);
    }

    @Benchmark
    public void apacheMersenneTwisterRandom(Blackhole bh)
    {
        int nextInt = apacheMersenneTwisterRandom.nextInt();
        bh.consume(nextInt);
    }

    @Benchmark
    public void coltMersenneTwisterRandom(Blackhole bh)
    {
        int nextInt = coltMersenneTwisterRandom.nextInt();
        bh.consume(nextInt);
    }

    public static void main(String[] args) throws RunnerException
    {
        Options opt = new OptionsBuilder()
                .include(SingleThreadRndBenchmark.class.getSimpleName())
                .warmupIterations(20)
                .measurementIterations(20)
                .result("result2.txt")
                .resultFormat(ResultFormatType.TEXT)
                .output("log2.txt")
                .build();

        new Runner(opt).run();
    }

}
Код:
import org.apache.commons.math3.random.MersenneTwister;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.results.format.ResultFormatType;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MultiThreadRndBenchmark
{
    private static final ThreadLocal<Random> oldRandom = new ThreadLocal<>().withInitial(Random::new);
    private static final ThreadLocal<MersenneTwister> apacheMersenneTwisterRandom
            = new ThreadLocal<>().withInitial(MersenneTwister::new);
    private static final ThreadLocal<cern.jet.random.engine.MersenneTwister> coltMersenneTwisterRandom
            = new ThreadLocal<>().withInitial(cern.jet.random.engine.MersenneTwister::new);

    @Benchmark
    public void threadLocalRandom(Blackhole bh)
    {
        int nextInt = ThreadLocalRandom.current().nextInt();
        bh.consume(nextInt);
    }

    @Benchmark
    public void oldRandom(Blackhole bh)
    {
        int nextInt = oldRandom.get().nextInt();
        bh.consume(nextInt);
    }

    @Benchmark
    public void apacheMersenneTwisterRandom(Blackhole bh)
    {
        int nextInt = apacheMersenneTwisterRandom.get().nextInt();
        bh.consume(nextInt);
    }

    @Benchmark
    public void coltMersenneTwisterRandom(Blackhole bh)
    {
        int nextInt = coltMersenneTwisterRandom.get().nextInt();
        bh.consume(nextInt);
    }

    public static void main(String[] args) throws RunnerException
    {
        Options opt = new OptionsBuilder()
                .include(MultiThreadRndBenchmark.class.getSimpleName())
                .warmupIterations(20)
                .measurementIterations(20)
                .threads(Runtime.getRuntime().availableProcessors() * 4)
                .forks(1)
                .result("result1.txt")
                .resultFormat(ResultFormatType.TEXT)
                .output("log1.txt")
                .build();

        new Runner(opt).run();
    }

}
 
  • Мне нравится
Реакции: kick, Enmity и zcxv

    zcxv

    Баллов: 19
    За сообщение

    0wn3d

    Баллов: 41
    За сообщение

    kick

    Баллов: 30
    За сообщение
TC-у:

Надеюсь Вы понимаете разницу между псевдослучайными величинами и случайными величинами....
ИМХО: говоря о том, что Ваш рандом покажет "ТРУ" шансы - вы сильно ошибаетесь. Он ничем не лучше. Ибо он тоже ПСЕВДО случайный... На хабре есть много интересных статей по поводу псевдослучайных и случайных величин.

А вот удобнее ли Ваш рандом? Это уже другой вопрос.
 
Последнее редактирование:
TC-у:

Надеюсь Вы понимаете разницу между псевдослучайными величинами и случайными величинами....
ИМХО: говоря о том, что Ваш рандом покажет "ТРУ" шансы - вы сильно ошибаетесь. Он ничем не лучше. Ибо он тоже ПСЕВДО случайный... На хабре есть много интересных статей по поводу псевдослучайных и случайных величин.

А вот удобнее ли Ваш рандом? Это уже другой вопрос.
Ну как бы в топике и шла речь исключительно о псевдо рандоме, что я многократно подчеркивал, так же это написано в документации к каждому из представленных рандомайзеров. Под "тру" шансами я имел ввиду лучшие, чем были, что, кстати, не подтвердилось тестами.
Я уже написал собственное тестирование качества случайной последовательности, лучшие результаты в котором показали Math.random и ThreadLocalRandom (сурс приложен) и вы говорите, что они ничем не лучше?
 
Назад
Сверху Снизу