背景起因:
记起以前的另一次也是关于内存的调优分享下
 
有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡。
我按经验开始调优,在每个关键步骤的加入如下代码耗时统计进行压测:
 
long startTime = System.currentTimeMillis();
 callRpc();   //这里比如调用RPC伪代码,当然还在插入数据库,中间件地方都加入统计
 long costTime = (System.currentTimeMillis() - startTime); 
 //统计600毫秒以上耗时
if (costTime > 600) { 
logger.warning("callRpc cost time:" + costTime); 
}
 
然后去grep日志, 最后神奇的发现各个地方都有超过600毫秒的地方...
然后各种定位的误导...
 
当然最终是解决了,原因是由于程序里使用了大对象导致
细分析,即使这种情况深研究也是分很多情况的
 
 
 
问题重现:
原因分析:

由于系统中使用了大对象,当并发来临,内存讲被吃紧,将有可能引起如下三种情况

第一种情况,系统内存够用(JVM内存未使用到SWAP内存),但JVM内存不够,最终导致JVM的频繁垃圾回收(FGC),严重影响性能 (stop the word)

第二种情况,系统内存不够,把JVM堆部分用到了SWAP,那么此时的垃圾回收需要把SWAP的内存换回到系统物理内存再进行JVM的垃圾回收。最大影响,导致每次GC的时间变得很久

第三种情况,  物理内存不够用, 大量JVM的堆内存被交换到SWAP后,垃圾回收时,把SWAP内存换回物理内存,但SWAP的内存又不会立即回, 此时可以观察到垃圾回收同时swap使用的内存会变大(其它部分内存要交换到SWAP里)

 
准备:
ubuntu 1G  4核
先关闭SWAP虚拟空间 sudo swapoff -a
 
java version "1.7.0_101"
apache-tomcat-8.5.9
设置好Tomcat的JVM内存:
JAVA_OPTS="-Xmx500m -Xms500m -Xmn200m -Xss228k -XX:+UseConcMarkSweepGC -XX:+UseParNewGC"
 
apache-jmeter-2.13 用于模拟HTTP请求压测,都是100条线程并发进行压测
 
 
 
模拟代码如下
 
/**
 * 模拟当系统中使用大对象时,对JVM造成的影响
 *
 * @author 包子(何锦彬). 2017.01.07
 * @QQ 277803242
 */
@WebServlet("/Test")
public class Test extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private Logger logger = Logger.getLogger(Test.class.getName());

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // use java heap 10m
        byte[] bts = new byte[1024 * 1024 * 10];// 代码段1
        long startTime = System.currentTimeMillis();
        // deal
        try {
            // 模拟业务花费时间
            Thread.sleep(500);
        } catch (InterruptedException e) {
        }

        // 理论上这里输出500附近
        long costTime = (System.currentTimeMillis() - startTime);
        if (costTime > 600) {
            logger.warning("cost time:" + costTime);
        }

        Writer out = response.getWriter();
        out.append("ok");
    }
 
 
先模拟正常的情况:
先注释掉"代码段1", 1W个请求下来,基本耗时都在500,一切正常,返回都是在500毫秒附近
 
垃圾回收情况,只发生了1次YGC,所以系统正常稳定...
 
 
 
模拟第一种情况:
放开“代码段1”,让每次请求都去堆内存申请10m的堆空间,同样是1W个请求,返回的平均值已经接近了2S
 
垃圾回收情况来看, 已经发生了1966次的FGC了, 在上面耗时158秒
 
 
 
模拟第二种情况:
把系统的SWAP打开,打开2G的SWAP,swapon -a
 
调大JVM参数,到1G,让JVM用到部分SWAP的空间
 
此时再让每次请求都去堆内存申请10m的堆空间,同样是1W个请求,性能已经低于第二种情况
 
 
垃圾回收来看,回收次数是1766次,比第二种情况发生的次数还要少, 但FGC耗费的时间已经是212秒,(虽然多了200m内存也没差距这么大,更精确看年轻代一样的内存,耗时也远超过)远超过第二种情况了
 
 
 
模拟第三种情况:
这种情况和我上一篇提到的类似,如果系统内存不够用时,系统将KIIL掉内存
 
 
总结:
 
1,频繁垃圾回收(FGC),会严重影响性能。而且会导致用统计耗时去寻找瓶颈出现失误
2,如果JVM堆用到了SWAP分区,将会严重影响到JVM的性能。故评估给JAVA分配内存时不要统计SWAP部分
3,SWAP分区开启可以有效防止进程因为内存问题而被系统杀掉
 
 
持续更新留言问题,解答疑问
 

欢迎关注我的公众号,专注重现各种线上的BUG

 

