最近在使用Redis的时候遇到了linux系统中的vm.overcommit_memory参数设置,对此不是很了解,于是研究了一下,有了本文。

=====================================

一个尝试,如何在内存中申请空间:

>>> 100000*400000*8/1024/1024/1024
298.0232238769531

实际代码:

import numpy as np

x=np.zeros((100000,400000))

运行情况:

运行上面的代码后执行top命令,发现该进程的内存空间并没有明显变大,可以说x变量申请的298G空间并没有被分配,那么如何使内存真正被分配呢,给出下面的代码:

import numpy as np

x=np.zeros((100000,400000))

x+=0.0001

运行情况:

该代码的执行可以通过top命令发现确实有298G的内存空间被分配。

从上面的这个操作可以知道,在linux系统中系统真正的分配内存并不是在你申请的时候,而是在你初始化的时候。比如你使用C语言中的malloc申请内存,但是此时你所获得的是操作系统分配给你的虚拟地址,而此时这部分内存并没有真正的分配给你,要理解这个操作就需要对操作系统的虚拟地址和真实地址有一定的了解。

关于overcommit_memory与linux内存分配参考:

https://blog.51cto.com/u_13875041/5877796

https://zhuanlan.zhihu.com/p/551677956

overcommit方式进行内存分配,就是允许内核分配的内存空间大于实际物理内存空间,如果使用overcommit方式分配内存后实际初始化后的内存空间大于物理内存那么就会进行(OOM = out-of-memory)报错,并对某个进程进行kill,以达到释放物理内存的目的。

个人认为overcommit方式的内存分配和航空公司的机票超售是相像的,航空公司对航班机票的销售往往都会超过实际机舱座位数的,其目的就是大概率会有一部分人买了机票后由于各种原因无法登记,因此可以利用该种情况来进行一票多售实现收益最大化,然而该种方式也有一定概率遇到问题,那就是售出的机票所有的顾客都全部到达机场候机,比如150个座位的航班,卖了160张票,结果真遇到了160人全部到达机场候机的情况,这时就需要按照某种方式将多余的10个人安排到其他航班上。

可以说overcommit方式进行内存分配是linux系统放弃掉一定的系统稳定性来实现性能最大化的一种方式;为防止完全不受限制的overcommit方式造成linux系统不稳定的问题,一般使用受限制的overcommit方式进行内存分配,也就是下文中所提到的vm.overcommit_memory=0的情况;但是对于一些科学计算问题,或者Redis服务器,这样使用场景比较单一,但是对内存需求比较大,同时往往很多时候虽然申请的内存空间较大但是实际初始化的内存只是其中一部分的情况,此时我们一般设置vm.overcommit_memory=1,也就是完全不受限制的overcommit内存分配方式。

linux中​ vm.overcommit_memory​ 参数的设置:

分别可以取值为: 0,1,2

取0时,使用Heuristic算法进行内存的overcommit分配;

取1时,对申请的内存进行不受限制的overcommit分配;

取2时,不允许overcommit。

举例:(这里不考虑使用linux系统中的swap,因此这里说的内存即为物理内存)

如果vm.overcommit_memory设置为2,那么物理内存为64G,所有进程申请的内存总和上限即为64G。

如果vm.overcommit_memory设置为1,那么物理内存为64G,所有进程申请的内存总和不受限制,比如所以进程申请的内存总额为128G,但是这里需要注意的是内存初始化后的总和不能超过物理内存的64G;也就是说,这种设置下只要最终的进程申请的内存初始化不超过物理总内存,那么是可以随意申请任何大小的内存空间的;

(还是上面最早提到的知识点,linux系统中内存申请和内存实际分配是两件事,如果进程申请内存后并没有进行初始化,那么这块内存空间并没有从实际的物理内存中分配出去)

在实际的linux系统运行中,vm.overcommit_memory参数一般默认为0,也就是使用heuristic算法对内存进行申请分配。

------------------------------------------------------------------

https://zhuanlan.zhihu.com/p/551677956中给出了heuristic算法的描述:

Heuristic overcommit算法在以下函数中实现,基本上可以这么理解:
单次申请的内存大小不能超过 【free memory + free swap + pagecache的大小 + SLAB中可回收的部分】,否则本次申请就会失败。

------------------------------------------------------------------

 
 
也就是说,heuristic算法虽然允许使用overcommit,但是是一种受限制的overcommit,该种方式主要限制单次申请的overcommit内存不要过大。heuristic方式在分配内存时,虽然允许overcommit,但是在分配内存时要考虑整体的可用内存空间+可调配页的内存空间+可回收的内存空间的大小,这样的话虽然内存分配时存在overcommit,但是如果在初始化时内存空间不够也可以通过内存的调配及回收来进行一定程度上的缓解,因此在实际的linux服务器运行过程中,我们一般设置 vm.overcommit_memory=1 。

-----------------------------------------------------------------------

查询linux系统的overcommit设置:

