我正在將小腳本嵌入到c#應用程序中。
爲了提高性能,我在應用程序啓動時編譯它們。CompiledCode.Execute在第一次迭代中需要很長時間
public CompiledCode CompileScript(string script)
{
return engine.CreateScriptSourceFromString(script).Compile();
}
CompiledCode實例然後存儲在一個字典中,以便稍後可以重用它們。
當時間已經到了執行它們,我使用類似:
result = code.Execute(scope);
凡範圍是一個簡單的輔助類保持了ScriptScope
一個實例。
這個範圍設置,以便提供給腳本變量和組件正確添加創建助手的實例時:
if (variables != null)
{
scope = engine.CreateScope(variables);
}
else
{
scope = engine.CreateScope();
}
if (assemblies != null)
{
assemblies.ForEach(a => scope.Engine.Runtime.LoadAssembly(a));
}
基本上,組件的列表傳遞給助手類的構造函數,並在各個地方重用助手類的實例。 (不是靜態類,因爲我確實需要針對特定場景的多個幫助程序實例,但是在這個問題的上下文中,我們正在討論單個實例)
在普通PC上使用此操作時,編譯/運行代碼是可忽略的。
但是,我在RaspberryPI
上運行這個程序,並注意到第一次執行特定腳本時,需要很長時間。 (對於2行腳本容易達到40秒)
後續執行相同CompiledCode
實例的執行速度非常快(200毫秒)。
所以我有已編譯的代碼(奇怪的是,第一次編譯也非常快),但在給定的CompiledCode
實例上首次調用Execute()需要很長時間。
現在我想知道,Execute()
第一次做什麼,並且有沒有一種方法可以在不實際執行代碼的情況下在早期執行任何操作? 在編譯和實際運行代碼之間似乎還有一個額外的步驟。
我想也許它的相關的事實,我重用了
輔助類中定義的範圍,當然,如果我只使用默認範圍上執行
我沒有任何變量和組裝引用。
更新:
在樹莓派跑這意味着我使用單聲道。
更具體地說 單聲道2.10.8.1(Debian 2.10.8.1-8)
我無法更新單聲道,因爲我依賴的是一個非常特定的MonoGame
版本,該版本只適用於編寫本文時的這個Mono版本。
您是否嘗試過使用性能分析器來查看它?有沒有例外?你看過哪些程序集正在加載/ JIT和需要多長時間? – 2013-03-20 09:28:24
不,掛接分析器非常困難,它只發生在運行在Raspberry上時,所以沒有調試器,單聲道分析器也沒有幫助我。奇怪的是,它每CompiledCode只發生一次,並且組裝/變量加載只發生一次,而不是CompiledCode的每個實例,所以它真的是第一個執行需要這麼長時間。另一種方法是我使用MEF來支持插件而不是腳本 – TimothyP 2013-03-20 09:54:37
Compile()方法生成IL。然後必須將其轉換爲機器碼。這需要做一次,你正在測量需要多長時間。單聲道沒有最奇怪的抖動,但40秒是相當長的時間。足夠長的時間來懷疑某種網絡問題,它大致匹配默認的tcp/ip連接超時。 – 2013-03-20 12:32:46