2010-11-09 60 views
22

我正在經歷一個真正的巨大的性能損失,同時調用一個簡單的XmlSerializer.Deserizlize()有很多字段的類。XmlSerializer啓動在64位系統上巨大的性能損失

注意:我在家裏編寫沒有Visual Studio的代碼,所以它可能有一些錯誤。

我的序列化的類是平坦的並且有數百字段:

[Serializable] 
class Foo 
{ 
    public Foo() { } 

    [XmlElement(ElementName = "Field1")] 
    public string Field1; 

    // [...] 500 Fields defined in the same way 

    [XmlElement(ElementName = "Field500")] 
    public string Field500; 
} 

我的申請反序列化輸入字符串(即使小):

StringReader sr = new StringReader(@"<Foo><Field1>foo</Field1></Foo>"); 
XmlSerializer serializer = new XmlSerializer(typeof(Foo)); 
object o = serializer.Deserialize(sr); 

運行在32位系統中的應用程序(或與32位強制執行corflags.exe),代碼大約需要ONE SECOND(臨時序列化類生成,全部...),那麼它接近於0.

運行在64位系統中的應用,代碼需要一分鐘第一次,那麼它的接近0

怎麼可能會導致系統掛起這麼長的時間,在第一次執行時一個XmlSerializer,用於64位系統中的大類?

現在我不知道如果我要責怪臨時類生成/刪除,XML名稱表初始化,CAS,Windows搜索,防病毒或聖誕老人...

破壞者

