下面的程序把一个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;
}
}
8条答案
按热度按时间z5btuh9x1#
什么版本?
pgpifvop2#
u3r8eeie3#
@landawn loop设置为100W试试?
uz75evzq4#
@landawn 平均时间当然没什么问题.
我的问题的是关注短板,也就是最差的情况,极端的情况,因为一旦出现这种情况,就意味着超时.
看你的结果,也有一次序列化时间超过383.287 ms的吧?
如果在增大并发,扩大循环次数,应该还有更差的短板~
xmq68pz95#
有什么问题你直接说.
ifsvaxew6#
我也遇到了一样的问题,在多线程环境下,每个线程第一次序列化的耗时非常高,第2次开始就好了。怎么解?这样导致我应用刚启动后,第一次请求百分百超时,因为我的请求链路上有很多JSON序列化操作。
eaf3rand7#
测试代码
测试结果:
d8tt03nd8#
所以看平均耗时,没有任何意义。只有第一次耗时很高,后面都无限趋近于0,一平均当然很低啦