大内高手—内存管理器

17、深入理解FastMM4内存管理器:原理、优化与实践 本文深入解析了FastMM4内存管理器的原理与实现,涵盖其小、中、大内存块分配器的工作机制,并探讨了内存重分配优化、并行环境下的内存分配策略及日志记录内存管理器的实现与局限性。通过具体示例分析了在并行程序中FastMM4的性能瓶颈及优化方向,为开发者提供了在不同场景下高效使用FastMM4的建议。 阅读详情
 

大内高手—内存管理器

 

转载时请注明出处和作者联系方式:http://blog.youkuaiyun.com/absurd

作者联系方式:李先静 <xianjimli at hotmail dot com>

更新时间:2007-7-9

作为一个C程序员,每天都在和malloc/free/calloc/realloc系列函数打交道。也许和它们混得太熟了,反而忽略了它们的存在,甚至有了三五年的交情,仍然对它们的实现一无所知。相反,一些好奇心未泯的新手,对它们的实现有着浓厚的兴趣。当初正是一个新同事的问题,促使我去研究内存管理算法的实现。

 

内存管理算法多少有些神秘,我们很少想着去实现自己的内存管理算法,这也难怪:有这样需求的情况并不多。其实,至于内存分配算法的实现,说简单也简单,说复杂也复杂。要写一个简单的,或许半天时间就可以搞掂,而要写一个真正实用的,可能要花上你几周甚至几个月的时间。

 

malloc和free是两个核心函数,而calloc和realloc之所以存在,完全是为了提高效率的缘故。否则完全可以用malloc和free的组合来模拟它们。

 

拿calloc函数的实现来说,在32位机上,内存管理器保证内存至少是4字节对齐的,其长度也会扩展到能被4字节整除,那么其清零算法就可以优化。可以一次清零4个字节,这大大提高清零速度。

 

拿realloc函数的实现来说,如果realloc的指针后面有足够的空间,内存管理器可以直接扩展其大小,而无须拷贝原有内容。当然,新大小比原来还小时,更不拷贝了。相反,通过malloc和free来实现realloc时,两种情况下都要拷贝,效率自然会低不少。

 

另外还有两个非机标准的,但很常用的函数,也涉及到内存分配:strdup和strndup。这两个函数在linux和win32下都支持,非常方便。这完全可以用malloc来模拟,而且没有性能上的损失。

 

这里我们主要关注malloc和free两个函数的实现,并以glibc 2.3.5(32位linux) 为例分析。

 

内存管理器的目标

内存管理器为什么难写?在设计内存管理算法时,要考虑什么因素?管理内存这是内存管理器的功能需求。正如设计其它软件一样,质量需求一样占有重要的地位。分析内存管理算法之前,我们先看看对内存管理算法的质量需求有哪些:

 

l         最大化兼容性

要实现内存管理器时,先要定义出分配器的接口函数。接口函数没有必要标新立异,而是要遵循现有标准(如POSIX或者Win32),让使用者可以平滑的过度到新的内存管理器上。

 

l         最大化可移植性

通常情况下,内存管理器要向OS申请内存,然后进行二次分配。所以,在适当的时候要扩展内存或释放多余的内存,这要调用OS提供的函数才行。OS提供的函数则是因平台而异,尽量抽象出平台相关的代码,保证内存管理器的可移植性。

 

l         浪费最小的空间

内存管理器要管理内存,必然要使用自己一些数据结构,这些数据结构本身也要占内存空间。在用户眼中,这些内存空间毫无疑问是浪费掉了,如果浪费在内存管理器身的内存太多,显然是不可以接受的。

 

内存碎片也是浪费空间的罪魁祸首,若内存管理器中有大量的内存碎片,它们是一些不连续的小块内存,它们总量可能很大,但无法使用,这也是不可以接受的。

 

l         最快的速度

内存分配/释放是常用的操作。按着2/8原则,常用的操作就是性能热点,热点函数的性能对系统的整体性能尤为重要。

 

l         最大化可调性(以适应于不同的情况)

内存管理算法设计的难点就在于要适应用不同的情况。事实上,如果缺乏应用的上下文,是无法评估内存管理算法的好坏的。可以说在任何情况下,专用算法都比通用算法在时/空性能上的表现更优。

 

