生产问题复盘!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进程分配是否合理

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

相关推荐
草履虫·6 分钟前
【Java集合】LinkedList
java
AngeliaXue8 分钟前
Java集合(List篇)
java·开发语言·list·集合
世俗ˊ9 分钟前
Java中ArrayList和LinkedList的比较
java·开发语言
zhouyiddd14 分钟前
Maven Helper 插件
java·maven·intellij idea
攸攸太上22 分钟前
Docker学习
java·网络·学习·docker·容器
Milo_K30 分钟前
项目文件配置
java·开发语言
程序员大金34 分钟前
基于SpringBoot+Vue+MySQL的养老院管理系统
java·vue.js·spring boot·vscode·后端·mysql·vim
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS网上购物商城(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
nsa652231 小时前
Knife4j 一款基于Swagger的开源文档管理工具
java
Ylucius1 小时前
JavaScript 与 Java 的继承有何区别?-----原型继承,单继承有何联系?
java·开发语言·前端·javascript·后端·学习