fastjson JSON.toJSON的序列化性能问题

ftf50wuq  于 2022-10-22  发布在  其他
关注(0)|答案(8)|浏览(226)

下面的程序把一个POJO进行序列化
POJO obj = JSON.toJSON(obj);

问题

我们在生产代码发现这段代码在极端情况下会有性能问题,耗时长达10几秒之久.
我还没来得及追踪源码去发现问题出在哪里,先把代码贴在这里,如果知道为什么可以说一下.

关于下面代码的简单解释:

起一个50的线程池,然后不断的并发调用JSON.toJSON(obj)方法,并且统计每次调用的耗时,并把最大的耗时记下来.

样例输出

count = 1083780
maxTime = 8664246821 (8秒多)

PS. 相反的过程 JSON.toJavaObject(json, clazz); 也有性能问题

测试代码

public class FastJsonPerfTest {

  public static AtomicLong maxTime = new AtomicLong();

  public static void main(String[] args) throws InterruptedException, ExecutionException {

    ExecutorService executorService = Executors.newFixedThreadPool(50);

    OrderSource source = JSON.parseObject(
        "{\"field7\":0,\"field8\":1,\"field9\":3072917514,\"field3\":\"1126892\",\"field11\":\"\",\"field2\":\"E20170108114143057876586\",\"field6\":\"\",\"field4\":\"\",\"field1\":76796,\"field5\":\"\"}",
        OrderSource.class);

    int total = 100000000;
//    List<Future<OrderSourceResult>> list = new ArrayList<>(total);

    AtomicLong count = new AtomicLong();

    Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
      System.out.println("count = " + count);
      System.out.println("maxTime = " + maxTime);
    }, 0, 500, TimeUnit.MILLISECONDS);

    for (int i = 0; i < total; i++) {
      Future<?> future = executorService.submit(
          () -> {
            long start = System.nanoTime();
            try {
              JSON.toJSON(source);
            } finally {
              count.incrementAndGet();
              checkAndUpdate(maxTime, (System.nanoTime() - start));
            }
          });
//      list.add(future);
    }

//    for (Future<OrderSourceResult> orderSourceResultFuture : list) {
//      orderSourceResultFuture.get();
//    }
  }

  public static void checkAndUpdate(AtomicLong atomicLong, long value) {
    while (true) {
      long origin = atomicLong.get();
      if (value > origin) {
        if (atomicLong.compareAndSet(origin, value)) {
          break;
        }
      } else {
        break;
      }
    }
  }
} 

class OrderSource implements Serializable {

  private Long field1;
  private String field2;
  private Long field3;
  private String field4;
  private String field5;
  private String field6;
  private Long field7;
  private Integer field8;
  private String field9;
  private Long field10;
  private String field11;

  public Long getField1() {
    return field1;
  }

  public void setField1(Long field1) {
    this.field1 = field1;
  }

  public String getField2() {
    return field2;
  }

  public void setField2(String field2) {
    this.field2 = field2;
  }

  public Long getField3() {
    return field3;
  }

  public void setField3(Long field3) {
    this.field3 = field3;
  }

  public String getField4() {
    return field4;
  }

  public void setField4(String field4) {
    this.field4 = field4;
  }

  public String getField5() {
    return field5;
  }

  public void setField5(String field5) {
    this.field5 = field5;
  }

  public String getField6() {
    return field6;
  }

  public void setField6(String field6) {
    this.field6 = field6;
  }

  public Long getField7() {
    return field7;
  }

  public void setField7(Long field7) {
    this.field7 = field7;
  }

  public Integer getField8() {
    return field8;
  }

  public void setField8(Integer field8) {
    this.field8 = field8;
  }

  public String getField9() {
    return field9;
  }

  public void setField9(String field9) {
    this.field9 = field9;
  }

  public Long getField10() {
    return field10;
  }

  public void setField10(Long field10) {
    this.field10 = field10;
  }

  public String getField11() {
    return field11;
  }

  public void setField11(String field11) {
    this.field11 = field11;
  }
}
pgpifvop

pgpifvop2#

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.20</version>
</dependency>
u3r8eeie

u3r8eeie3#

@landawn loop设置为100W试试?

uz75evzq

uz75evzq4#

@landawn 平均时间当然没什么问题.

我的问题的是关注短板,也就是最差的情况,极端的情况,因为一旦出现这种情况,就意味着超时.

看你的结果,也有一次序列化时间超过383.287 ms的吧?

如果在增大并发,扩大循环次数,应该还有更差的短板~

xmq68pz9

xmq68pz95#

有什么问题你直接说.

ifsvaxew

ifsvaxew6#

我也遇到了一样的问题,在多线程环境下,每个线程第一次序列化的耗时非常高,第2次开始就好了。怎么解?这样导致我应用刚启动后,第一次请求百分百超时,因为我的请求链路上有很多JSON序列化操作。

eaf3rand

eaf3rand7#

测试代码

public static void main(String[] args) {
        ExecutorService pool = ThreadPools.newFixedPool(64, 1, "test");
        for (int i = 0; i < 64; i++) {
            Map<String, String> map = new HashMap<>();
            map.put("id", "11");
            pool.submit(() -> {
                // 第1次
                {
                    long s = System.nanoTime();
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.putAll(map);
                    jsonObject.toJavaObject(TaskNode.class);
                    long e = System.nanoTime();
                    long cost = (e - s) / 1000_000;
                    System.out.println("第1次:" + cost);
                }
                // 第2次
                {
                    long s = System.nanoTime();
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.putAll(map);
                    jsonObject.toJavaObject(TaskNode.class);
                    long e = System.nanoTime();
                    long cost = (e - s) / 1000_000;
                    System.out.println("第2次:" + cost);
                }
            });
        }
    }

测试结果:

d8tt03nd

d8tt03nd8#

所以看平均耗时,没有任何意义。只有第一次耗时很高,后面都无限趋近于0,一平均当然很低啦

相关问题