日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
ObjectMapper,別再像個(gè)傻子一樣一直New了!

很多同學(xué)發(fā)現(xiàn),jackson并沒有類似fastjson的JSON.parseObjec這樣的,確實(shí)看起來很快的方法。要想解析json,你不得不new一個(gè)ObjectMapper,來處理真正的解析動(dòng)作。

創(chuàng)新互聯(lián)是專業(yè)的平武網(wǎng)站建設(shè)公司,平武接單;提供成都做網(wǎng)站、成都網(wǎng)站制作,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行平武網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!

就像下面這樣。

public String getCarString(Car car){
ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(car);
return str;
}

這種代碼就在CV工程師手中遍地開了花。

神奇。

這代碼有問題么?

你要說它有問題,它確實(shí)能正確的執(zhí)行。你要說它沒問題,在追求性能的同學(xué)眼里,這肯定是一段十惡不赦的代碼。

一般的工具類,都是單例的,同時(shí)是線程安全的。ObjectMapper也不例外,它也是線程安全的,你可以并發(fā)的執(zhí)行它,不會(huì)產(chǎn)生任何問題。

這段代碼,ObjectMapper在每次方法調(diào)用的時(shí)候,都會(huì)生成一個(gè)。那它除了造成一定的年輕代內(nèi)存浪費(fèi)之外,在執(zhí)行時(shí)間上有沒有什么硬傷呢?

new和不new,真的區(qū)別有那么大么?

有一次,xjjdog隱晦的指出某段被頻繁調(diào)用的代碼問題,被小伙伴怒吼著拿出證據(jù)。

證據(jù)?這得搬出Java中的基準(zhǔn)測(cè)試工具JMH,才能一探究竟。

JMH(the Java Microbenchmark Harness) 就是這樣一個(gè)能夠做基準(zhǔn)測(cè)試的工具。如果你通過我們一系列的工具,定位到了熱點(diǎn)代碼,要測(cè)試它的性能數(shù)據(jù),評(píng)估改善情況,就可以交給JMH。它的測(cè)量精度非常高,最高可達(dá)到納秒的級(jí)別。

JMH是一個(gè)jar包,它和單元測(cè)試框架JUnit非常的像,可以通過注解進(jìn)行一些基礎(chǔ)配置。這部分配置有很多是可以通過main方法的OptionsBuilder進(jìn)行設(shè)置的。

上圖是一個(gè)典型的JMH程序執(zhí)行的內(nèi)容。通過開啟多個(gè)進(jìn)程,多個(gè)線程,首先執(zhí)行預(yù)熱,然后執(zhí)行迭代,最后匯總所有的測(cè)試數(shù)據(jù)進(jìn)行分析。在執(zhí)行前后,還可以根據(jù)粒度處理一些前置和后置操作。

JMH測(cè)試結(jié)果

為了測(cè)試上面的場(chǎng)景,我們創(chuàng)造了下面的基準(zhǔn)測(cè)試類。分為三個(gè)測(cè)試場(chǎng)景:

  • 直接在方法里new ObjectMapper
  • 在全局共享一個(gè)ObjectMapper
  • 使用ThreadLocal,每個(gè)線程一個(gè)ObjectMapper

這樣的測(cè)試屬于cpu密集型的。我的cpu有10核,直接就分配了10個(gè)線程的并發(fā),cpu在測(cè)試期間跑的滿滿的。

@BenchmarkMode({Mode.Throughput})
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@Threads(10)
public class ObjectMapperTest {
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";

@State(Scope.Benchmark)
public static class BenchmarkState {
ObjectMapper GLOBAL_MAP = new ObjectMapper();
ThreadLocal GLOBAL_MAP_THREAD = new ThreadLocal<>();
}

@Benchmark
public Map globalTest(BenchmarkState state) throws Exception{
Map map = state.GLOBAL_MAP.readValue(json, Map.class);
return map;
}


@Benchmark
public Map globalTestThreadLocal(BenchmarkState state) throws Exception{
if(null == state.GLOBAL_MAP_THREAD.get()){
state.GLOBAL_MAP_THREAD.set(new ObjectMapper());
}
Map map = state.GLOBAL_MAP_THREAD.get().readValue(json, Map.class);
return map;
}

@Benchmark
public Map localTest() throws Exception{
ObjectMapper objectMapper = new ObjectMapper();
Map map = objectMapper.readValue(json, Map.class);
return map;
}

public static void main(String[] args) throws Exception {
Options opts = new OptionsBuilder()
.include(ObjectMapperTest.class.getSimpleName())
.resultFormat(ResultFormatType.CSV)
.build();

new Runner(opts).run();
}
}

測(cè)試結(jié)果如下。

Benchmark                                Mode  Cnt         Score         Error  Units
ObjectMapperTest.globalTest thrpt 5 25125094.559 ± 1754308.010 ops/s
ObjectMapperTest.globalTestThreadLocal thrpt 5 31780573.549 ± 7779240.155 ops/s
ObjectMapperTest.localTest thrpt 5 2131394.345 ± 216974.682 ops/s

從測(cè)試結(jié)果可以看出,如果我們每次調(diào)用都new一個(gè)ObjectMapper,每秒可以執(zhí)行200萬次JSON解析;如果全局使用一個(gè)ObjectMapper,則每秒可以執(zhí)行2000多萬次,速度足足快了10倍。

如果使用ThreadLocal的方式,每個(gè)線程給它分配一個(gè)解析器,則性能會(huì)有少許上升,但也沒有達(dá)到非??鋸埖牡夭?。

所以在項(xiàng)目中寫代碼的時(shí)候,我們只需要保證有一個(gè)全局的ObjectMapper就可以了。

當(dāng)然,由于ObjectMapper有很多的特性需要配置,你可能會(huì)為不同的應(yīng)用場(chǎng)景分配一個(gè)單獨(dú)使用的ObjectMapper??傊臄?shù)量不需要太多,因?yàn)樗蔷€程安全的。

End

所以結(jié)論就比較清晰了,我們只需要在整個(gè)項(xiàng)目里使用一個(gè)ObjectMapper就可以了,沒必要傻不拉幾的每次都new一個(gè),畢竟性能差了10倍。如果你的JSON有很多自定義的配置,使用全局的變量更能凸顯它的優(yōu)勢(shì)。

不要覺得這樣做沒有必要,保持良好的編碼習(xí)慣永遠(yuǎn)是好的。高性能的代碼都是點(diǎn)點(diǎn)滴滴積累起來的。不積跬步,無以至千里。不積小流,無以成江海,說的就是這個(gè)道理。

作者簡(jiǎn)介:小姐姐味道 (xjjdog),一個(gè)不允許程序員走彎路的公眾號(hào)。聚焦基礎(chǔ)架構(gòu)和Linux。十年架構(gòu),日百億流量,與你探討高并發(fā)世界,給你不一樣的味道。


本文名稱:ObjectMapper,別再像個(gè)傻子一樣一直New了!
文章位置:http://www.dlmjj.cn/article/dhjpdsd.html