我們有很多的FTL代碼執行哈希級聯是這樣的:由於下面的代碼NonStringExceptions消耗相當多的時候,哈希的級聯發生
<#local event_data = event_data + {
'subaction_name': subactionName
} />
然而,這些結構造成一定的開銷(在freemarker.core .AddConcatExpression類_getAsTemplateModel(環境Env)方法):
try {
String s1 = getStringValue(leftModel, left, env);
if(s1 == null) s1 = "null";
String s2 = getStringValue(rightModel, right, env);
if(s2 == null) s2 = "null";
return new SimpleScalar(s1.concat(s2));
} catch (NonStringException e) {
if (leftModel instanceof TemplateHashModel && rightModel instanceof TemplateHashModel) {
if (leftModel instanceof TemplateHashModelEx && rightModel instanceof TemplateHashModelEx) {
TemplateHashModelEx leftModelEx = (TemplateHashModelEx)leftModel;
TemplateHashModelEx rightModelEx = (TemplateHashModelEx)rightModel;
if (leftModelEx.size() == 0) {
return rightModelEx;
} else if (rightModelEx.size() == 0) {
return leftModelEx;
} else {
return new ConcatenatedHashEx(leftModelEx, rightModelEx);
}
} else {
return new ConcatenatedHash((TemplateHashModel)leftModel,
(TemplateHashModel)rightModel);
}
} else {
throw e;
}
}
因爲GetStringValue方法拋出在這種情況下NonStringExceptions。的NonStringException,反過來,繼承了TemplateException下面的構造邏輯:
super(getDescription(description, cause));
causeException = cause;
this.env = env;
if(env != null)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
env.outputInstructionStack(pw);
pw.flush();
ftlInstructionStack = sw.toString();
}
else
{
ftlInstructionStack = "";
}
其中取每次完整的指令堆棧無論進一步處理。
在我們的例子中,這會導致每個頁面請求花費在異常構造函數上的執行時間高達50 ms,這對整體吞吐量非常關鍵。
任何人都可以提供一些建議,如何避免這些例外,而不觸及FTL代碼,請?或者,也許有可能獲得某種修補程序,它將在AddConcatExpression._getAsTemplateModel方法中的catch塊之前移動TemplateModelHash instanceof check?
編輯: freemarker的版本2.3.19
我的第一個問題就是爲什麼這個邏輯首先在視圖層中處理 - 你可以將它移出到Java代碼嗎?一般來說,視圖層中的處理邏輯並不是一個好主意,更不是一個好主意,當它被定義自己的操作的腳本語言處理時。 –
@DaveNewton,我同意表示層應該包含最少的邏輯。但是,不幸的是,我們不能重寫表示層,因爲有大量的ftl。所以,我們唯一能做的就是設法解決這個問題的原因。 – evgeniy44
除了地圖連接之外,你還可以採取其他方式嗎? –