2011-03-07 44 views
1

我们使用Apache Velocity作为动态模板。目前速度有以下的评价方法/更换:在StringBuilders/CharSequences中使用Apache Velocity

public static boolean evaluate(Context context, Writer writer, String logTag, Reader reader) 

public static boolean evaluate(Context context, Writer out, String logTag, String instring) 

我们通过提供StringWriter写评价结果使用这些方法。我们的传入数据将采用StringBuilder格式,因此我们使用StringBuilder.toString并将其作为instring供稿。

的问题是,我们的模板是相当大的(可以是兆字节,在罕见的情况下几十ms),发生替换非常频繁,并且每个替换操作三元所需的存储器的量(这将创建一个输入数据+ StringBuilder.toString()新副本+传出数据)。

我想知道是否有办法改善这一点。例如。如果我可以找到一种方法来提供一个ReaderWriter在相同的StringBuilder实例之上,只使用额外的内存进/出差异,这是一个好方法吗?有没有人做过类似的事情,并可以分享这类课程的任何资源?或者,也许有更好的解决方案给予问题?

回答

2

速度在评估之前需要解析整个模板。您将无法提供ReaderWriter以获得单个评估中的任何内容。然而,你可以将你的模板分解成更小的部分来单独评估它们。这将取决于它们的内容以及部件是否相互依赖。根据你的情况,开销可能不值得。

如果您只处理模板中的变量替换,您可以简单地评估输入的每一行。理想情况下,您可以在进入StringBuilder之前截取。否则,您仍然需要承担该内存的费用以及您拨入BufferedReader以拨打readLine()的呼叫的toString()

如果有#set指令,您需要不断传递相同的上下文进行评估。如果有任何#if#foreach块,它会变得棘手。实际上,我之前已经完成了这些工作,并读取了足够多的行来捕获Velocity的输入块以进行解析和评估。然而,在这一点上,你开始做Velocity的工作,这可能不值得。

+0

许多有趣的点,谢谢! – mindas 2011-03-12 22:13:02

0

哎呀。这对evaluate()来说非常重要。我假设你有很好的理由不使用标准资源加载器的东西,所以我不会认证。 :)

我没有听说过,将适合这个任何解决方案,但因为读者是不是一个特别复杂的类,我的本能会刚刚创建自己的StringBufferReader类,并传递英寸

1

您可以通过反射读取来自StringBuildervalue领域和创造上,一个CharArrayReader保存字符串的一个副本:

StringBuilder sb = new StringBuilder("bla"); 
    Field valueField = StringBuilder.class.getSuperclass().getDeclaredField("value"); 
    valueField.setAccessible(true); 
    char[] value = (char[]) valueField.get(sb); 
    Reader r = new CharArrayReader(value, 0, sb.length());