#java #spring #java-8 #spring-el
#java #spring #java-8 #spring-el
Вопрос:
Я использую spEL 4.0.0.RELEASE для привязки http-параметров к объектам java. Я замечаю некоторую странную проблему при многократном использовании анализатора выражений: каждый вызов занимает больше времени (постоянно). Это происходит только на java 8. На java 7 все в порядке.
Вот пример кода:
package ru.tersys.test;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class Test {
public static void main(String[] args) {
Test instance = new Test();
Table t = new Table();
Column c = new Column();
t.getColumns().add(c);
int counter = 10;
while (counter-- > 0)
{
instance.doTest("t", t);
}
}
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
public void doTest(String prefix, Object obj)
{
Date d = Calendar.getInstance().getTime();
int counter = 0;
String el = "t.columns[0].name";
context.setVariable(prefix, obj);
String prefixWithDot = prefix ".";
int count = 400;
while (count -- > 0)
{
if (el.startsWith(prefixWithDot))
{
parser.parseExpression("#" el).setValue(context, "testColumnName");
counter ;
}
}
System.out.println("bind duration sec = " (Calendar.getInstance().getTime().getTime() - d.getTime())/1000 " param count = " counter);
}
static class Table
{
public Table()
{
columns = new ArrayList<>();
}
public ArrayList<Column> getColumns() {
return columns;
}
public void setColumns(ArrayList<Column> columns) {
this.columns = columns;
}
private ArrayList<Column> columns;
}
static class Column
{
public Column()
{
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
вывод jdk 8:
bind duration sec = 1 param count = 400
bind duration sec = 3 param count = 400
bind duration sec = 5 param count = 400
bind duration sec = 7 param count = 400
bind duration sec = 9 param count = 400
bind duration sec = 12 param count = 400
bind duration sec = 14 param count = 400
bind duration sec = 16 param count = 400
bind duration sec = 19 param count = 400
bind duration sec = 22 param count = 400
вывод Java 7:
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
bind duration sec = 0 param count = 400
Это ошибка или особенность? Есть ли какой-либо обходной путь?
Комментарии:
1. Я предлагаю профилировать с помощью VisualVM, чтобы показать, на что тратится это время.
2. Использование
Calendar
для этой цели — самая странная вещь, которую я когда-либо видел. Вы знаетеSystem.nanoTime()
?3. Привет, Марко. Да, я тестировал это с помощью jVisualVm. Горячий метод — org.springframework.core. ResolvableType.asCollection(). Похоже, что есть какая-то проблема с коллекциями.
4. Вы получили это из списка «горячих точек»? Это не обязательно рассказывает всю историю. Анализ трассировок стека моментального снимка и поиск вызова метода bottleneck намного надежнее. Извините, если это то, что вы уже сделали.
5. Проблема была решена путем перехода на spring-el версии 4.0.5.RELEASE
Ответ №1:
Это может быть связано с проблемой JIRA «Проблемы с производительностью SerializableTypeWrapper на Java 1.7.0_51», которая была исправлена в версии 4.0.1.