這裏是我的測試,如果你不想被我的(可能的)分析錯誤所束縛,請不要閱讀本文。

  • 運行代碼的從Visual Studio調試器使得即使在64個的系統
  • 添加(完全未記錄的)system.diagnostic開關「XmlSerialization.Compile」,這防止了系統從除去FAST運行代碼序列化臨時類,使代碼在64位系統中運行FAST
  • 以運行時創建的臨時FooXmlSerializer類(包括項目中的.cs),並使用它代替XmlSerializer,即使在代碼中也可以運行FAST 64位系統
  • 使用sgen.exe創建相同的FooXmlSerializer類,包括.cs在我的項目中,並使用它代替XmlSerializer,即使在64位系統中也能使代碼運行FAST
  • 使用sgen.exe創建相同的FooXmlSerializer類,並引用Foo.XmlSerializers。dll程序集,並使用它代替XmlSerializer,即使在64位系統中也能使代碼運行SLOW(,這使我非常困難
  • 僅當反序列化的輸入實際上包含字段時纔會發生性能損失大班的(這也來煩我了很多

爲了進一步解釋最後一點,如果我有一個類:

[Serializable] 
class Bar 
{ 
    public Bar() { } 

    [XmlElement(ElementName = "Foo")] 
    public Foo Foo; // my class with 500 fields 
} 

傳遞一個富孩子,只有當反序列化是緩慢的。即使我已經進行了反序列化:

StringReader sr = new StringReader(@"<Bar></Bar>"); 
XmlSerializer serializer = new XmlSerializer(typeof(Bar)); 
object o = serializer.Deserialize(sr); // FAST 

StringReader sr = new StringReader(@"<Bar><Foo><Field1>foo</Field1></Foo></Bar>"); 
XmlSerializer serializer = new XmlSerializer(typeof(Bar)); 
object o = serializer.Deserialize(sr); // SLOW 

編輯我忘了說,我分析了進程監視器執行,我沒有看到任何任務花費很長的時間,從我的應用程序或CSC。 exe或任何與框架有關的東西。該系統只是做其他的東西(或者我失去了一些東西),如防病毒,explorer.exe的,Windows搜索索引(已試圖將其關閉)

+0

sgen有什麼問題?爲什麼不只想走這條路嗎? – 2010-11-09 19:39:55

+0

我的Foo()類,調用XmlDeserializer的代碼是由舊系統動態生成的,我不能重構太多,我已經有了一個可接受的解決方案(使用system.diagnostic開關設置),但我真的很想知道什麼掛在系統:) – Filini 2010-11-09 19:54:00

+0

因此,你的系統不是很忙,它只是坐在那裏?這種表示某種類型的超時,可能試圖解決一個XML架構或什麼。不過,我預計在32位和64位環境中都會出現相同的延遲,除非先前以32位模式緩存模式,否則someh流。請重新輸入。 。 。 – TMN 2010-11-09 20:11:18

回答

6

UPDATE

我能重現此,調查顯示,大部分的時間是在JIT編譯器花費:

JittingStarted: 「Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderFoo」, 「Read2_Foo」, 「實例類SerializersTester.Foo」

您可以輕鬆地證明沒有任何分析器工具。

  • 生成* .XmlSerializers.dll通過查看sgen用於x86和x64目標
  • 通過NGEN生成本地圖像。

你可以看到64一代將與x86彙編比較更慢

在64 JIT-內部(BTW它完全從x86的不同),不幸的是我不的確切原因隱藏沒有足夠的空餘時間來找到它。

爲了避免這種性能損失,您可以通過sgen生成串行器的程序集,在終端用戶PC上的應用程序設置期間通過ngen將其引用並編譯爲本地映像。

+0

適用於.NET 2.0,3.5和4.0。「生成序列化程序集「只生成用於Web服務引用的序列化類,我手動使用了sgen.exe,看到了我的文章,還沒有使用分析器 – Filini 2010-11-09 19:51:25

+1

」確切原因隱藏在x64 JIT內部「 - 希望這個主題能夠吸引JIT團隊的成員,他們可以對此有所瞭解。 – 2010-11-09 22:20:39

+0

尼克,我仍然不明白的是爲什麼從外部程序集引用的類Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderFoo速度很慢,而向項目添加速度很快。在同一個程序集中使用foo類和它的序列化程序類是否會給JIT編譯器帶來好處? – Filini 2010-11-10 02:20:14

9

我不知道這是在所有相關的,但我有一個問題,XSLT和發現those rather interesting comments微軟對64位抖動:

的問題的根源是有關有兩件事:首先,x64 JIT編譯器有幾個算法是二次縮放的。其中之一是調試信息生成器,不幸的是。所以對於非常大的方法,它真的失去控制。

[...]

在64位JIT一些算法具有多項式縮放。實際上,我們正致力於將32位JIT編譯器移植到x64,但是直到下一個並行版本的運行時纔會看到天亮(如「2.0 & 4.0運行旁邊,但是3.0/3.5/3.5SP1是'in-place'版本)我已經將其轉換爲'建議',因此我可以將它保留在JIT吞吐量工作項目中,以確保在新移植的JIT是準備出貨。

再次,這是關於一個完全不同的問題,但在我看來,64位抖動的意見是普遍的。

+0

你是對的,這是一個不同的問題,但64位的JITter性能問題可能是相關的 – Filini 2010-11-10 02:25:11

+0

其次,JIT有些負責,我不知道爲什麼,但它是! – massimogentilini 2010-11-10 09:25:53

3

澄清「XmlSerialization。編譯「這就是它發生的事情:

如果我們在64位上運行沒有.config文件的代碼,它很慢。

如果再加上以下部分的config文件的應用程序

<configuration> 
    <system.diagnostics> 
    <switches> 
     <add name="XmlSerialization.Compilation" value="4"/> 
    </switches> 
    </system.diagnostics> 
</configuration> 

結果如下:

  • cs文件,用於串行DLL和PDB文件留在臨時文件夾
  • 串行器啓動快捷,它仍然比32位慢,但明確可接受(1-2秒而不是60)

也許創造在調試模式下DLL(因爲有可用的PDB文件)改變JIT編譯器的行爲再次快速使它......

0

,因爲64位的版本微軟已經知道這.NET:

http://connect.microsoft.com/VisualStudio/feedback/details/508748/memory-consumption-alot-higher-on-x64-for-xslcompiledtransform-transform-then-on-x86

從MSFT: 「是x64 JIT編譯器具有的平方比例數的算法。 ...自從64位框架在2005年首次發佈以來,我們已經看到過很多次。「 和

」這個問題是已知的,並且b)並不是真正無足輕重的地址。這是64位JIT的設計問題。我們正處於取代我們的64位JIT實施的初期階段,所以最終會得到地址,但不會在CLR 4.0時間範圍內,不幸的是。「