Json和Xml序列化,什么性能更好?

zsohkypk  于 2022-11-19  发布在  其他
关注(0)|答案(7)|浏览(240)

我必须在文件中存储一些配置信息。在C#代码中,配置数据由类表示,在文件中,我将以json或xml格式保存该类。那么,序列化json或xml的最佳性能是什么?

h43kikqp

h43kikqp1#

好了,不用猜了,我有答案了。下面是测试程序:

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

JSON在一次迭代后总是快一点,1000次迭代后就没有什么区别了,10000次迭代后,XML明显更快。
在这一点上,我不能解释为什么JSON一次一个时会更快,但XML重复时会更快。可能是由于缓存或库中的一些奇特之处。您可以看到,JsonSerializer线性扩展,迭代次数增加10个数量级,运行时间线性增加10个数量级。XmlSerializer的行为不同,其性能并不以线性方式缩放。
我重复了几次,都得到了同样的结果。
因此,如果只解析一个对象一次,那么JSON会稍微好一点。但是如果重复解析对象,那么XML可能会表现得更好。虽然我还没有测试如果对象值随着每次迭代而改变会发生什么,但这可能会造成不同。
另外请注意,我在这里使用的是原生的Runtime.Serialization库。其他库可能会产生不同的结果。
编辑:我只是在每次调用字符串时生成一个新的Guid和随机Int时尝试了这个方法。这对单次或10000次迭代测试没有什么区别。但是对于1000次迭代,JSON大约快了1ms。所以看起来XML序列化器确实在缓存值。

hgncfbus

hgncfbus2#

当我在.NET应用程序中查找配置时,我希望在某处找到一个名为MyApp.exe.config的XML文件。
坚持使用principle of least surprise,我更倾向于XML序列化而不是JSON。还有一个额外的好处是,XML格式的配置可以适应Configuration API的工作。否则两者都有同样的支持:平台不可知、良好的解析器、基于文本等。
只有当性能成为一个问题时,它才是一个问题。我喜欢在编写代码之前识别潜在的问题,但这通常是由体系结构决策引入的性能问题。像这样的东西,小而相当独立,如果它被证明是一个剖析中的问题,那么改变它并不困难。

d7v8vwbk

d7v8vwbk3#

Json的可读性可能比xml差一些,但是Json生成的文件更小。所以如果你需要通过网络发送文件,Json可能是更好的选择,或者如果你想能够阅读它,XML更好。另一个好处是,在.NET 4中你有dynamic关键字,你可以直接将你的Json转换成C#对象。

cotxawn7

cotxawn74#

在我看来,一切都取决于您需要做什么以及如何实现,这里有一篇比较JSON和XML很好的文章。
祝你好运
https://dzone.com/articles/json-vs-xml-net-developer%e2%80%99s

lfapxunr

lfapxunr5#

这是对2014年@Wedge答案的更新。
它是用.NET 6.0写的,也利用了流行的Newtonsoft.Json库,我还增加了迭代次数,以前是1、1,000、10,000,这个版本现在也是100,000、10,000,000、1,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的序列化性能的一些概念。
如果有人想指出我的答案中的问题,提出改进其中任何一个的建议,请让我知道。

bgtovc5b

bgtovc5b6#

序列化的成本大致相同。这不太可能是一个明显的差异。使用您的用户将感到最舒适的修改格式(因为它是一个配置文件)。
真实的的性能差异可能发生在需要通过网络发送JSON或XML时,性能取决于发送的内容的多少,由于JSON通常比XML更简洁,因此它在网络上的性能通常更好。

vc9ivgsu

vc9ivgsu7#

这基本上与answer上解释的代码相同,但由于我读到的每个答案似乎都只运行代码一次,并且从1次迭代开始,似乎有一个结论是运行1次迭代比1000次迭代更糟糕,因此我决定运行它多次,结果如下:
如果从100,000开始,您在第一次迭代中获得相同的预期性能:
我不能给予一个非常知情的答复,所以我保持原样。

相关问题