使用XML序列化程式產生器工具加速XML序列化

  • 12063
  • 0

使用XML序列化程式產生器工具加速XML序列化

XML 序列化程式產生器工具

.NET程式在做XML序列化時,在效能上表現並不佳,因此提供了XML 序列化程式產生器工具來改善這個問題。使用XML 序列化程式產生器工具,可為指定組件中的型別建立 XML 序列化 (Serialization) 組件,以改善 XmlSerializer 在序列化或還原序列化指定型別物件時的啟動效能。

 

如果未使用 XML 序列化程式產生器,為指定組件中的型別建立XML 序列化組件。則每當應用程式執行時,XmlSerializer 便會為每個型別產生序列化程式碼和序列化組件,造成XML序列化緩慢。

 

何謂XML序列化組件呢?換句話說就是使用XML 序列化程式產生器所產生出來的檔案,也就是檔案命名後半部為XmlSerializers.dll的檔案,像是Data.XmlSerializers.dll。

 

這邊我們可以寫個簡單的程式來觀察這個現象,程式碼如下:


Imports System.IO

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim count As Integer = 1
        Dim perosn As New Person
        Dim xs As New XmlSerializer(GetType(Person))
        Dim sw As Stopwatch = Stopwatch.StartNew
        Using ms As New MemoryStream
            For i As Integer = 0 To count - 1
                ms.Seek(0, SeekOrigin.Begin)
                xs.Serialize(ms, perosn)
            Next
        End Using
        MsgBox("ElapsedMilliseconds: " & sw.ElapsedMilliseconds)
    End Sub
End Class

Public Class Person
    Private _name As String
    Public Property Name() As String
        Get
            Return _name
        End Get
        Set(ByVal value As String)
            _name = value
        End Set
    End Property

    Private _year As Integer
    Public Property Year() As Integer
        Get
            Return _year
        End Get
        Set(ByVal value As Integer)
            _year = value
        End Set
    End Property
End Class

 

運行後用ProcessMonitor去觀察,可發現當第一次執行到建立XmlSerializer物件的程式碼時,背後就在偷偷的找尋並試圖建立XML序列化組件。

image

 

使用XML 序列化程式產生器工具

要熟悉如何使用XML 序列化程式產生器工具來加速XML序列化的動作,先來看一下Sgen.Exe的用法。

Usage: sgen.exe [[/assembly:<assembly name>] | [<assembly file location>]]
    [/type:] [/reference:] [/compiler:] [/debug] [/keep] [/nologo]
    [/silent] [/verbose]

  Developer options:
    /assembly:   Assembly location or display name. Short form is '/a:'.
    /type:       Generate code for serialization/deserialization of a single
                 type from the input assembly. Short form is '/t:'.
    /reference:  Reference metadata from the specified assembly files.
                 Short form is '/r:'.
    /compiler:   Visual C# compiler options to use while compiling generated
                 code. Short form is '/c'.
                 For complete list of available options see c# compiler help.
    /proxytypes  Generate serialization code only for proxy classes and web
                 method parameters. Short form is '/p'.
    /debug       Generate image which can be used under a debugger.
                 Short form is '/d'.
    /keep        Keep source code and compiler temp files. Short form is '/k'.
    /force       Forces overwrite of a previously generated assembly.
                 Short form is '/f'.
    /out:        Output directory name (default: target assembly location).
                 Short form is '/o:'.
    /parsableerrors
                 Print errors in a format similar to those reported by
                 compilers.

  Miscellaneous options:
    /? or /help  Show this message
    /nologo      Prevents displaying of logo. Short form is '/n'.
    /silent      Prevents displaying of success messages. Short form is '/s'.
    /verbose     Displays verbose output for debugging. Short form is '/v'.
                 List types from the target assembly that cannot be serialized
                 with XmlSerializer.

 

最簡單的用法就是直接在命令後面接上組件名稱,像是:

Sgen XXX.dll

 

若產生的檔案可能已經存在,可加上/f參數強迫覆蓋。而若無法正確的產生XML序列化組件,可加上/v參數顯示造成無法產生的錯誤訊息。

 

使用上可在[專案]→[屬性]→[編譯]→[建置事件]內的建置後事件加上如下命令(命令路徑請依電腦實際狀況去做調整):

"%ProgramFiles%\Microsoft SDKs\Windows\v7.0A\bin\sgen.exe" /a:"$(TargetPath)" /force

image

 

如此建置後將在輸出目錄自動產生對應的XML序列化組件,將產生的XML序列化組件與自己撰寫的組件放在一起,序列化的速度就會提升了。

 

若仍嫌速度緩慢,也可以把產生的序列化組件加入參考,匯入Microsoft.Xml.Serialization.GeneratedAssembly命名空間,改用序列化組件內的Serializer取代XmlSerializer,像是:


Imports System.IO
Imports Microsoft.Xml.Serialization.GeneratedAssembly

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim count As Integer = 1000
        Dim perosn As New Person
        Dim xs As New PersonSerializer
        Dim sw As Stopwatch = Stopwatch.StartNew
        Using ms As New MemoryStream
            For i As Integer = 0 To count - 1
                ms.Seek(0, SeekOrigin.Begin)
                xs.Serialize(ms, perosn)
            Next
        End Using
        MsgBox("ElapsedMilliseconds: " & sw.ElapsedMilliseconds)
    End Sub
End Class

 

效能測試

這邊針對校能的改進作了一些測試,測試的CODE沿用上面的範例,實驗數據與結果如下:

次數 無XML序列化組件 有XML序列化組件 使用XML序列化組件的Serialzer
1000 125 107 84
10000 946 884 597
100000 7382 5909 5924
1000000 62892  59159 44779

image

 

Link