记录一次 - 内存占用优化
某个导出,导出数据量过大总是导致OOM,但是根据需求,导出数据大小并没有那么大
按照导出数据的查询来看
SELECTg.inventory_code,g.visit_record_code,g.recovery_price AS transactionAmount
FROM
crm_goods g
...
...
三个字段大小预计大小100W数据应该是不大于100m的,但是现实是1个G都不够用,果断开启MAT,查看最大对象如下
震惊,100w个单纯对象声明,竟然占用了1.3GB内存,于是我测试了一下原对象全部字段和单纯查询三个字段声明100W个的差距
ArrayList<VisitGoodsInfoResp> visitGoodsInfoResps = new ArrayList<>(1000000);ArrayList<VisitGoodsInfoExport> visitGoodsInfoExports = new ArrayList<>(1000000);for (int i = 0; i < 1000000; i++) {VisitGoodsInfoResp visitGoodsInfoResp1 = new VisitGoodsInfoResp();visitGoodsInfoResps.add(visitGoodsInfoResp1);VisitGoodsInfoExport visitGoodsInfoExport1 = new VisitGoodsInfoExport();visitGoodsInfoExports.add(visitGoodsInfoExport1);}
MAT分析如下
两个竟然差距如此之大,我们使用jol
工具看下两个对象的差距
com.VisitGoodsInfoResp object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 05 c2 00 f8 (00000101 11000010 00000000 11111000) (-134168059)12 4 java.lang.String VisitGoodsInfoResp.inventoryCode null16 4 java.lang.String VisitGoodsInfoResp.name null...... 省略N个字段...652 4 java.lang.String VisitGoodsInfoResp.dockingCustomerDeptName null656 4 java.time.LocalDateTime VisitGoodsInfoResp.registrationTime null660 4 java.math.BigDecimal VisitGoodsInfoResp.salesTransitCount null
Instance size: 664 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes totalcom.VisitGoodsInfoExport object internals:OFFSET SIZE TYPE DESCRIPTION VALUE0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)8 4 (object header) 8b c3 00 f8 (10001011 11000011 00000000 11111000) (-134167669)12 4 java.lang.String VisitGoodsInfoExport.inventoryCode null16 4 java.math.BigDecimal VisitGoodsInfoExport.transactionAmount null20 4 java.lang.String VisitGoodsInfoExport.visitRecordCode null
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
可以看出一个声明为24bytes
一个为664bytes
,这个还是开启了指针压缩的,若是堆栈内存超过32GB,无法施行压缩,则会多占用更多内存。由此可见,虽然java已经很大限度的帮我们管理内存,但是在编程过程中涉及到大数据梁的时候还是要有对应的空间意识的。