Mythbuster: Serialisierung

Mir klingt noch in Ohren, wie vor vielen Jahren MySQL als die “kostenfreie schnelle Datenbank” von vielen Seiten gelobt wurde. Nachdem wir im Team dann einen Performance Test aufgebaut hatten zerfiel die Tatsache zu Staub und erwies sich als düstere Legende in der man einen kennt der einen kennt.

In diesem Kontext habe ich mir verschiedene Serialisierungen angesehen.  Spezielle die Aussagen zu Newtonsoft JSON.NET werden in der Regel gerne von der Fachwelt zitiert.

Um ehrlich zu sein, mein Testszenario ist nicht perfekt. Alles läuft auf einer Maschine, Fremdeinflüsse sind nicht ausgeschlossen oder gar Methodische Fehler. Hinweise wie immer in den Kommentaren.

Testziel ist es aus 91 Datensätzen der Northwind Customers Tabelle einen String zu erstellen. Gemessen wird mit der Stopwatch Klasse. Da die Zeitspannen sehr kurz sind habe ich mich für Ticks statt Millisekunden entschieden. Außerdem wurde Testweise jeweils der Test 1000x ausgeführt um längere Zeiten zu bekommen. Da ich aber nicht ausschließen kann das dann Optimierungen vom Compiler, Betriebssystem und co greifen  ist der Test letztendlich nur einmal pro Code Segment.

   1:   Dim timer As Stopwatch = New Stopwatch()
   2:   timer.Start()
   3:   timer.Stop()
   4:   TextBox1.Text = timer.ElapsedTicks '25136
   5:   
   6:   
   7:  timer.Restart()

 

Ich habe mir 5 Varianten überlegt, wobei sogar eine SDF Variante dabei ist. Weil die Parameter unterschiedlich sind wie Stream oder String ist der Code deutlich unterschiedlich.

Microsoft Json

   1:   Dim ser0 As DataContractJsonSerializer = New DataContractJsonSerializer(GetType(List(Of Customers)))
   2:   Using ms = New MemoryStream()
   3:              ser0.WriteObject(ms, kunden)
   4:              Dim json0 = Encoding.Default.GetString(ms.ToArray())
   5:   End Using

 

NewtonSoft Json

   1:      Dim json1 = JsonConvert.SerializeObject(kunden, Formatting.None, New JsonSerializerSettings With
   2:       {
   3:         .TypeNameHandling = TypeNameHandling.Auto,
   4:         .TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple
   5:       })

 

Microsoft XML

   1:    Dim ser As DataContractSerializer = New DataContractSerializer(GetType(List(Of Customers)))
   2:    Using ms = New MemoryStream()
   3:              ser.WriteObject(ms, kunden)
   4:              Dim json0 = Encoding.Default.GetString(ms.ToArray())
   5:    End Using

XLINQ

   1:      Dim xml As XElement =
   2:   New XElement("Customers",
   3:            From c In kunden
   4:            Select <Customer>
   5:            <Address><%= c.Address %></Address>
   6:            <City><%= c.City %></City>
   7:            <Company_Name><%= c.Company_Name %></Company_Name>
   8:            <Contact_Name><%= c.Contact_Name %></Contact_Name>
   9:            <Contact_Title><%= c.Contact_Title %></Contact_Title>
  10:            <Country><%= c.Country %></Country>
  11:            <Customer_ID><%= c.Customer_ID %></Customer_ID>
  12:            <Fax><%= c.Fax %></Fax>
  13:            <Phone><%= c.Phone %></Phone>
  14:            <Postal_Code><%= c.Postal_Code %></Postal_Code>
  15:             <Region><%= c.Region %></Region>
  16:        </Customer>)
  17:     Dim sxml = xml.ToString(SaveOptions.DisableFormatting)
  18:      

Stringbuilder und SDF

   1:   Dim s As New StringBuilder
   2:          For Each c In kunden
   3:              s.Append(c.Address)
   4:              s.Append(";")
   5:              s.Append(c.City)
   6:              s.Append(";")
   7:              s.Append(c.Company_Name)
   8:              s.Append(";")
   9:              s.Append(c.Contact_Name)
  10:              s.Append(";")
  11:              s.Append(c.Contact_Title)
  12:              s.Append(";")
  13:              s.Append(c.Country)
  14:              s.Append(";")
  15:              s.Append(c.Customer_ID)
  16:              s.Append(";")
  17:              s.Append(c.Fax)
  18:              s.Append(";")
  19:              s.Append(c.Phone)
  20:              s.Append(";")
  21:              s.Append(c.Postal_Code)
  22:              s.Append(";")
  23:              s.Append(c.Region)
  24:              s.AppendLine()
  25:          Next
  26:          Dim se = s.ToString

 

Das Ergebnis

Methode MS JsonSerial JSON.NET XMLSerial xLinq String
Ticks 3585 6329 3105 3416 305
Length 25136 intended: 32725 
none: 24988
34737 33321 11428

Zunächst ist überrascht, das JSON.NET doppelt so lange braucht wie der Microsoft Serialisierer. Der Mythos ist damit zerstört. Auch der XML Serialsisierer überrascht positiv sowohl in Bezug auf Größe als auch Zeit. Der Hammer ist aber, das plain old Text über 10x schneller ist und auch wesentlich weniger Platz braucht. Letzteren Nachteil wird wahrscheinlich HTTP 1.1 Kompression nahezu komplett ausgleichen, aber es ist durchaus eine Überlegung speziell in closed systems auf SDF zu setzen.

Kommentare sind geschlossen