为每种情况都写一套内存管理算法,显然是不太合适的。我们不需要追求最优算法,那样代价太高,能达到次优就行了。设计一套通用内存管理算法,通过一些参数对它进行配置,可以让它在特定情况也有相当出色的表现,这就是可调性。

 

l         最大化局部性(Locality)

大家都知道,使用cache可以提高程度的速度,但很多人未必知道cache使程序速度提高的真正原因。拿CPU内部的cache和RAM的访问速度相比,速度可能相差一个数量级。两者的速度上的差异固然重要,但这并不是提高速度的充分条件,只是必要条件。

 

另外一个条件是程序访问内存的局部性(Locality)。大多数情况下,程序总访问一块内存附近的内存,把附近的内存先加入到cache中,下次访问cache中的数据,速度就会提高。否则,如果程序一会儿访问这里,一会儿访问另外一块相隔十万八千里的内存,这只会使数据在内存与cache之间来回搬运,不但于提高速度无益,反而会大大降低程序的速度。

 

因此,内存管理算法要考虑这一因素,减少cache miss和page fault。

 

l         最大化调试功能

作为一个C/C++程序员,内存错误可以说是我们的噩梦,上一次的内存错误一定还让你记忆犹新。内存管理器提供的调试功能,强大易用,特别对于嵌入式环境来说,内存错误检测工具缺乏,内存管理器提供的调试功能就更是不可或缺了。

 

l         最大化适应性

前面说了最大化可调性,以便让内存管理器适用于不同的情况。但是,对于不同情况都要去调设置,无疑太麻烦,是非用户友好的。要尽量让内存管理器适用于很广的情况,只有极少情况下才去调设置。

 

设计是一个多目标优化的过程,有些目标之间存在着竞争。如何平衡这些竞争力是设计的难点之一。在不同的情况下,这些目标的重要性又不一样,所以根本不存在一个最好的内存分配算法。

 

关于glibc的内存分配器,我们并打算做代码级分析,只谈谈几点有趣的东西:

1.         Glibc分配算法概述:

l         小于等于64字节:用pool算法分配。

l         64到512字节之间:在最佳凭配算法分配和pool算法分配中取一种合适的。

l         大于等于512字节:用最佳凭配算法分配。

l         大于等于128K:直接调用OS提供的函数(如mmap)分配。

 

2.         Glibc扩展内存的方式:

 

l         int brk(void *end_data_segment);

本函数用于扩展堆空间(堆空间的定义可参考内存模型一章),用end_data_segment指明堆的结束地址。

l         void *sbrk(ptrdiff_t increment);

本函数用于扩展堆空间(堆空间的定义可参考内存模型一章),用increment指定要增加的大小。

l         void*  mmap(void *start, size_t length, int prot , int flags, int fd, off_t offset);

本函数用于分配大块内存了,如前面所述大于128K的内存。

 

3.         空指针和零长度内存

l         free(NULL)会让程序crash吗?答案是不会,标准C要求free接受空指针,然后什么也不做。

l         malloc(0)会分配成功吗?答案是会的,它会返回一块最小内存给你。

 

4.         对齐与取整

l         内存管理器会保证分配出来的内存地址是对齐的,通常是4或8字节对齐。

l         内存管理器会对要求内存长度取整,让内存长度能被4或8的整除。

5.         已经分配内存的结构

allocate

如果前面有一块有效内存块的,则第一个size_t指明前一块内存的大小。

第二个size_t指明自己的大小,同时还指明:自己是不是用mmap分配的(M),前面是否有一个效内存块(P)。你可能觉得奇怪,在32位机上,sizeof(size_t)就是32位,怎么还能留下两个位来保存标志呢?前面我们说了,会对内存长度取整,保证最低2或3bits为0,即是空闲的。

 

6.         空闲内存的管理

free

由此可以看出,最小内存块的长度为16字节:

sizeof(size_t) +

sizeof(size_t) +

sizeof(void*) +

sizeof(void*) +

0

这一招非常管用,第一次看到时,感觉简直太巧妙了。这使得无需要额外的内存来管理空闲块,利用空闲块自己,把空闲块强制转换成一个双向链表就行了。

 

