内存抖动

内存抖动(memory thrashing)

现代操作系统都有一个叫虚拟内存的概念。操作系统如果只使用物理内存作为可用内存的话,会很受限制。于是就提出一种以廉价硬盘代替昂贵内存的方法,“扩充”可用内存。

   于是,就在硬盘上划出一部分硬盘空间用来暂时存放内存数据。当系统进程发现物理内存不够了,就在内存空间上找一些不活跃的进程,把它占用的内存复制到硬 盘上,空出来的内存就可以重新使用了。而这时内存被空出来的进程并不知道其实他们其实已经被停下来了。当这些被停下来的进程重新激活,就需要再找一块不那 么活跃的进程占用的内存空间,把它们的内存拷出来,把原来硬盘上的数据再拷回去。

  假如内存相对应用程序要求严重不足,就会导致这种数据的内存/硬盘频繁切换,反而占用了大量CPU时间,而其实这些CPU时间应该是用来运行程序的。按我的理解,这应该就是抖动了吧。

 

页面的频繁更换,导致整个系统效率急剧下降,这个现象称为内存抖动。

 

 

抖动一般是内存分配算法不好,内存太小引或者程序的算法不佳引起的页面频繁从内存调入调。
比如:
在用页式管理的操作系统中,可供程序用的内存大小为3页,采用最近最久未使用的算法或者先进先出的算法分配内存,请求调用页面的顺序为:1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4.。。。。。。。。。。。
这样的话,每一次cpu要调用数据或者程序时数据或程序所在的页都不知内存中,都要和外存对换页。这就是抖动!


转链接:http://qing.blog.sina.com.cn/2161971512/80dd113833002j7a.html

链表操作过程中出现的内存抖动问题通常源于频繁的内存分配与释放。在链表中,尤其是动态链表,节点的插入、删除操作会不断触发 `malloc` 和 `free` 等内存管理函数,导致内存分配器频繁进行内存块的分割、合并与回收。这种行为不仅会引发内存碎片问题,还可能造成内存抖动Memory Thrashing),即系统在短时间内频繁进行内存回收和分配,从而显著影响程序性能 [^3]。 ### 链表操作中的内存抖动表现 - **频繁的内存分配与释放**:链表节点的动态创建与销毁会频繁调用内存分配函数,尤其在高并发或高频操作场景下,这种行为会加剧内存抖动 [^3]。 - **内存碎片化**:由于链表节点大小不一,频繁的 `malloc` 与 `free` 会加剧外部碎片问题,导致内存利用率下降,甚至出现“有足够内存但无法分配连续空间”的问题 [^3]。 - **性能下降**:内存抖动会导致内存分配器效率下降,甚至引发系统级的内存回收行为,影响整体程序响应时间 [^1]。 ### 内存抖动的优化方法 #### 1. **使用内存池** 通过预分配固定大小的内存池来管理链表节点,避免频繁调用 `malloc` 和 `free`。内存池可以复用已释放的节点,显著减少内存分配的开销。 ```c typedef struct Node { int data; struct Node *next; } ListNode; typedef struct { ListNode *pool; // 内存池起始地址 int capacity; // 池容量 int used; // 已使用数量 } MemPool; ListNode* mem_pool_alloc(MemPool *mp) { if (mp->used >= mp->capacity) return NULL; return &mp->pool[mp->used++]; } void mem_pool_reset(MemPool *mp) { mp->used = 0; } ``` #### 2. **Slab 分配器** Slab 分配器是一种高效的内存管理机制,特别适用于固定大小对象的分配。通过将链表节点按照固定大小组织为 slab,可以减少内存碎片并提升分配效率 [^3]。 #### 3. **对象复用机制** 在链表删除操作中,不立即释放节点内存,而是将其缓存到一个“空闲链表”中。下次插入新节点时,优先从空闲链表中获取节点,减少内存分配次数。 ```c ListNode *free_list = NULL; ListNode* get_node() { if (free_list != NULL) { ListNode *node = free_list; free_list = free_list->next; return node; } return (ListNode*)malloc(sizeof(ListNode)); } void release_node(ListNode *node) { node->next = free_list; free_list = node; } ``` #### 4. **批量分配与释放** 在链表初始化或大规模插入操作前,预先分配一批节点内存,避免单次操作频繁调用分配函数。同样,在批量删除时,可将节点统一归还到内存池或 slab 中,减少碎片化风险。 #### 5. **减少链表节点大小差异** 若链表节点大小差异较大,建议采用内存池或 slab 分配器进行分类管理,避免因大小不均导致内存碎片和抖动 [^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值