Java 8 Spring SpEL可重复绑定减慢了每个迭代的速度。

5

我正在使用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

这是bug还是特性?有没有解决方法?

1
我建议使用VisualVM进行分析,以揭示时间花费在哪里。 - Marko Topolnik
使用Calendar来做这件事是我见过的最奇怪的事情。你知道System.nanoTime()吗? - Holger
你好,Marko。是的,我用 jVisualVm 进行了测试。热方法是 org.springframework.core.ResolvableType.asCollection()。看起来集合存在一些问题。 - Sergey Zubarev
你是从“热点”列表中得到的吗?这并不一定能够完全说明问题。分析快照的堆栈跟踪并找到瓶颈方法调用会更加可靠。如果你已经这样做了,那我很抱歉。 - Marko Topolnik
不,我是从“调用树”中获取的。在热点选项卡中,最常调用的方法是[java.lang.Class.getClassLoader() 97.0107 22 685毫秒(97%)22 685毫秒]。这是在调用树中org.springframework.core.ResolvableType.asCollection()方法调用的叶子节点。 - Sergey Zubarev
1
问题通过切换到Spring EL版本4.0.5.RELEASE得以解决。 - Sergey Zubarev
1个回答

4

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接