cat /proc/sys/vm/overcommit_memory

===============================================

参考:

https://blog.csdn.net/weixin_42073629/article/details/117170686

使用Redis时的vm.overcommit_memory内存分配控制的更多相关文章

  1. 运行时数据区即内存分配管理——JVM之六

    内存分配结构,请参考: http://iamzhongyong.iteye.com/blog/1333100

  2. JVM学习笔记三:垃圾收集器与内存分配策略

    内存回收与分配重点关注的是堆内存和方法区内存(程序计数器占用小,虚拟机栈和本地方法栈随线程有相同的生命周期). 一.判断对象是否存活? 1. 引用计数算法 优势:实现简单,效率高. 致命缺陷:无法解决 ...

  3. jvm-垃圾收集器与内存分配策略

    垃圾收集器与内存分配策略 参考: https://my.oschina.net/hosee/blog/644085 http://www.cnblogs.com/zhguang/p/Java-JVM- ...

  4. C++动态内存分配

    C++动态内存分配1.堆内存分配 :C/C++定义了4个内存区间:代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念:通常定 ...

  5. spark内存分配

    问题描述 在测试spark on yarn时,发现一些内存分配上的问题,具体如下. 在$SPARK_HOME/conf/spark-env.sh中配置如下参数: SPARK_EXECUTOR_INST ...

  6. JAVA 垃圾收集算法,垃圾收集器与内存分配策略(内容全面,解析简单易懂)

    垃圾收集器需要解决的三个问题: 1)哪些内存需要回收 2)什么时候回收 3)如何回收 背景:程序计数器,虚拟机栈,本地方法栈3个区域随线程而生,随线程而灭,在这几个区域内不需要过多的考虑回收的问题,因 ...

  7. C++ 动态内存分配(6种情况,好几个例子)

    1.堆内存分配 : C/C++定义了4个内存区间: 代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念: 通常定义变量(或对 ...

  8. [UE4]C++ 动态内存分配(6种情况,好几个例子)

    1.堆内存分配 : C/C++定义了4个内存区间: 代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念: 通常定义变量(或对 ...

  9. redis源码解析之内存管理

    zmalloc.h的内容如下: void *zmalloc(size_t size); void *zcalloc(size_t size); void *zrealloc(void *ptr, si ...

  10. 【面试必备】小伙伴栽在了JVM的内存分配策略。。。

    周末有小伙伴留言说上周面试时被问到内存分配策略的问题,但回答的不够理想,小伙伴说之前公号里看过这一块的文章的,当时看时很清楚,也知道各个策略是干嘛的,但面试时脑子里清楚,心里很明白,但嘴里就是说不清楚 ...

随机推荐

  1. C#.NET HTTP Request 跳过自签名证书校验。

    public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain ...

  2. 图片jpg,png转为BASE64编码

    -- using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; namespace aliy ...

  3. excel计算日期天数和表格冻结首行

    excel计算日期天数和表格冻结首行 1.在单元格E35中输入公式DATEDIF(A35.B35."MD")MD表起始日期.结束日期天数差."Y" 时间段中的整 ...

  4. MySQL Docker搭建挂载并启用远程连接

    1.拉取镜像 后面可以指定版本号,这里使用8.0 docker pull docker.io/mysql:8.0 2.查看mysql镜像 docker images 3.启动docker并挂载 doc ...

  5. Vue聊天框自动滚动底部

    原理:通过监听数据更新,将滚动的最大高度赋值给滚动条的最大高度,并等待页面更新完成后再将页面滚动到底部. 容器代码 watch监听 scrollTop: 距离最顶部高度 scrollHeight:滚动 ...

  6. 链表中,LNode和* LinkList的理解

    typedef struct LNode { int data; struct LNode* next; }LNode, * LinkList; 这是标准链表创建法. 简单的说,其中LNode和 * ...

  7. vue项目中一些常用的插件

    @riophae/vue-treeselect:带选择的树组件 https://vue-treeselect.js.org/ ele-calendar:日历组件 https://www.npmjs.c ...

  8. 大数据面试吹牛草稿V2.0

    面试吹牛之前先打个草稿! 各位面试官好! 我叫 xxx,毕业于 xxx,之前在 xxx 公司待了 1 年多,期间⼀直从事的是 IT 行业,刚开始的时候做的是 Java 开发后来转岗到大数据方向做大数据 ...

  9. 一次STM32进入HardFault_Handler 的解决情况

    STM32进入HardFault_Handler调试 --- title: STM32进入HardFault_Handler调试 date: 2020-06-18 10:26:48 categorie ...

  10. 题解:洛谷 P1165 日志分析

    标签:栈,模拟 题意 对于一个栈,给定三种操作: 0 x,将 \(x\) 入栈: 1,出栈,栈空时忽略: 2,查询当前栈内最大值. 思路 前两个都是栈的基本操作,关键在于查最大值. 每次询问暴力找肯定 ...