最近在使用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. Scrapy框架(二)--持久化存储

    持久化存储 scrapy的高性能持久化存储操作,有两种方式:基于终端指令的持久化存储 和 基于管道的持久化存储操作. 基于终端指令的持久化存储 保证爬虫文件的parse方法中有可迭代类型对象(通常为列 ...

  2. work03

    第一题: 1.定义一个包含十个元素的数组.数组元素自己给出 2.遍历打印出数组元素 3.求出数组当中的最小值打印出来 4.求出数组当中的最大值打印出来 5,求数组当中 第二大 值 第二题: 1.定义一 ...

  3. 燕千云ITAM:解锁数字化时代下企业竞争新优势

    数字化时代下,企业的IT资产管理(ITAM)尤为关键.企业通过在成长的每个阶段实施有效的IT资产管理策略,以确保资源的最优化利用和风险的有效控制,并在竞争激烈的市场环境中保持优势.然而实际实践中,企业 ...

  4. window10 java环境变量配置

    window10 此电脑 右击属性 相关设置 高级系统配置 点击右下的 环境变量 在系统变量中新增JAVA_HOME=D:\Program Files\Java\jdk1.8.0_25 在系统变量中修 ...

  5. 引入feign注入报错 org.springframework.beans.factory.NoSuchBeanDefinitionException解决

    引入feign注入报错 org.springframework.beans.factory.NoSuchBeanDefinitionException解决 [172.16.22.215] out: C ...

  6. mysql 联合表查询从表即使有索引依然ALL的一个原因-索引ALL解决,字符编码方式不一致导致全表搜索

    mysql 联合表查询从表即使有索引依然ALL的一个原因-索引ALL解决,字符编码方式不一致导致全表搜索那就是主表和从表的关联字段的编码方式不一样!!! 产生的现象: 解决之后,正确的使用了t2.or ...

  7. 何时/如何使用 std::enable_shared_from_this<T>?

    要点回顾 继承自 std::enable_shared_from_this<T> 的类能够在其自身实例中通过 std::shared_from_this 方法创建一个指向自己的 std:: ...

  8. 从0到1:CTFer成长之路网上平台的使用以及docker环境配置

    1.首先安装docker(这里在kali里演示) sudo su #以root身份运行 apt install docker.io #安装docker systemctl start docker # ...

  9. 2020-2021 ICPC, NERC, Northern Eurasia Onsite BEIJ 题解

    B. Button lock 题意:有 \(d\) 个 01 按键以及一个 reset 按键,你需要把所有题目给定的 \(n\) 个密码全部表示一遍.只有按下 reset 按键后才能使所有 01 按键 ...

  10. Android JACK 编译错误SSL error when connecting to the Jack server

    背景 之前编译好好,今天居然遇到了这样子的问题.还以为是和之前一样,Android7.0 配置JACK支持多用户同时编译. 结果不是: /bin/bash -c "(prebuilts/sd ...