我需要将一些配置信息存储到文件中。在C#代码中,配置数据由类表示,在文件中我将以json或xml格式保存此类数据。那么,序列化json或xml的性能哪个更好?
我需要将一些配置信息存储到文件中。在C#代码中,配置数据由类表示,在文件中我将以json或xml格式保存此类数据。那么,序列化json或xml的性能哪个更好?
我有答案,不用再猜了。这是测试程序:
class Program
{
static void Main(string[] args)
{
string xmlConfig = "";
string jsonConfig = "";
Config myConfig = new Config()
{
value = "My String Value",
DateStamp = DateTime.Today,
counter = 42,
Id = Guid.NewGuid()
};
// Make both strings
DataContractSerializer xmlSerializer = new DataContractSerializer(typeof(Config));
using (MemoryStream xmlStream = new MemoryStream())
{
xmlSerializer.WriteObject(xmlStream, myConfig);
xmlConfig = Encoding.UTF8.GetString(xmlStream.ToArray());
}
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Config));
using (MemoryStream jsonStream = new MemoryStream())
{
jsonSerializer.WriteObject(jsonStream, myConfig);
jsonConfig = Encoding.UTF8.GetString(jsonStream.ToArray());
}
// Test Single
var XmlSingleTimer = Stopwatch.StartNew();
SerializeXML(xmlConfig, 1);
XmlSingleTimer.Stop();
var JsonSingleTimer = Stopwatch.StartNew();
SerializeJSON(jsonConfig, 1);
JsonSingleTimer.Stop();
// Test 1000
var XmlTimer = Stopwatch.StartNew();
SerializeXML(xmlConfig, 1000);
XmlTimer.Stop();
var JsonTimer = Stopwatch.StartNew();
SerializeJSON(jsonConfig, 1000);
JsonTimer.Stop();
// Test 10000
var XmlTimer2 = Stopwatch.StartNew();
SerializeXML(xmlConfig, 10000);
XmlTimer2.Stop();
var JsonTimer2 = Stopwatch.StartNew();
SerializeJSON(jsonConfig, 10000);
JsonTimer2.Stop();
Console.WriteLine(String.Format("XML Serialization Single: {0}ms", XmlSingleTimer.Elapsed.TotalMilliseconds));
Console.WriteLine(String.Format("JSON Serialization Single: {0}ms", JsonSingleTimer.Elapsed.TotalMilliseconds));
Console.WriteLine();
Console.WriteLine(String.Format("XML Serialization 1000: {0}ms", XmlTimer.Elapsed.TotalMilliseconds));
Console.WriteLine(String.Format("JSON Serialization 1000: {0}ms ", JsonTimer.Elapsed.TotalMilliseconds));
Console.WriteLine();
Console.WriteLine(String.Format("XML Serialization 10000: {0}ms ", XmlTimer2.ElapsedMilliseconds));
Console.WriteLine(String.Format("JSON Serialization 10000: {0}ms ", JsonTimer2.ElapsedMilliseconds));
}
public static void SerializeXML(string xml, int iterations)
{
DataContractSerializer xmlSerializer = new DataContractSerializer(typeof(Config));
for (int i = 0; i < iterations; i++)
{
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(xml)))
{
Config serialized = (Config)xmlSerializer.ReadObject(stream);
}
}
}
public static void SerializeJSON(string json, int iterations)
{
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(Config));
for (int i = 0; i < iterations; i++)
{
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
Config serialized = (Config)jsonSerializer.ReadObject(stream);
}
}
}
}
public class Config
{
public string value;
public DateTime DateStamp;
public int counter;
public Guid Id;
}
这是测量输出结果:
XML Serialization Single: 2.3764ms
JSON Serialization Single: 2.1432ms
XML Serialization 1000: 13.7754ms
JSON Serialization 1000: 13.747ms
XML Serialization 10000: 100ms
JSON Serialization 10000: 134ms
在1次迭代后,JSON的速度始终比XML稍快。经过1000次迭代后,它们之间几乎没有区别。但是,在10000次迭代后,XML明显更快。
目前还无法解释为什么一次一次地解析JSON会更快,但是如果重复解析,则XML会更快。可能是由于缓存或库中的某些花哨功能造成的。您可以看到JsonSerializer以线性方式扩展,将迭代次数增加一个数量级就会线性地增加已用时间一个数量级。但XmlSerializer的表现不同,其性能并没有呈线性扩展。
我多次重复此操作,并始终得到相同的结果。
因此,教训是:如果您只需要解析单个对象一次,则JSON会略微更好。但是,如果您要重复解析对象,则XML可能表现更佳。尽管我没有测试对象值在每次迭代中更改时会发生什么,但那可能会有所不同。
还请注意,我在此处使用的是本机Runtime.Serialization库。其他库可能会产生不同的结果。
编辑:我刚刚尝试了一下,在调用字符串时每次都生成一个新的Guid和随机整数。对于单次迭代和10000次迭代测试,这对结果没有影响。但是对于1000次迭代,JSON大约快了1毫秒。因此,看起来XML序列化程序确实正在缓存值。
Newtonsoft.Json
è؟›è،ŒJSONه؛ڈهˆ—هŒ–,那ه°±ه¤ھو£’ن؛†.. :) - TryingToImproveNewtonsoft.Json
。基准测试结果显示,在超过1次迭代的情况下,Newtonsoft.Json在处理XML和JSON的速度上要比原生的DataContractSerializers快得多。 - Dan Atkinson这是对@Wedge在2014年回答的更新。
它是用.NET 6.0编写的,同时还使用了流行的Newtonsoft.Json库。我还增加了迭代次数。之前是1、1,000和10,000。这个版本现在也进行100,000、1,000,000和10,000,000次迭代,但仍然非常不科学,也不现实。
下面是使用的代码。如果您想复制此代码,请确保导入Newtonsoft.Json到您的项目中。
using Newtonsoft.Json;
using System.Diagnostics;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
Config myConfig = new Config()
{
value = "My String Value",
DateStamp = DateTime.Today,
counter = 42,
Id = Guid.NewGuid()
};
// Xml serializer
string xmlConfig = "";
var xmlSerializer = new DataContractSerializer(typeof(Config));
using (var xmlStream = new MemoryStream())
{
xmlSerializer.WriteObject(xmlStream, myConfig);
xmlConfig = Encoding.UTF8.GetString(xmlStream.ToArray());
}
// Json serializer
string jsonConfig = "";
var jsonSerializer = new DataContractJsonSerializer(typeof(Config));
using (var jsonStream = new MemoryStream())
{
jsonSerializer.WriteObject(jsonStream, myConfig);
jsonConfig = Encoding.UTF8.GetString(jsonStream.ToArray());
}
// Newtonsoft.Json serializer.
string newtonsoftJsonConfig = "";
var newtonsoftJsonSerializer = new JsonSerializer();
using (var newtonSoftMemoryStream = new MemoryStream())
using (var writer = new StreamWriter(newtonSoftMemoryStream))
using (var newtonsoftJsonWriter = new JsonTextWriter(writer))
{
newtonsoftJsonSerializer.Serialize(newtonsoftJsonWriter, myConfig);
newtonsoftJsonWriter.Flush();
newtonSoftMemoryStream.Position = 0;
newtonsoftJsonConfig = Encoding.UTF8.GetString(newtonSoftMemoryStream.ToArray());
}
// Create a group of 5 different tests.
int[] counterArray = { 1, 1000, 10000, 100000, 1000000, 10000000 };
foreach (var iterations in counterArray)
{
// Serialize XML.
var xmlTimer = Stopwatch.StartNew();
SerializeXML(xmlConfig, iterations);
xmlTimer.Stop();
// Serialize JSON.
var jsonTimer = Stopwatch.StartNew();
SerializeJSON(jsonConfig, iterations);
jsonTimer.Stop();
// Serialize JSON (Newtonsoft).
var newtonsoftJsonTimer = Stopwatch.StartNew();
SerializeNewtonsoftJson(newtonsoftJsonConfig, iterations);
newtonsoftJsonTimer.Stop();
Console.WriteLine($"XML Serialization {iterations}: {xmlTimer.Elapsed.TotalMilliseconds}ms");
Console.WriteLine($"JSON Serialization {iterations}: {jsonTimer.Elapsed.TotalMilliseconds}ms");
Console.WriteLine($"Newtonsoft.Json Serialization {iterations}: {newtonsoftJsonTimer.Elapsed.TotalMilliseconds}ms");
Console.WriteLine();
}
static void SerializeXML(string xml, int iterations)
{
var xmlSerializer = new DataContractSerializer(typeof(Config));
for (var i = 0; i < iterations; i++)
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(xml));
var serialized = (Config)xmlSerializer.ReadObject(stream);
}
}
static void SerializeJSON(string json, int iterations)
{
var jsonSerializer = new DataContractJsonSerializer(typeof(Config));
for (var i = 0; i < iterations; i++)
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
var serialized = (Config)jsonSerializer.ReadObject(stream);
}
}
static void SerializeNewtonsoftJson(string json, int iterations)
{
// Newtonsoft.Json serializer.
var newtonsoftJsonSerializer = new JsonSerializer();
for (var i = 0; i < iterations; i++)
{
using var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
using var reader = new JsonTextReader(new StreamReader(stream, new UTF8Encoding()));
var serialized = newtonsoftJsonSerializer.Deserialize<Config>(reader);
}
}
public class Config
{
public string value;
public DateTime DateStamp;
public int counter;
public Guid Id;
}
以下是基准测试结果:
XML Serialization 1: 4.3958ms
JSON Serialization 1: 3.3516ms
Newtonsoft.Json Serialization 1: 37.5018ms
XML Serialization 1000: 11.137ms
JSON Serialization 1000: 6.8425ms
Newtonsoft.Json Serialization 1000: 2.4205ms
XML Serialization 10000: 39.1409ms
JSON Serialization 10000: 56.8301ms
Newtonsoft.Json Serialization 10000: 21.352ms
XML Serialization 100000: 358.903ms
JSON Serialization 100000: 519.5981ms
Newtonsoft.Json Serialization 100000: 197.7238ms
XML Serialization 1000000: 3585.8248ms
JSON Serialization 1000000: 5256.336ms
Newtonsoft.Json Serialization 1000000: 2006.7546ms
XML Serialization 10000000: 36326.6082ms
JSON Serialization 10000000: 53260.1445ms
Newtonsoft.Json Serialization 10000000: 20506.9946ms
正如您所看到的,在Newtonsoft.Json中进行单个序列化非常缓慢-几乎慢了10倍。 然而,在多次迭代中,这个数字显著下降,Newtonsoft.Json成为明显的赢家。
同样,这不是科学的,也不是现实的,但确实给出了使用Newtonsoft.Json进行序列化性能的一些想法。
如果有人想指出我的答案问题,提供改进其中任何一个的性能建议,请让我知道。
Json有时比XML对人类不太易读,但是生成的文件大小较小。因此,如果您需要通过网络发送文件,则Json可能是更好的选择;或者如果您想要能够阅读它,则XML更好。另一个好处是,在.NET 4中,您拥有动态关键字,并且可以直接将Json转换为C#对象。
序列化的成本大致相同。不太可能有明显的差异。使用您的用户最舒适修改的格式(因为它是配置文件)。
真正的性能差异可能发生在您需要通过网络发送JSON或XML时。然后,性能取决于您要发送多少内容,由于JSON通常比XML更简洁,因此通常在网络上表现更好。