首页 > 系统相关 >善待内存

善待内存

时间:2023-06-15 14:07:48浏览次数:59  
标签:善待 Cache 8G 内存 1G 缺页 分配


背景介绍

现在有35块内存,每块200M,均采用malloc分配。

在使用中,他们都被填入了10M~100M不等的数据,余下部分空闲。

然后我们将这35块内存中的有数据部分复制到一块1G的大内存中(已知有效数据总和不超过1G)。

 

伪代码如下

 

#define MAX_PER_BLOCK_MEM_SIZE      (1024*1024*200)
#define MAX_TOTAL_BLOCK_MEM_SIZE    (1024*1024*1024) 
for ( i = 0; i < 35; i++)
        mem[i] = malloc(MAX_PER_BLOCK_MEM_SIZE);
 
big_block = malloc(MAX_TOTAL_BLOCK_MEM_SIZE);
 
for ( i = 0; i < 35; i++)
        put some data to mem[i];
        len[i] = len(somedata);
 
for ( i = 0; i < 35; i++)
        copyto(big_block, mem[i], len[i]);

 

 

这个段程序的执行结果是怎样的呢?由于总数据不足1G,按照一般机器的内存拷贝速度,预计总时间不超过1秒钟。但实际执行结果却让我费解,着1G不到的内存复制居然消耗了30秒!一般有两种情况会影响速度:

1、 Cache Miss

2、 Page Swap

鉴于速度下降如此厉害,Cache Miss的可能性不大。即使从Cache理论上分析,复制数据的过程与Cache命中率基本上无关---Cahce Read 的 Miss Rate必然接近100% ;对于Cache Write, Write-Back Cache可以一定程度上加速写内存的过程,但数据量一旦大大超过Cache Capacity,也会挂掉。 Write Through的Cache就不说了。所以应该是Page Swap造成的。

 

free查看空闲内存,约8G。 再算我申请的内存:35*0.2G + 1G = 8G 。居然是刚刚好……肯定是发生Page Swap了~!

 

系统空闲内存:

善待内存_磁盘

 

 

解决方法

将每块内存改小:

#define MAX_PER_BLOCK_MEM_SIZE      (1024*1024*120)

 

重测,biu~~~秒杀。果然是发生换页了!

 

 

根据对操作系统内存分配机制的知识,这背后的机制却让我有些费解。

 

假设如下场景: malloc函数一次性分配了8G虚拟内存,而只实际只使用了其中的8G中的前面500M。

操作系统背后会做些什么呢?首先,为该进程分配映射8G空间所需要的页表,约占2M空间(按照PAGE_SIZE = 4KB算)。页表中填入什么呢?有两种选择:

立即分配(immediate allocation)方式: 只要有空闲物理内存页,就立即将这些空闲页分配给进程,页地址填入到页表中。

懒惰分配(lazy allocation)方式: 不管系统中有不有空闲物理页,页表中先什么都不填,仅仅标志NOT_PRESENT。当用户用虚拟地址访问到该页面时,将发生缺页中断。操作系统此时根据系统维护的状态可以知道该次访问是对页面的第一次访问,需要为其分配物理页面。now,操作系统向物理页面管理器发起物理页面申请,并将申请到的页地址填入到页表中,用户就可以继续对页面的访问了。

 

两种方式各自有何利弊呢?立即分配的方式的弊端由我上面的程序就已经可以看出来了。当用户喜欢预先申请大量内存,却不及时释放的时候,系统性能将受到严重影响。比如,A进程一次申请了8G内存,B进程如果想申请2G内存,则没有可用物理页了。只好将页表标记为NOT_PRESENT。一旦B进程访问这2G内存,将发生缺页中断。由于系统中没有可用物理内存了(A进程在占着茅坑不拉屎@@),操作系统换页机制将启动,当前某些物理页将被换入到磁盘中。这个过程相当耗时!

对于懒惰分配方式,上面的情况将不会出现,因为A进程分配的8G内存并没有实际分配,系统内还是有8G的空闲物理页。懒惰方式的缺点在于,缺页中断将会频繁发生!陷入内核的开销也是不容小觑的。举个例子:某个进程A,分配了1G内存,由于采用了懒惰分配方式,顺序访问这1G内存将会导致1G/4K=256K次缺页中断。假设每次中断处理时间需要1us,那么缺页造成的损失为1us * 256K = 256ms = 0.2s,在性能很重要的计算环境下,这个开销已经很大了。

 

解决方案

