2016-12-05 23 views
1

我們有很多的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

+0

我的第一個問題就是爲什麼這個邏輯首先在視圖層中處理 - 你可以將它移出到Java代碼嗎?一般來說,視圖層中的處理邏輯並不是一個好主意,更不是一個好主意,當它被定義自己的操作的腳本語言處理時。 –

+0

@DaveNewton,我同意表示層應該包含最少的邏輯。但是,不幸的是,我們不能重寫表示層,因爲有大量的ftl。所以,我們唯一能做的就是設法解決這個問題的原因。 – evgeniy44

+0

除了地圖連接之外,你還可以採取其他方式嗎? –

回答

2

儘量使用最新的穩定版本的FreeMarker(2.3.25目前),看看速度是可以接受的。一個提交於2013年6月13日說:

這進一步(據 ,因爲它會被悄悄處理)減少TemplateException創建資源使用率,從指責 表達,提示最終消息等是隻有當消息確實需要 時才組裝。

2.3.19早於2012-02-29發佈。

更新:我已經承諾進入2.3.26-nightly,因此回落到散列添加並不依賴於異常拋出/捕獲。不確定這是你的性能問題的主導,但肯定是效率低下。

+0

2.3.19我們的平均響應時間爲271ms。 2.3.25 - 284ms。所以,在版本更新之後,我們甚至可以看到性能有所下降。至少它沒有改善它。 – evgeniy44

+0

所以我想那時候並沒有花時間來構建這個消息。分析器是否仍然指向異常構建?投擲一個新的(!)異常相對昂貴,因爲它必須捕獲Java堆棧跟蹤等,即使您在構造函數中什麼也不做。 – ddekany

+0

每個請求有多少個並置是BTW?我可以在單個3.3 GHz Haswell核心上每250毫秒進行150000個串接。不是很好,但你真的在做這麼多的連接嗎? – ddekany