2010-08-22 17 views
9

He leído muy a menudo que BinaryFormatter tiene un mejor rendimiento que XmlSerializer. Por curiosidad, escribí una aplicación de prueba.Rendimiento: BinaryFormatter frente a XmlSerializer

un momento wtf ... ¿por qué Xml es mucho más rápido que Bin (especialmente la deserialización)?

using System; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.Xml.Serialization; 
using System.Runtime.Serialization.Formatters.Binary; 
using System.IO; 

namespace SerPlayground 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var items = new List<TestClass>(); 
      for (int i = 0; i < 1E6; i++) 
      { 
       items.Add(new TestClass() { Name = i.ToString(), Id = i }); 
      } 

      File.Delete("test.bin"); 
      using (var target = new FileStream("test.bin", FileMode.OpenOrCreate)) 
      { 
       System.Threading.Thread.Sleep(1000); 
       var bin = new BinaryFormatter(); 
       var start = DateTime.Now; 
       bin.Serialize(target, items); 
       Console.WriteLine("Bin: {0}", (DateTime.Now - start).TotalMilliseconds); 

       target.Position = 0; 
       System.Threading.Thread.Sleep(1000); 
       start = DateTime.Now; 
       bin.Deserialize(target); 
       Console.WriteLine("Bin-D: {0}", (DateTime.Now - start).TotalMilliseconds); 
      } 

      File.Delete("test.xml"); 
      using (var target = new FileStream("test.xml", FileMode.OpenOrCreate)) 
      { 
       System.Threading.Thread.Sleep(1000); 
       var xml = new XmlSerializer(typeof(List<TestClass>)); 
       var start = DateTime.Now; 
       xml.Serialize(target, items); 
       Console.WriteLine("Xml: {0}", (DateTime.Now - start).TotalMilliseconds); 

       target.Position = 0; 
       System.Threading.Thread.Sleep(1000); 
       start = DateTime.Now; 
       xml.Deserialize(target); 
       Console.WriteLine("Xml-D: {0}", (DateTime.Now - start).TotalMilliseconds); 
      } 

      Console.ReadKey(); 
     } 
    } 

    [Serializable] 
    public class TestClass 
    { 
     public string Name { get; set; } 
     public int Id { get; set; } 
    } 
} 

mis resultados:

Bin: 13472.7706 
Bin-D: 121131.9284 
Xml: 8917.51 
Xml-D: 12841.7345 
+1

Deserialización es mucho más lenta que la serialización. ¿Puedes modificar tu muestra para hacer ambas cosas? Esa será una comparación mucho más interesante. –

+0

Hola, Consideraría ejecutar algunas de sus pruebas varias veces (más de 100 veces), ya sea con el inicio (creando los formateadores/serializadores) incluido en el ciclo o sin él. La sincronización del resultado de muchas más ejecuciones puede proporcionarle una imagen más precisa del rendimiento. También considere usar la clase StopWatch para hacer los tiempos, ya que creo que usa el temporizador de alto rendimiento donde sea posible. Si aún obtiene una serialización XML más rápida, ¡sería bueno saber por qué también! – Jennifer

+0

Siempre he entendido que el binario es "más rápido" con respecto a la transferencia de red, ya que contendrá menos bytes. Sin embargo, esperaría que llevara una carga útil bastante alta para que la diferencia sea evidente. – kbrimington

Respuesta

7

Debido a que está serialising un objeto que no tiene ninguna propiedad.

Si serializa algo diferente que en realidad contiene algunos datos, como por ejemplo una cadena, el serializador binario es mucho más rápido que el serializador XML.

hice este cambio en su código:

items.Add("asfd"); 

y me da este resultado:

Xml: 1219.0541 
Bin: 165.0002 

Una parte de la diferencia es, por supuesto que el archivo XML es aproximadamente diez veces mayor que el archivo binario

+1

Vale la pena señalar que todo se ejecuta casi el doble de rápido si se intercambia la posición de los bloques XML y BIN (aunque la proporción de tiempo utilizada entre los bloques permanece aproximadamente igual). Así que creo que todo el punto de referencia es sospechoso, tal vez debido a la recolección de basura o algún otro factor. –

+2

asfd - Sociedad Americana de Diseñadores de Muebles? –

+0

& Rober Harvey: He agregado una clase más compleja ... el intercambio de XML y BIN no hace ningún cambio ahora ... el resultado es el mismo XML es más rápido – Lukas

3

El ejemplo es bastante bueno y la pregunta es interesante (estoy de acuerdo con Robert en que debe ejecutar el método Main al menos una vez antes de hacer cualquier medida ya que la inicialización de varios tipos no se debe considerar como parte de la prueba).

Una vez dicho esto, una diferencia clave entre XmlSerializer y BinaryFormatter (aparte de lo obvio) es que XmlSerializer no intenta realizar un seguimiento de las referencias. Si su gráfico de objetos tiene múltiples referencias al mismo objeto, obtiene múltiples copias en el XML y esto no se resuelve correctamente (de vuelta en un solo objeto) después de la deserialización. Peor aún si tiene ciclos, el objeto no se puede serializar en absoluto. Contraste esto con BinaryFormatter, que hace un seguimiento de las referencias y reconstruye de manera confiable el gráfico de objetos, sin importar cuántas referencias de objetos tenga y qué tipo de referencias tenga. Tal vez la sobrecarga de esta instalación representa el peor rendimiento?

La razón principal para utilizar BinaryFormatter sobre XmlSerializer es el tamaño de la salida, no el rendimiento de la serialziation/deserialization. (Los gastos generales de construcción de texto no es tan grande, que es el transporte de ese texto XML que es caro.)

Cuestiones relacionadas