Недавно я набрал пять отрицательных голосов (!) За ответ на Groovy производительности;однако, я думаю, что должно быть , действительно, нужны объективные факты.Лично я считаю, что работать с Groovy и Grails продуктивно и весело;тем не менее, - это проблема производительности, которую необходимо устранить.
В сети существует ряд сравнительных сравнений, включая это .Вы никогда не можете доверять отдельным тестам (а приведенный даже не близок к научному), но вы поймете, что идея.
Groovy сильно полагается на метапрограммирование времени выполнения .Каждый объект в Groovy (ну, кроме скриптов Groovy) расширяется, например, от GroovyObject
с помощью метода invokeMethod(..)
.Каждый раз, когда вы вызываете метод в ваших классах Groovy, метод будет вызываться не напрямую, как в Java, а вызывать вышеупомянутый invokeMethod(..)
(который выполняет целую кучу размышлений и поисков).
Кроме того, каждыйGroovyObject
имеет связанный MetaClass
.Концепции вызова метода и т. Д. Схожи.
Существуют и другие факторы, снижающие производительность Groovy по сравнению с Java, в том числе бокс примитивных типов данных и (необязательно) слабая типизация, но вышеупомянутая концепция среды выполненияметапрограммирование имеет решающее значение.Вы даже не можете подумать о JIT-компиляторе с Groovy, который компилирует байт-код Java в собственный код для ускорения выполнения.
Для решения этих проблем существует проект Groovy ++ ,Вы просто аннотируете свои классы Groovy с помощью @Typed
, и они будут статически скомпилированы в (настоящий) байт-код Java.К сожалению, однако, я обнаружил, что Groovy ++ не достаточно развит и плохо интегрирован с основной линией Groovy и IDE.Groovy ++ также противоречит базовым парадигмам программирования Groovy.Более того, аннотация Groovy ++ '@Typed
не работает рекурсивно, то есть не влияет на базовые библиотеки, такие как GORM или инфраструктуру контроллеров Grails.
Полагаю, вы также оцениваете использование проекта Grails.
При взгляде на GORM Grails, эта среда, в которой интенсивно используется метапрограммирование во время выполнения, с непосредственным использованием Hibernate, должна работать намного лучше.
На уровне контроллеров или (особенно) сервисов обширные вычисления могутбыть выведенным на Java-классы.Однако доля GORM в типичных приложениях CRUD выше.
Потенциальная производительность в Grails обычно определяется уровнями кэширования на уровне база данных или избеганием вызова методов службы или контроллеров (см. Плагин SpringCache или плагин Cache Filter ).Как правило, они реализуются поверх инфраструктуры Ehcache .
Кэширование, очевидно, может хорошо подходить для статических данных в отличие от часто изменяющихся данных (базы данных) или веб-вывода, который довольно изменчив.
И, наконец, вы можете «бросить на это железо».: -)
В заключение, наиболее решающим фактором за или против использования Groovy / Grails на крупномасштабном веб-сайте должен быть вопрос о том, соответствует ли кэширование характеру конкретного веб-сайта.
EDIT: Что касается вопроса, имел ли JIT-компилятор Java возможность войти ...
Простой класс Groovy
class Hello {
def getGreeting(name) {
"Hello " + name
}
}
компилируется в
public class Hello
implements GroovyObject
{
public Hello()
{
Hello this;
CallSite[] arrayOfCallSite = $getCallSiteArray();
}
public Object getGreeting(Object name) {
CallSite[] arrayOfCallSite = $getCallSiteArray();
return arrayOfCallSite[0].call("Hello ", name);
}
static
{
Long tmp6_3 = Long.valueOf(0L);
__timeStamp__239_neverHappen1288962446391 = (Long)tmp6_3;
tmp6_3;
Long tmp20_17 = Long.valueOf(1288962446391L);
__timeStamp = (Long)tmp20_17;
tmp20_17;
return;
}
}
Это только вершина айсберга.Йохен Теодору, активный разработчик Groovy, выразил это так:
Вызов метода в Groovy обычно состоит из нескольких обычных вызовов метода, где аргументы хранятся в массиве, классы аргументов должныбыть извлеченным, из них генерируется ключ, для поиска метода используется hashmap, а в случае сбоя необходимо проверить доступные методы для совместимых методов, выбрать один из методов на основе типа времени выполнения, создать ключдля hasmap, а затем в конце сделайте отражение, как вызов метода.
Я действительно не думаю, что JIT включает такие динамические, очень сложные вызовы.
Что касается "решения" вашего вопроса, то нет "сделайте это так, и у вас все хорошо",Вместо этого задача состоит в том, чтобы определить факторы, которые являются более важными, чем другие, и возможные альтернативы и стратегии смягчения, оценить их влияние на ваши текущие варианты использования («могу ли я жить с этим?») И, наконец, определить сочетаниетехнологий, которые отвечают требованиям лучше всего (не полностью).