You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何C#使用System.Text.Json执行JSON反序列化性能远低于Go?

性能差异的核心原因

你目前的C#实现存在两个严重影响性能的低级错误,和Go的测试条件也不对等,才会出现上百倍的性能差距:

  • 重复实例化JsonSerializerOptions:你每次调用FromJson方法都会新建一个JsonSerializerOptions对象,这个实例的初始化会触发对目标类的反射扫描、序列化元数据构建等重开销操作,10万次循环等于重复执行了10万次元数据生成逻辑,这部分占了99%以上的耗时。JsonSerializerOptions是线程安全的,完全可以静态缓存复用,不需要每次新建。
  • 测试构建类型不对等:你直接执行dotnet run .默认运行的是Debug构建,没有开启代码优化,还附带调试符号,性能本身就比Release构建低3~10倍不等,而你运行的Go二进制是经过编译优化的Release版本,测试条件完全不对等。

优化方案

1. 缓存序列化配置

修改BinanceTradeUpdate类的FromJson方法,把JsonSerializerOptions改为静态只读对象复用:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace jsonperf
{
    public class BinanceTradeUpdate
    {
        // 原有属性代码保持不变
        [JsonPropertyName("e")]
        public string EventType { get; set; }
        [JsonPropertyName("E")]
        public long EventUnixTimestamp { get; set; }
        [JsonIgnore]
        public DateTime EventTime => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(EventUnixTimestamp);
        [JsonPropertyName("s")]
        public string MarketSymbol { get; set; }
        [JsonPropertyName("t")]
        public long TradeId { get; set; }
        [JsonPropertyName("p")]
        public double Price { get; set; }
        [JsonPropertyName("q")]
        public double Quantity { get; set; }
        [JsonPropertyName("b")]
        public long BuyerOrderId { get; set; }
        [JsonPropertyName("a")]
        public long SellerOrderId { get; set; }
        [JsonPropertyName("T")]
        public long TradeUnixTimestamp { get; set; }
        [JsonIgnore]
        public DateTime TradeTime => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(TradeUnixTimestamp);
        [JsonPropertyName("m")]
        public bool BuyerIsMarketMaker { get; set; }
        [JsonPropertyName("M")]
        public bool UndocumentedFlag { get; set; }

        // 新增:静态缓存序列化配置,全局只初始化一次
        private static readonly JsonSerializerOptions _jsonSerializeOptions = new JsonSerializerOptions()
        {
            NumberHandling = JsonNumberHandling.AllowReadingFromString
        };

        public static BinanceTradeUpdate FromJson(string json)
        {
            // 复用静态配置,不再每次新建
            return JsonSerializer.Deserialize<BinanceTradeUpdate>(json, _jsonSerializeOptions);
        }
    }
}

2. 用Release模式运行测试

执行以下命令运行优化后的Release版本:

dotnet run --configuration Release

3. 可选:使用源生成器进一步优化

如果要完全消除运行时反射开销,可以使用System.Text.Json提供的源生成器功能,在编译阶段就生成好序列化/反序列化代码:
首先将BinanceTradeUpdate改为partial类,加上JsonSerializable特性:

[JsonSerializable(typeof(BinanceTradeUpdate))]
public partial class BinanceTradeUpdate
{
    // 原有属性代码不变
}

然后修改FromJson方法使用预生成的序列化上下文:

public static BinanceTradeUpdate FromJson(string json)
{
    return JsonSerializer.Deserialize(json, JsonContext.Default.BinanceTradeUpdate);
}

优化后效果

完成前两项修改后,C#版本的运行耗时就会降到和Go版本同一水平,不会再出现百倍差距,使用源生成器优化后性能还能再提升10%~20%。

内容的提问来源于stack exchange,提问作者Benj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 22:57:04