开发者社区> 问答> 正文

java对内存居高不下的问题

场景:
一个文件由2672094万条数据,每个数据信息以|分割。例如:
1926717087|1||BOC_EPOS_CREDIT_ZHBZ8011|2014-08-09|1540.00|||1.54||0||||
首先,按“|”把每条数据拆开,分别对每一列进行格式校验,如非空,日期格式,金额格式(小数点两位,非负数)。每条都进行校验。
其次,进行业务校验,校验其是否符合某个规则。每条都需要校验。不合法数量较多,大约三分之一,不合法的数据通过异常返回。
每条进行业务校验的同时,还会返回一些数据,例如,上面一条数据,传过去之后,可能还会返回10个字段的数据。
最后,将不合法的数据插入bad表,将合法的数据插入good表(50多个字段)。
问题:格式校验较快,不到20秒。业务校验比较慢。其中每条业务校验时,我都会把传递的参数记录下来,如:
2016-05-14 15:45:00 [WARN] args: clearDate:2014-08-06 DeptBI:OTHER_BANGFUTONG DeptID:31 Matcher:I0** sucDate:2016-05-16 TxAmt:100
现在程序大约执行了6个小时还没有执行完,并且jvisualvm(JDK自带工具)检测jvm参数,显示堆内存的使用量已经达到10G(设置tomcat对内存为10G)。
并且用top命令查看,tomcat占的进程的CPU到达1200多(此时程序执行一段时间,暂停一段时间,我怀疑是在进行垃圾回收,但是回收效果不明显)
我现在怀疑性能出现在如下几个方面:
1、日志太多,不应每条记录日志。
2、业务校验程序写的有问题
3、不明白的问题,堆内存最后一直10G不下降?
不知道大家对这个有什么看法

展开
收起
落地花开啦 2016-05-31 13:55:25 3250 0
1 条回答
写回答
取消 提交回答
  • 喜欢技术,喜欢努力的人

    1、NIO:采用NIO的MappedByteBuffer类读写,并且不要每处理一行就写入一次,批量写入
    2、多线程:由一个专门的调度线程负责读取文件里的记录,然后插入任务队列,再由一个线程池去任务队列里取任务,然后处理业务逻辑校验什么的,线程池可以直接用Concurrent包里的线程池实现
    3、异常:慎用异常,异常是重量级对象,非法数据不要通过异常返回,可自定义错误码返回,异常对性能影响很大的(单次可能不明显,但对你这种大数据量批处理任务就很可观了)
    4、仔细检查业务校验逻辑代码,看能不能调优,原因跟3一样,细节的优化对单次性能提升不明显,但累加效应就很可观了。一些小的优化细节建议:
    使用性能更优的字符串方法,比如谨慎使用JDK1.6的substring,使用不当可能会导致内存不能释放,应该用new String(str.substring(..))、优先用StringTokenizer而不是split进行字符串拆分、优先使用charAt和indexOf、使用StringBuilderStringBuffer处理字符串拼接并提供预估长度参数
    尽量保证代码对GC友好,比如尽量让对象小而生命周期短,尽量不要让老年代的对象引用年轻代对象(避免YGC时卡表扫描代价太高),比如static变量引用方法局部变量应该避免
    逻辑能简化则简化,看看能不能用一个正则进行完全匹配,正则匹配效率可能高些

    2019-07-17 19:21:50
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
基于Java容器的多应用部署技术实践 立即下载
从《阿里巴巴Java开发手册》编写推广谈技术成长 立即下载
云服务器ECS内存增强型实例re6全新发布 立即下载