系统进行内存分配的时候,区别对待大内存分配和小内存分配。对于大内存分配采用懒惰分配方式,对于小内存,则一次性满足。在采用懒惰分配方式的时候,每次发生了缺页,可以一次分配几十到几百个页面给进程,这样可以有效避免懒惰分配方式中存在的缺页开销大的问题。

 

结论

莫非linux犯傻了?回头看看源码去~

 

Note:

这里“缺页中断”有两种语义,请注意区别:

1、传统意义的缺页中断。内核需要到磁盘上去读回所缺页。

2、物理页层次的缺页中断。此时实际上有足够的物理页面,只不过这些物理页面没有分配给进程而已。只有当发生物理层次的缺页中断时这些物理页才分配给进程。

标签:善待,Cache,8G,内存,1G,缺页,分配
From: https://blog.51cto.com/u_16162111/6486707

相关文章

  • JavaScript内存限制
    JavaScriptmemorylimitJavaScript应用程序可以存储的最大数据量是多少?我猜这是由浏览器处理的,每个浏览器都有其局限性吗?如果没有限制,将创建页面文件吗?如果是这样,那不安全吗? 相关讨论  有一些限制,尽管这些取决于浏览器。例如,Firefox对堆栈空间以及过多的CPU消......
  • Kubernetes 中的 Pod 内存请求(request)和限制(limit)设置多大合适
    Kubernetes中的Pod内存请求(request)和限制(limit)是为容器编排和资源管理提供支持的重要概念。一般来说,合适的内存request和limit需要基于应用程序的内存需求大小、应用程序的容器镜像大小以及在Kubernetes集群中Pod的数量等因素进行考虑。以下是一些关于如何设置Pod的......
  • jvm垃圾回收及内存模型
    1、了解垃圾回收之前,必须先了解内存模型 2、垃圾回收区域  a、首先要标记垃圾,找出垃圾   b、Java垃圾回收(一)_java垃圾回收_头发慢点掉的小马的博客-CSDN博客 垃圾回收器   方法区不需要连续的内存,可以选择固定大小或者可扩展。并且还可以选择不实现......
  • 配置云主机swap虚拟内存
    配置云主机虚拟内存:ddif=/dev/zeroof=/mnt/swapbs=block_sizecount=number_of_blockddif=/dev/zeroof=/mnt/swapbs=1Mcount=8192mkswap/mnt/swapswapon/mnt/swapvi/etc/fstab/mnt/swapswapswapdefaults00vi/etc/sysctl.confvm.swappiness=60sysctl-p swa......
  • java开发系统内核:应用程序与系统内核的内存隔离
    当前,我们可以开发运行在系统上的应用程序了,接下来的问题是如何保护系统内核免受恶意应用程序的危害。恶意程序要想侵犯系统,主要路径有两条,一是让内核执行它的代码,而是修改内核数据,通过修改数据改变内核的行为。我们看看,如何预防恶意程序侵入到系统内核的数据区域中。无论是内核还是......
  • 动态内存分配
    栈区:局部变量 函数的形式参数堆区:动态内存分配 malloc,free,calloc,realloc静态区:全局变量,静态变量,statint#include<stdlib.h>   malloc,free的头文件返回类型void*向内存申请空间malloc开辟空间 malloc(空间大小值 * sizeof())当动态申请的空间不再使用的时候 ......
  • C语言编程—内存管理
    C语言中的动态内存管理。C语言为内存的分配和管理提供了几个函数。这些函数可以在<stdlib.h>头文件中找到。在C语言中,内存是通过指针变量来管理的。指针是一个变量,它存储了一个内存地址,这个内存地址可以指向任何数据类型的变量,包括整数、浮点数、字符和数组等。C语言提供了一些函......
  • 浅聊一下 C#程序的 内存映射文件 玩法
    一:背景1.讲故事前段时间训练营里有朋友问内存映射文件是怎么玩的?说实话这东西理论我相信很多朋友都知道,就是将文件映射到进程的虚拟地址,说起来很容易,那如何让大家眼见为实呢?可能会难倒很多人,所以这篇我以自己的认知尝试让大家眼见为实。二:如何眼见为实1.我想象的文件映射......
  • ionic3打包内存溢出解决方法
    ionic3打包遇到报错aheadoutofmemorylimits,就是常见的node内存溢出问题,原因是由于node引擎在64位操作系统下内存限制(大小为1.4G)如果超出就会报内存泄漏错误。解决方法:1.全局安装increase-memory-limit插件项目目录控制台中输入:sudonpminstall-gincrease-memory-limit......
  • Javascript中的内存(垃圾)回收机制
    JavaScript具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行常见的垃圾回收方式:标记清除、引用计数方式。一、标记清除方法1、工作原理:【标记“离开环境”的就回收内存】当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“......