OpenCASCADE:Foundation Classes内存管理 OpenCASCADE:Foundation Classes内存管理内存管理器的使用如何配置内存管理器优化技术优点和缺点 在工作会话中,几何建模应用程序创建和删除分配在动态内存(堆)中的大量 C++ 对象。在这种情况下,用于分配和取消分配内存的标准函数的性能可能不够。为此,Open CASCADE 技术采用了在标准包中实现的专用内存管理器。 内存管理器基于以下原则: 小内存阵列被分组到集群中,然后回收(集群永远不会释放到系统中), 大数组是通过系统的标准函数分配和取消分配的(数组在不再使用时释放给系统)。 阅读详情

相关推荐

C语言实现内存管理

通过C语言,基本实现了内存管理过程中的创建、修改、删除等操作

YAMM - Systemverilog 内存管理器

缓冲区可以按照任何粒度或地址对齐的6种分配模式进行分配缓冲区可以由用户插入(非重叠)缓冲区可以通过地址或句柄来解除分配缓冲区可以通过地址或句柄在内存空间中搜索缓冲区支持有效载荷,可以由用户分配,随机生成,读取和比较。实现快速缓冲区搜索算法除了这些功能之外,YAMM还提供调试功能(例如,内存镜像存储,使用情况统计),并且很容易将其与现有验证环境集成。

分享记录一下工作中遇到的相关知识 952

避开这些坑!QMT多因子策略实盘中的5个常见错误及解决方案

本文深入剖析了在QMT平台上实施多因子策略时常见的5个错误,包括因子过拟合、数据延迟处理不当、因子失效、交易成本低估和风险控制缺失,并提供了实用的解决方案。通过优化因子筛选、数据对齐和动态管理,帮助量化交易者提升策略稳健性和实盘表现。

k5l6m的博客 238

C语言的内存管理

1、内存管理的概述 当程序被加载到内存的时候,它在内存中会大致被组织成三个部分:代码区,静态存储区和动态存储区。代码区存放的是将要执行的程序的机器语言表示,包括组成程序的各种用户自定义函数和系统调用函数。关于静态存储区和动态存储区:The word static refers to things that happen at compile time and link time when the

水逝流年 1892

论文理解【LLM-OR】——【OptMATH】A Scalable Bidirectional Data Synthesis Framework for Optimization Modeling

本文提出 LLM-OR 领域的双向数据合成框架 OptMATH,从已有 MF/PD 出发反向生成 NL,再使用 AutoFormulator 进行正向建模,通过最优值匹配 rejection sampling 确保语义一致性。实现了难度可控的语义一致数据合成

佚失的诗篇 497

burpsuite抓取ios数据包

1:首先在burpsuite中设置 添加proxy listeners 2:电脑开热点,手机连接,把代理设为电脑的ip和代理的端口 3:在Safari浏览器中打开网址http://burp下载证书 4:打开设置->通用->描述文件与设备管理 5:设置->通用->关于本机->证书信任设置 之后就可以正常抓包了 ...

weixin_45682070的博客 2065

实现简单的内存管理

