Drools Fusion: измерение производительности

Я хочу измерить производительность drools на основе количества правил и сложности правил. Поэтому мне нужно измерить время, необходимое для обработки событий. Я хочу написать простой тест следующим образом:

long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
    insertHeartRate(150, 0, macAddress);
    ksession.fireAllRules();
}
long stop = System.currentTimeMillis();
System.out.println("Running time: " + (stop - start));

Проблема, с которой я столкнулся, заключается в том, что это не работает, поскольку вы можете вставлять столько событий, сколько хотите, и слюни будут обрабатывать их позже. Таким образом, время этой части всегда меньше секунды, очевидно. Итак, мой вопрос: как я могу вызвать long stop = System.currentTimeMillis() после обработки всех событий?


person Tim    schedule 25.04.2016    source источник


Ответы (1)


fireAllRules возвращается после того, как все произошло. Таким образом, опубликованный вами код действительно будет измерять время, прошедшее для вставки этих событий и запуска всех сработавших правил.

Если ваши правила запускают какие-либо таймеры, которые будут выполняться позже: это другое дело. Кроме того, вы обращаетесь к Fusion: эти события не будут поступать в соответствии с жесткой петлей, а временные метки и операторы окна: время и темпоральные: ничто не будет работать так, как ожидалось в ваших правилах.

Если временные операторы или окно: время отсутствуют, вы можете измерить время, необходимое для первой вставки фактов, и измерить продолжительность действия fireAllRules.

Все сильно зависит от поведения Java JIT, GC и некоторых деталей вашего процессора...

Изменить После просмотра вашего кода я могу добавить еще одну рекомендацию. Убедитесь, что у вас есть последовательная последовательность событий, включающая вставки и выполнение правил. Либо запустить все — вставки и fireAllRules, один раз, либо повторно — в одном потоке и замерить время до и после. Или запустите fireUntilHalt в одном потоке, измерьте время и вставьте в другой поток. Теперь, чтобы увидеть, когда все стихло после последней вставки, вам придется что-то сконструировать, чтобы поймать этот момент. Одним из способов было бы вставить какой-то особый факт, запустить правило с очень низкой заметностью и измерить время окончания по его следствию.

person laune    schedule 25.04.2016
comment
Я использую окно: время. Я сделал то же самое с Esper (еще один движок cep), и там этот цикл работает, хотя я также использую win:time. Одно из решений, которое пришло на ум, — вставить событие после всех остальных, запускающих определенное правило, и выполнить long stop = System.currentTimeMillis(); при срабатывании этого правила. Но я предпочитаю избегать этого, есть ли другой способ? - person Tim; 25.04.2016
comment
Ничего не должно происходить после возврата из fireAllRules. - person laune; 25.04.2016
comment
Хорошо, но как мне измерить время выполнения, когда есть правила с окном: время? При выполнении fireAllRules требуется много времени, пока все события не будут обработаны. Это то, что я хочу измерить. Как я могу этого добиться? - person Tim; 25.04.2016
comment
Когда вы вставляете события в drools и выполняете fireallrules, должен быть какой-то другой поток, который обрабатывает эти события? Не могли бы вы измерить, когда эта нить закончилась? - person Tim; 28.04.2016
comment
Все, что вам нужно, это (один) поток, вставляющий события и вызывающий fireAllRules. Обработка событий, выходящих за рамки этого, больше не Drools. - person laune; 28.04.2016
comment
Хорошо, тогда я хочу измерить обработку событий после этого, как это происходит, как мне это сделать? - person Tim; 28.04.2016
comment
Я не понимаю, что вы имеете в виду. Почему последствия ваших правил не могут решить вопрос? - person laune; 28.04.2016
comment
Когда я измеряю производительность с помощью Esper и вставляю 1000 событий, для их обработки требуется 2500 миллисекунд. Когда я делаю это с Drools Fusion и следую вашему предложению по измерению (поэтому мой исходный код в моем вопросе), это занимает всего 95 миллисекунд, что невозможно, поскольку drools медленнее, чем Esper. Кроме того, правила все еще запускаются после того, как я напечатаю свой Running time, который указывает, что Drools не закончил обработку событий. Я использую только window.time и не использую таймеры, поэтому это не должно быть проблемой, почему Drools запускает события. - person Tim; 28.04.2016
comment
Согласно javadoc, неограниченный fireAllRules не возвращается до тех пор, пока не будут разработаны все ожидающие активации. Если вы можете составить демонстрацию, подтверждающую ваше утверждение (т. е. правила все еще срабатывают после последнего возврата), я могу продолжить рассмотрение вопроса, зарегистрировав ошибку. Отредактируйте необходимые правила и приложение Java в своем вопросе, и я возьму его оттуда. - person laune; 29.04.2016
comment
Спасибо! Вот ссылка на Dropbox, где вы можете скачать мой исходный код. Код можно запустить из основного класса в тестовом пакете: dropbox. com/s/at6clhqz1y2k0jb/DroolsSpeedTest.zip?dl=0 - person Tim; 30.04.2016
comment
Код представляет собой клубок. Вы создаете сеанс и запускаете поток, выполняющий fireUntilHalt, затем вставляете факты и вызываете fireAllRules в другом потоке, и именно здесь вы измеряете время, в результате чего получается 225 мс. Но правила будут срабатывать асинхронно в потоке, в котором запущен fireUntilHalt, поэтому весь вывод кода RHS происходит после отображения 225. Просто закомментируйте начало потока, и тогда fireAllRules будет контролировать выполнение правила, и время будет 656 мс, напечатанное после всех сообщений. - Я добавил несколько хороших советов к моему ответу. - person laune; 30.04.2016
comment
Да, действительно, это была проблема. Спасибо! Последний вопрос, который вы сказали: Кроме того, вы обращаетесь к Fusion: эти события не будут поступать в соответствии с жесткой петлей. Могу ли я сделать так, чтобы эти события поступали по замкнутому циклу? - person Tim; 30.04.2016
comment
Если (что характерно для Fusion) события поступают в режиме реального времени, измерить производительность практически невозможно — вы не сможете измерить множество коротких действий из-за детализации системных часов, по крайней мере, с достаточной точностью. Но если вы передаете события в жестком цикле, вам придется явно устанавливать временные метки и соответствующим образом продвигать псевдотаймер, запуская все в промежутке времени. - person laune; 01.05.2016