生产问题复盘!Swap对GC的影响

Swap

1. 什么是Swap

swap 是把一块磁盘空间或者一个本地文件当做内存来使用。可用内存无法满足内存分配请求的时候,把不常用的内存数据存储到磁盘,并在内存中释放这部分内存。当进程再次访问这部分内存的时候,再读取到内存中来。

2. 为什么要有swap

os面对物理内存申请不足的时候,一种方法是oom,另一种方法是回收内存。

内存回收也分成2种,一种就是直接回收,另一种是定期回收,swap就是定期回收的一种

所以,swap的出现主要是解决内存不足

3. 对于gc有没有影响

如果java进程用到了swap内存,那么在gc的时候是会有影响的,毕竟涉及到磁盘写入和读取,且这个是由os控制。换入到磁盘的是冷数据,那应该也就影响Full GC,由于内存不足导致的频繁清理也会影响Minor GC(猜的)。

出现这种问题最大的问题还是物理内存不足以满足进程所需内存。所以应该把着重点放在进程所需内存调整和物理内存扩容这两点上。

4. swap大致运行逻辑

前面提到os在回收内存有两种方式,一种就是直接回收,另一种是定期回收。定期回收由专门的内核线程来进行回收。

当 pages_min<剩余内存<pages_low,线程就会执行内存回收。

可以通过cat /proc/zoneinfo查看。

回收模式可以通过cat /proc/sys/vm/zone_reclaim_mode查看。

  • 0 意味着关闭zone_reclaim模式,可以从其他zone回收内存
  • 1 表示打开zone_reclaim模式,这样内存回收只会发生在本地节点内
  • 2 在本地回收内存时,可以将cache中的脏数据写回硬盘,以回收内存。
  • 4 可以用swap方式回收内存。

简单实验

环境准备

  1. 开启Swap
shell 复制代码
# 创建Swap文件
$ fallocate -l 8G /mnt/swapfile
# 修改权限只有根用户可以访问
$ chmod 600 /mnt/swapfile
# 配置Swap文件
$ mkswap /mnt/swapfile
# 开启Swap
$ swapon /mnt/swapfile
# 关闭Swap
$ swapoff -a
  1. java文件准备
java 复制代码
import java.lang.ref.SoftReference;

class FullGCTest {
  public static void main(String[] args) {
      SoftReference<byte[]>[] list=new SoftReference[1000];
      for (int i = 0; i < 1000; i++) {
          try {
              Thread.sleep(1000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }

          list[i]= new SoftReference<>(new byte[1024 * 1024 * 10]);
      }
      System.out.println("程序执行完毕");
  }
}
  1. 启动命令
ruby 复制代码
# Xms Xmx我这选择用的就是free的值
java -XX:+PrintGCDetails -Xms1398m -Xmx1398m -XX:SurvivorRatio=8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC FullGCTest
  1. gc情况查看(看日志也行) 具体参数和其他命令可以参考:JVM命令行调优工具备忘录

    jstat -gc 15198 100

  2. 清空缓存

bash 复制代码
sudo echo 3 > /proc/sys/vm/drop_caches

Swap未开启

当内存快满的时候,并未有明显的时间家具

Swap开启

加大堆内存

java -XX:+PrintGCDetails -Xms4096m -Xmx4096m -XX:SurvivorRatio=8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC FullGCTest

不太精确的总结

  • 前面2个对照组,当没有使用到swap空间的时候,gc时间差不多,当swap空间使用的时候,会有一个明显的增加
  • 最后一个是模拟大量使用swap的场景,gc时间都有一个明显的增加
    • 当然也可能和我阿里云服务器1核2G有关,又分配了4G的堆内存。
  • gc属于java进程管理,swap属于os管理。影响应该是有的,但是两者都不可控,不应该纠结于swap,而是研究物理内存是否充足,java进程分配是否合理

以上来自一次真实的生产事故排查

相关推荐
hqxstudying23 分钟前
java依赖注入方法
java·spring·log4j·ioc·依赖
·云扬·32 分钟前
【Java源码阅读系列37】深度解读Java BufferedReader 源码
java·开发语言
martinzh1 小时前
Spring AI 项目介绍
后端
Bug退退退1232 小时前
RabbitMQ 高级特性之重试机制
java·分布式·spring·rabbitmq
小皮侠2 小时前
nginx的使用
java·运维·服务器·前端·git·nginx·github
前端付豪2 小时前
20、用 Python + API 打造终端天气预报工具(支持城市查询、天气图标、美化输出🧊
后端·python
爱学习的小学渣2 小时前
关系型数据库
后端
武子康2 小时前
大数据-33 HBase 整体架构 HMaster HRegion
大数据·后端·hbase
前端付豪2 小时前
19、用 Python + OpenAI 构建一个命令行 AI 问答助手
后端·python
凌览2 小时前
斩获 27k Star,一款开源的网站统计工具
前端·javascript·后端