1 源码: 源码已经提交github,内存管理github链接,欢迎一起讨论。 2 实现过程 该代码实现了在固定地址空间上进行内存的分配与释放。在操作系统启动时刻指定固定的地址作为mymlloc()操作的Heap空间,也可以直接定义数组。在嵌入式系统中,最好指定固定的地址,方便进行管理以及问题的排查。 2.1 内存控制块定义 struct free_block_t{ unsigned long size; unsigned char *start; unsigned char *en

qq_32938605的博客 855

ADXL355 STM32 HAL 库 SPI 驱动实战:从零构建高精度加速度数据采集系统

本文详细介绍了如何使用STM32 HAL库通过SPI接口驱动ADXL355高精度加速度计,构建稳定可靠的数据采集系统。从硬件连接到寄存器配置,再到数据采集与处理,提供了完整的实战代码和优化技巧,特别适合工业级振动监测等应用场景。

weixin_28738397的博客 324

用c++写个内存管理器

内存管理器是一种重要的系统组件,用于管理程序运行时使用的内存。下面是一个简单的 C 语言内存管理器的例子: #include <stdio.h> #include <stdlib.h> #define MEM_SIZE 100 char memory[MEM_SIZE]; int used_size = 0; void *my_malloc(int size) { ...

weixin_35754962的博客 249

ESP32S3接入讯飞在线语音识别教程及配套源代码

本文介绍了如何使用ESP32-S3开发板实现讯飞在线语音识别功能。首先,需要准备硬件设备,包括ESP32-S3开发板、麦克风模块、MicroSD卡模块和扬声器模块。接着,安装Arduino IDE并配置ESP32-S3开发环境,注册讯飞开放平台账号并获取API凭证。然后,通过I2S接口连接麦克风模块,并编写代码实现语音录制、Base64编码、API请求和识别结果处理。代码包括初始化WiFi、麦克风、系统时间,以及录制语音、发送请求、解析响应等功能。最后,通过按键触发录音,并将识别结果输出到串口。

2401_88800025的博客 746

ESP32设备驱动-TM1637-驱动4位7段数码管

TM1637是一款带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成了MCU数字接口、数据锁存、LED高压驱动、键盘扫描等功能。 TM1637使用DIP20/SOP20封装,主要适用于电磁炉、微波炉、小家电的显示驱动。

视觉与物联智能 2117

大内高手—内存管理器 (转)

大内高手—内存管理器 转载时请注明出处和作者联系方式:http://blog.youkuaiyun.com/absurd作者联系方式:李先静 更新时间:2007-7-9作为一个C程序员,每天都在和malloc/free/calloc/realloc系列函数打交道。也许和它们混得太熟了,反而忽略了它们的存在,甚至有了三五年的交情,仍然对它们的实现一无所知。相反,一些好奇心未泯的新手,对它

青青的专栏--C/C++ OOA/D Design Pattern 652

Python爬虫实战:模拟登录B站 – 处理Cookie和加密参数

由于B站在登录过程中采用了多种安全措施,包括加密的请求参数和cookie验证,模拟登录成为一项具有挑战性的任务。首先,我们需要获取B站的登录页面,并解析出其中的CSRF令牌和其他隐藏的字段。B站的登录接口通常会包含一些动态的加密参数,我们需要在登录前通过GET请求获取这些信息。本文详细介绍了如何使用Python模拟登录B站,解决加密参数的处理、图形验证码的识别以及登录后的数据抓取。库中的加密方法加密登录请求中的密码。一旦登录成功,我们可以通过维护会话状态,抓取登录后的数据,如个人主页、评论、观看记录等。

2201_76125261的博客 1309

大内高手 内存管理器

大内高手 内存管理器

jggyff的博客 199

cadence中利用sva进行FPV实战(可直接使用)

在cadence中使用fpv进行formal验证

youzjuer的博客 749

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【转】大内高手—内存管理器

转载时请注明出处和作者联系方式:http://blog.youkuaiyun.com/absurd 作者联系方式:李先静 <xianjimli at hotmail dot com> 更新时间:2007-7-9 作为一个C程序员,每天都在和malloc/free/calloc/realloc系列函数打交道。也许和它们混得太熟了,反而忽略了它们的存在,甚至有了三五年的交情,仍然对它们的实...

weixin_34062329的博客 96

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

转载--大内高手—内存管理器(一)

大内高手—内存管理器(一) 转载时请注明出处:http://blog.youkuaiyun.com/absurd作为一个C程序员,每天都在和malloc/free/calloc/realloc系列函数打交道。也许和它们混得太熟了,反而忽略了它们的存在,甚至有了三五年的交情,仍然对它们的实现一无所知。相反,一些好奇心未泯的新手,对它们的实现有着浓厚的兴趣。当初正是一个新同事的问题,促使我去研究内存管

技术资料库 1694

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java内存管理器

java内存管理器是基于EhCache封装 Java内存管理器主要特点: 内存管理器缓存在内存和磁盘存储可以伸缩到数G,Ehcache为大数据存储做过优化。 大内存的情况下,所有进程可以支持数百G的吞吐。 为高并发和大型多CPU服务器做优化。 ...

chuangjiji0839的博客 145
上一篇: 大内高手—共享内存与线程局部存储
下一篇: 大内高手—常见内存错误
trunk0813
博客等级 码龄18年 7粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值