您好,登錄后才能下訂單哦!
Java性能優(yōu)化中如何進(jìn)行壓縮,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。
在微服務(wù)調(diào)用,如果需要傳入的內(nèi)容過(guò)長(zhǎng),壓縮是個(gè)不錯(cuò)的辦法,能提高傳輸?shù)乃俣?。壓縮有很多方法,一種方法是在傳輸對(duì)象的屬性名字上做調(diào)整,盡量減少傳輸報(bào)文大小,這比較適合傳輸?shù)氖荍SON或者XML,比如
public class OrderRequest{ private String orderId; private String userId; }
如果使用JSON傳輸,內(nèi)容是
{"orderId":xxx,"userId":yyyyy}
可以調(diào)整為
public class OrderRequest{ private String oid; private String uid; }
使用JSON傳輸 {"oid":xxx,"uid":yyyyy},這種調(diào)整,顯然傳輸報(bào)文大小體積小一點(diǎn)。也可以對(duì)傳輸對(duì)象的一些字段做合并,比如“訂單狀態(tài)“,"用戶狀態(tài)","測(cè)試訂單"合并成一個(gè)int類型,通過(guò)“位“來(lái)區(qū)分狀態(tài)
public class OrderRequest{ //用戶狀態(tài) private int userStatus; //訂單狀態(tài) private int orderStatus; //測(cè)試訂單 private int testFlag }
改成如下,需要通過(guò)位運(yùn)算獲取訂單的各個(gè)狀態(tài)
public class OrderRequest { /** * 0位表示是否測(cè)試訂單,1-4位節(jié)表示用戶狀態(tài),5-8位表示訂單狀態(tài) */ int s; public boolean isTest(){ //取出第1位的值 return (status&0b1)==1; } public int getUserStatus(){ // 右移1,取出1-4位的值 return (status>>1&0b1111); } public int getOrderStatus(){ //右移5,取出5-8位的值 return (status>>5&0b1111); } }
這樣,OrderRequest本來(lái)需要3個(gè)int類型,總計(jì)12個(gè)字節(jié)來(lái)保存的訂單狀態(tài),現(xiàn)在只需要4個(gè)字節(jié)保存即可。如果有更多的狀態(tài),也可以用s值的剩下的位來(lái)表示。比如,訂單新增一個(gè)狀態(tài)表示是否是包含大件,可以用第9位表示
public boolean isLargeProduct(){ return (status>>9&0b1)==1; }
如果s值是0b1_0100_0110_1(對(duì)應(yīng)的10進(jìn)制653),那么isTest返回true,getUerStatus返回6,getOrderStatus返回4,isLargeProduct返回true
還有一種壓縮方法是在傳輸協(xié)議上進(jìn)行壓縮,比如JSON就比XML更加節(jié)省,使用MessagePack又比JSON更加節(jié)省空間,關(guān)于MessagePack用法,會(huì)在第5章用一節(jié)詳細(xì)介紹。
在傳輸內(nèi)容過(guò)多的時(shí)候,可以考慮對(duì)內(nèi)容進(jìn)行壓縮,對(duì)內(nèi)容進(jìn)行壓縮再傳送有如下好處
壓縮后減少網(wǎng)絡(luò)傳送的字節(jié),節(jié)約了帶寬,網(wǎng)絡(luò)可以同時(shí)傳送的內(nèi)容更多了
相比于壓縮耗時(shí),網(wǎng)絡(luò)傳送更加耗時(shí)。尤其是現(xiàn)在的分布式系統(tǒng),服務(wù)器非常便宜,可以無(wú)限擴(kuò)展,從數(shù)十臺(tái)服務(wù)器到數(shù)萬(wàn)臺(tái)服務(wù)都可以,然而帶寬有限且價(jià)格不菲,有些企業(yè)專網(wǎng)帶寬只有1M,非常小。
壓縮有各種算法,會(huì)輸出不同的壓縮比的內(nèi)容,以及壓縮耗時(shí)也不一樣,本節(jié)選取zip,針對(duì)5K,20K,100k的做一個(gè)性能測(cè)試。一般來(lái)說(shuō),壓縮比越大,越耗時(shí)。在實(shí)際分布式系統(tǒng)調(diào)用,需要根據(jù)業(yè)務(wù)需求,確定采用什么樣的壓縮算法。
壓縮會(huì)使用JDK自帶的zip包中的Deflater類進(jìn)行壓縮,提供了最快壓縮BEST_SPEED(值是1),最大壓縮比BEST_COMPRESSION(值是9),還有默認(rèn)壓縮DEFAULT_COMPRESSION(值是-1)
//ZipUtil.java public static byte[] zip(byte[] bs) throws IOException { return compress(bs,DEFAULT_COMPRESSION); } public static byte[] compress(byte[] input, int compressionLevel ) throws IOException { //zip壓縮 Deflater compressor = new Deflater(compressionLevel, false); //壓縮內(nèi)容 compressor.setInput(input //壓縮結(jié)束 compressor.finish(); //獲取壓縮內(nèi)容 ByteArrayOutputStream bao = new ByteArrayOutputStream(); //一個(gè)緩沖 byte[] readBuffer = new byte[1024]; int readCount = 0; //如果壓縮內(nèi)容,則循環(huán) while (!compressor.finished()) { readCount = compressor.deflate(readBuffer); if (readCount > 0) { bao.write(readBuffer, 0, readCount); } } compressor.end(); return bao.toByteArray(); }
可以測(cè)試一個(gè)100k報(bào)文,對(duì)于三種壓縮比,有如下數(shù)據(jù),說(shuō)明ZIP的默認(rèn)壓縮級(jí)別已經(jīng)足夠好 DEFAULT_COMPRESSION 壓縮后是34.8K BEST_SPEED 壓縮是39K BEST_COMPRESSION 壓縮后是34.7K
為了測(cè)試壓縮性能,通過(guò)Content工具類分別生成5K,20K,100K報(bào)文供測(cè)試,并且分別測(cè)試默認(rèn)壓縮,最快壓縮和最好壓縮。
// ZipTest.java byte[] k5 = null; byte[] k20 = null; byte[] k100 = null; //默認(rèn),最快,最好壓縮 @Param({"-1", "1", "9"}) int level; @Setup public void init() { Content content = new Content(); this.k5 = content.genContentBySize(1000 * 5); this.k20 = content.genContentBySize(1000 * 20); this.k100 = content.genContentBySize(1000 * 100); } @Benchmark public byte[] k5() throws IOException { return ZipUtil.compress(k5, level); } @Benchmark public byte[] k20() throws IOException { return ZipUtil.compress(k20, level); } @Benchmark public byte[] k100() throws IOException { return ZipUtil.compress(k100, level); }
JMH測(cè)試結(jié)果如下??梢钥吹郊词?0K報(bào)文內(nèi)容,壓縮的速度還是非常快的。在不到1毫秒。100K報(bào)文,則需要較長(zhǎng)時(shí)間,默認(rèn)壓縮(-1)需要4毫秒左右。
Benchmark (level) Score Score error Units c.i.c.c.ZipTest.k100 -1 4.467 0.233 ms/op c.i.c.c.ZipTest.k100 1 1.773 0.097 ms/op c.i.c.c.ZipTest.k100 9 5.028 0.152 ms/op c.i.c.c.ZipTest.k20 -1 0.571 0.016 ms/op c.i.c.c.ZipTest.k20 1 0.310 0.010 ms/op c.i.c.c.ZipTest.k20 9 0.592 0.023 ms/op c.i.c.c.ZipTest.k5 -1 0.157 0.008 ms/op c.i.c.c.ZipTest.k5 1 0.112 0.005 ms/op c.i.c.c.ZipTest.k5 9 0.151 0.003 ms/op
這個(gè)測(cè)試選用的是一篇文章作為壓縮內(nèi)容,你需要根據(jù)你的業(yè)務(wù)情況,用真實(shí)的報(bào)文來(lái)做壓縮測(cè)試,事實(shí)上,如果是XML或者JSON報(bào)文,有著非常大的壓縮比。
本節(jié)選擇了zip壓縮方式,還有其他可選方式,比如gzip,bzip2,7z等等,可以使用開(kāi)源庫(kù)Apache Commons Compress進(jìn)行壓縮,在筆者測(cè)試后,發(fā)現(xiàn)zip還是一種壓縮比和性能都比較好的方式。7z具有最大的壓縮比,但壓縮時(shí)長(zhǎng)超過(guò)百毫秒,在實(shí)時(shí)的業(yè)務(wù)系統(tǒng)中是不可接受的。
對(duì)于解壓來(lái)說(shuō),無(wú)論采用何種壓縮方式,何種壓縮級(jí)別,解壓需要的時(shí)間都是非常少的。
看完上述內(nèi)容,你們掌握J(rèn)ava性能優(yōu)化中如何進(jìn)行壓縮的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。