故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题的更多相关文章

  1. 【JVM】JVM内存结构 VS Java内存模型 VS Java对象模型

    原文:JVM内存结构 VS Java内存模型 VS Java对象模型 Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点.而且很多概念的名称看起来又那么相似,很多人会傻傻分不清 ...

  2. JVM自动内存管理机制——Java内存区域(下)

    一.虚拟机参数配置 在上一篇<Java自动内存管理机制——Java内存区域(上)>中介绍了有关的基础知识,这一篇主要是通过一些示例来了解有关虚拟机参数的配置. 1.Java堆参数设置 a) ...

  3. JVM内存结构 VS Java内存模型 VS Java对象模型

    前面几篇文章中, 系统的学习了下JVM内存结构.Java内存模型.Java对象模型, 但是发现自己还是对这三者的概念和区别比较模糊, 傻傻分不清楚.所以就有了这篇文章, 本文主要是对这三个技术点再做一 ...

  4. 硬件内存模型到 Java 内存模型,这些硬核知识你知多少?

    Java 内存模型跟上一篇 JVM 内存结构很像,我经常会把他们搞混,但其实它们不是一回事,而且相差还很大的,希望你没它们搞混,特别是在面试的时候,搞混了的话就会答非所问,影响你的面试成绩,当然也许你 ...

  5. 区分 JVM 内存结构、 Java 内存模型 以及 Java 对象模型 三个概念

    本文由 简悦 SimpRead 转码, 原文地址 https://www.toutiao.com/i6732361325244056072/ 作者:Hollis 来源:公众号Hollis Java 作 ...

  6. [转帖]JVM内存结构 VS Java内存模型 VS Java对象模型

    JVM内存结构 VS Java内存模型 VS Java对象模型 https://www.hollischuang.com/archives/2509 Java作为一种面向对象的,跨平台语言,其对象.内 ...

  7. 【转】JVM内存结构 VS Java内存模型 VS Java对象模型

    JVM内存结构 我们都知道,Java代码是要运行在虚拟机上的,而虚拟机在执行Java程序的过程中会把所管理的内存划分为若干个不同的数据区域,这些区域都有各自的用途. 其中有些区域随着虚拟机进程的启动而 ...

  8. Java内存管理:Java内存区域 JVM运行时数据区

    转自:https://blog.csdn.net/tjiyu/article/details/53915869 下面我们详细了解Java内存区域:先说明JVM规范定义的JVM运行时分配的数据区有哪些, ...

  9. Rails内存的问题 Java内存情况

    Rails内存的问题 Java内存情况 一个txt文件,100M,300万行,都是坐标数据: 需要进行坐标的变换.计算.比较: 在Rails中使用Ruby进行计算,会导致内存超过1.5G,最后溢出而亡 ...

随机推荐

  1. Socket聊天程序——服务端

    写在前面: 昨天在博客记录自己抽空写的一个Socket聊天程序的初始设计,那是这个程序的整体设计,为了完整性,今天把服务端的设计细化记录一下,首页贴出Socket聊天程序的服务端大体设计图,如下图: ...

  2. 写出易调试的SQL(修订版)

    h4 { background: #698B22 !important; color: #FFFFFF; font-family: "微软雅黑", "宋体", ...

  3. 【原创】免费申请SSL证书【用于HTTPS,即是把网站从HTTP改为HTTPS,加密传输数据,保护敏感数据】

    今天公司有个网站需要改用https访问,所以就用到SSL证书.由于沃通(以前我是在这里申请的)暂停了免费的SSL证书之后,其网站推荐了新的一个网站来申请证书,所以,今天因为刚好又要申请一个证书,所以, ...

  4. 动手做第一个Chrome插件

    Chrome插件是令人惊讶的简单,一旦你弄懂它的工作和实现原理.它是由一部分HTML,一部分Js,然后混合了一个叫做manifest.json的Json文件组合而成的整体.这意味着你可以使用你最擅长的 ...

  5. VS项目中使用Nuget还原包后编译生产还一直报错?

    Nuget官网下载Nuget项目包的命令地址:https://www.nuget.org/packages 今天就遇到一个比较奇葩的问题,折腾了很久终于搞定了: 问题是这样的:我的解决方案原本是好好的 ...

  6. celery使用的一些小坑和技巧(非从无到有的过程)

    纯粹是记录一下自己在刚开始使用的时候遇到的一些坑,以及自己是怎样通过配合redis来解决问题的.文章分为三个部分,一是怎样跑起来,并且怎样监控相关的队列和任务:二是遇到的几个坑:三是给一些自己配合re ...

  7. 【微信小程序开发•系列文章六】生命周期和路由

    这篇文章理论的知识比较多一些,都是个人观点,描述有失妥当的地方希望读者指出. [微信小程序开发•系列文章一]入门 [微信小程序开发•系列文章二]视图层 [微信小程序开发•系列文章三]数据层 [微信小程 ...

  8. Android——eclipse下运行android项目报错 Conversion to Dalvik format failed with error 1解决

    在eclipse中导入android项目,项目正常没有任何错误,但是运行时候会报错,(clean什么的都没用了.....)如图: 百度大神大多说是jdk的问题,解决: 右键项目-Properties如 ...

  9. 如何区别数据库删除语句drop与delete与truncate?

    1.delete:删除数据表中的行(可以删除某一行,也可以在不删除数据表的情况下删除所有行) 删除某一行:delete from 数据表名称 where 列名称=值: 删除所有行:delete*fro ...

  10. Linux LVM逻辑卷配置过程详解

    许多Linux使用者安装操作系统时都会遇到这样的困境:如何精确评估和分配各个硬盘分区的容量,如果当初评估不准确,一旦系统分区不够用时可能不得不备份.删除相关数据,甚至被迫重新规划分区并重装操作系统,以 ...