Мы часто видим людей, использующих сценарии (например, в служебной задаче, слушателе выполнения и т. Д.) Для различных целей. Использование сценариев против логики Java часто имеет смысл:
- Это не должно быть упаковано в банку и помещено в путь к классу
- Это делает определение процесса более понятным: нет необходимости просматривать разные файлы
- Логика является частью определения процесса, что означает отсутствие хлопот, чтобы убедиться, что используется правильная версия логики
Однако важно также учитывать аспект производительности использования сценариев в определении процесса и сбалансировать эти требования с указанными выше преимуществами.
Два языка сценариев, которые мы обычно видим при использовании Activiti, — это Javascript и Groovy. Javascript поставляется в комплекте с JDK ( Rhino для JDK 6 и 7) и Nashorn для JDK 8, что позволяет легко подобрать. Для Groovy необходимо добавить механизм сценариев Groovy в classpath.
Но позвольте мне сказать вам, что я не фанат использования Javascript в качестве языка выбора сценариев, так как при переходе между версиями JDK происходят небольшие изменения (подробнее об этом читайте в предыдущем посте, здесь и здесь , и это те, которые были задокументировано…). Таким образом, это означает, что вы могли бы написать свою логику в один прекрасный день, и все это сработало, а на следующий день после обновления JDK все это не удалось. Я скорее трачу свое время на собственно кодирование.
Для проверки производительности я сделал очень маленький микробенчмарк:
и где скрипт делал что-то глупое (смысл был в том, чтобы там были getVariable () и setVariable () и что-то еще, например, получение текущего дня):
1
2
3
|
var input = execution.getVariable(‘input’); var today = new Date().getDay(); execution.setVariable(‘result’, input * today); |
Тот же код в задаче службы Java:
1
2
3
4
5
6
7
8
9
|
public class MyDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) throws Exception { Integer input = (Integer) execution.getVariable( "input" ); int today = Calendar.getInstance().get(Calendar.DAY_OF_MONTH); execution.setVariable( "result" , input * today); } } |
и Groovy аналог:
1
2
3
|
def input = execution.getVariable( 'input' ); int today = Calendar.getInstance().get(Calendar.DAY_OF_MONTH); execution.setVariable( 'result' , input * today); |
Я запустил этот экземпляр процесса 10.000 раз и просто записал общее время выполнения, думаю, цифры говорят сами за себя:
- JavaDelegate : 6255 мс
- Groovy : 7248 мс
- Javascript : 27314 мс
Используемая версия JDK была последней версией (1.8.0_60). В первый раз, когда я запускал тесты, я был на 1.8.0_20, и результаты Javascript были на 25% выше (я читал, что улучшения производительности были в JDK 1.8.0_40). Для Groovy я использовал версию 2.4.4 (которую вы должны использовать, так как старые версии имеют проблемы с безопасностью !)
Просто чтобы наглядно представить разницу между вариантами:
Использование Groovy для языка сценариев кажется гораздо лучшим выбором по сравнению с использованием Javascript. Учтите, что это микробенчмарк для одного очень простого варианта использования. Но, учитывая наши проблемы в прошлом с обновлениями JDK, которые нарушают сценарии Javascript, и этот результат, очень трудно обосновать выбор Javascript по умолчанию.
ОБНОВЛЕНИЕ 11 СЕНТЯБРЯ ’15: Довольно много людей спрашивали меня, почему разница столь велика . Я предполагаю, что это потому, что движок javascript в JDK не является потокобезопасным и, следовательно, не может быть повторно использован или кэширован, что каждый раз приводит к дорогостоящей загрузке ScriptingEngine. Если вы посмотрите на http://docs.oracle.com/javase/7/docs/api/javax/script/ScriptEngineFactory.html , вы можете прочитать, что есть специальный параметр THREADING, который мы используем в Activiti: https : //github.com/Activiti/Activiti/blob/master/modules/activiti-engine/src/main/java/org/activiti/engine/impl/scripting/ScriptingEngines.java#L111, чтобы определить, может ли механизм сценариев быть кэшируются. Nashorn (и Rhino) возвращает здесь значение null, то есть его нельзя использовать для выполнения сценариев в нескольких потоках, т. Е. Каждому потоку нужен свой собственный экземпляр. Я могу только предположить, что ScriptEngineManager в JDK делает нечто подобное.
Ссылка: | Влияние на производительность сценариев в процессах от нашего партнера по JCG Йорама Барреса в блоге « Маленькие шаги с большими ногами» . |