java 8 spring spEL повторяемая привязка замедляет каждую итерацию

#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.