首页 > 解决方案 > 如何使用高性能解析器解析 Java 中的 JSON?

问题描述

我的输入是一个大约有的数组。每秒接收 2,000 个元素,有时每秒接收几次。数组的每个元素都有 3 个大小数。

Jackson (com.fasterxml) 是其他亚毫秒应用程序中最慢的部分,需要 15 毫秒(平均)。慢函数是 objectMapper.readValue(text, MyDto.class);

使用基于子字符串的自定义 JSON 解析算法时,需要几微秒。使用 ObjectMapper 是 15 毫秒。

通过子字符串解析 JSON 是一种不好的做法,因为代码很冗长并且容易出现错误。

你会用什么来解析 JSON?要求是一个非常快速的算法。

https://github.com/ngs-doo/dsl-json我找到了 DSL json,但不知道如何将带有 JSON 的字符串解析到我的 DTO 中。我还没有找到一个简单的快速算法来将 JSON 从 String 解析为 DTO。

编辑:要解析的输入位于:

https://pastebin.com/831YtBdq

代码:

public class BitstampOrderBook {
    private long timestamp;
    private List<List<BigDecimal>> bids;
    private List<List<BigDecimal>> asks;

    public BitstampOrderBook() {

    }

    public BitstampOrderBook(long timestamp, List<List<BigDecimal>> bids, List<List<BigDecimal>> asks) {
        this.timestamp = timestamp;
        this.bids = bids;
        this.asks = asks;
    }

    public long getTimestamp() {
        return timestamp;
    }

    public List<List<BigDecimal>> getBids() {
        return bids;
    }

    public List<List<BigDecimal>> getAsks() {
        return asks;
    }
}

public class BitstampOrder {
    private BigDecimal price;

    private BigDecimal amount;

    private String datetime;

    private int id;

    @SerializedName("order_type")
    private int orderType;

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public BigDecimal getAmount() {
        return amount;
    }

    public void setAmount(BigDecimal amount) {
        this.amount = amount;
    }

    public String getDatetime() {
        return datetime;
    }

    public void setDatetime(String datetime) {
        this.datetime = datetime;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getOrderType() {
        return orderType;
    }

    public void setOrderType(int orderType) {
        this.orderType = orderType;
    }

    @Override
    public String toString() {
        return "BitStampOrder{" +
                "price=" + price +
                ", amount=" + amount +
                ", datetime='" + datetime + '\'' +
                ", id='" + id + '\'' +
                ", orderType='" + orderType + '\'' +
                '}';
    }
}

主要的:

BitstampOrderBook orderBook = objectMapper.readValue(jsonString, BitstampOrderBook.class);

JProfiler(杰克逊):

https://i.imgur.com/mjdbDQe.png

编辑2:

JProfiler(Gson):

https://i.imgur.com/WcHVhhd.png

从 JProfiler 可以看出,Gson 比 Jackson 快几倍。什么会比 Gson 更快?

标签: javajson

解决方案


  1. 不要使用字符串作为输入,而是立即解析从线路或磁盘读取的缓冲字节。
  2. 不要绑定到 BigDecimal,如果您需要以相同的精度将其值序列化回 JSON,请根据您的规则使用双原语 + 高效格式化程序。
  3. 为您的价格/金额对的内部数组使用 2-field 类。
  4. 切换到 Scala 并使用jsoniter-scala(声明:我是这个神奇库的贡献者)。

完成所有这些步骤,在一个线程中解析样本时,您将获得超过每秒 400Mb 的速度。

在此处查看GeoJSONReading解析大部分相同类型 JSON(数字的 2 值子数组的数组)的 结果


推荐阅读