内存碎片

虚拟内存管理

独自空忆成欢 提交于 2020-03-05 08:54:54
1、什么是虚拟内存 虚拟内存是计算机系统内存管理的一种技术。它使的应用程序认为他拥有连续的可用内存( 一个连续完整的地址空间 ),而实际上,他通常是被分割成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。 注意:虚拟内存不只是“用磁盘空间来扩展物理内存”的意思--这只是扩充内存级别以使其包含磁盘驱动器而已,把内存扩展到磁盘只是使用虚拟内存技术的一个结果,他的作用可以通过覆盖或者把处于不活动状态的程序以及他们的数据交换到磁盘上等方式实现。 2、为什么会有虚拟内存 许多年以前,当人们还在使用DOS或更古老的操作系统的时候,计算机内存还非常小,一般都是以K为单位进行计算的,相应的,当时的程序规模也不大,所以内存容量虽然小,但还是可以容纳当时的程序。但随着图像界面的想起还有用户需求的不断增大,应用程序的规模也随之膨胀起来。终于一个难题出现在程序员面前,那就是应用程序太大以至于内存容不下该程序,通常解决的办法是把程序分割成许多覆盖快的片段。覆盖块0首先运行,结束时他将调用另一个覆盖块。虽然覆盖块的交换是由os完成的,但是必须先有程序员吧程序先进行分割,这是一个费时费力的工作,而且相当枯燥。虚拟存储器就应运而生。 3、物理地址、虚拟地址、逻辑地址区别 32位系统的地址总线是32位的, 64位 CPU是指 CPU 内部的通用寄存器的宽度为 64 比特

深入理解java垃圾回收算法

吃可爱长大的小学妹 提交于 2020-03-03 23:35:25
Java 虚拟机 的内存区域中,程序计数器、虚拟机栈和本地方法栈三个区域是线程私有的,随线程生而生,随线程灭而灭;栈中的栈帧随着方法的进入和退出而进行入栈和出栈操作,每个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这三个区域的内存分配和回收都具有确定性。垃圾回收重点关注的是堆和方法区部分的内存。 常用的垃圾回收算法有: (1).引用计数算法: 给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值就减1;任何时刻计数器都为0的对象就是不再被使用的,垃圾收集器将回收该对象使用的内存。 引用计数算法实现简单,效率很高,微软的COM技术、ActionScript、Python等都使用了引用计数算法进行内存管理,但是引用计数算法对于对象之间相互循环引用问题难以解决,因此java并没有使用引用计数算法。 (2).根搜索算法: 通过一系列的名为“GC Root”的对象作为起点,从这些节点向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Root没有任何引用链相连时,则该对象不可达,该对象是不可使用的,垃圾收集器将回收其所占的内存。 主流的商用程序语言C#、java和Lisp都使用根搜素算法进行内存管理。 在java语言中,可作为GC Root的对象包括以下几种对象: a. java虚拟机栈

MMU内存管理单元

女生的网名这么多〃 提交于 2020-03-03 20:52:13
arm-linux学习-(MMU内存管理单元) 什么是MMU MMU(Memory Management Unit)主要用来管理虚拟存储器、物理存储器的控制线路,同时也负责 虚拟地址映射为物理地址 ,以及提供硬件机制的内存访问授权、多任务多进程操作系统。(来自百度百科, 对其几个点不熟悉,因此可以只考虑加粗部分 ) 发展历史 注意:学习一个知识点,很重要的一步是了解其 为什么而存在?它的存在是为了解决什么问题? 然后,在学习的过程中带着这些问题去理解、去思考。 在许多年以前,还是使用DOS或一些古老的操作系统时,内存很小,同时,应用程序也很小,将程序存储在内存中基本能够满足需要。随着科技的发展,图形界面及一些其他更复杂的应用出现,内存已经无法存储这些应用程序了,通常的解决办法是将程序分割成很多个 覆盖块 ,覆盖块0最先运行,运行结束之后,就调用另一个覆盖块,虽然这些操作由OS来完成,但是,需要程序员对程序进行分割,这非常不高效;因此,人们想出了一个 虚拟存储器(virtual memory) 的方法。虚拟存储器的基本思想是:程序、数据、堆栈的总大小可以超过内存空间的大小,操作系统将当前运行的部分保存在内存中,未使用的部分保存在磁盘中。比如一个16MB的程序和一个内存只有4MB的机器,操作系统通过选择可以决定哪部分4MB的程序内容保存在内存中,并在需要时,在内存与磁盘中交换程序代码

python面试1000题之7-8

你离开我真会死。 提交于 2020-03-02 18:52:15
7 Python是如何进行内存管理的? http://developer.51cto.com/art/201007/213585.htm Python引用了一个内存池(memory pool)机制,即Pymalloc机制(malloc:n.分配内存),用于管理对小块内存的申请和释放 内存池(memory pool)的概念: 当 创建大量消耗小内存的对象时,频繁调用new/malloc会导致大量的内存碎片,致使效率降低。内存池的概念就是预先在内存中申请一定数量的,大小相等 的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。 内存池的实现方式有很多,性能和适用范围也不一样。 python中的内存管理机制——Pymalloc: python中的内存管理机制都有两套实现,一套是针对小对象,就是大小小于256bits时,pymalloc会在内存池中申请内存空间;当大于256bits,则会直接执行new/malloc的行为来申请内存空间。 关于释放内存方面,当一个对象的引用计数变为0时,python就会调用它的析构函数。在析构时,也采用了内存池机制,从内存池来的内存会被归还到内存池中,以避免频繁地释放动作。 8 解释一下python的and-or语法 http://www.kuqin.com

slab内存管理分享

孤街浪徒 提交于 2020-03-02 16:45:35
1. 什么是 slab Slab 是中内存管理算法,最早是由 sun 的工程师提出,主要是基于一下因数考虑: 1 :内核函数经常倾向于反复请求相同的数据类型。比如:创建进程时,会请求一块内存来存放 mm 结构。 2 :不同的结构使用不同的分配方法可以提高效率。同样,如果进程在撤消的时候,内核不把 mm 结构释放掉,而是存放到一个缓冲区里,以后若有请求 mm 存储空间的行为就可以直接从缓冲区中取得,而不需重新分配内存 . 3: 前面我们曾分析过,如果伙伴系统频繁分配,释放内存会影响系统的效率,以此,可以把要释放到的内存放到缓冲区中,直至超过一个阀值才把它释放至伙伴系统,这样可以在一定程度上缓减减伙伴系统的压力 4: 为了缓减“内碎片”的产生,通常可以把小内存块按照 2 的倍数组织在一起,这一点和伙伴系统类似 2.slab 算法的具体思想 slab 的思想是将 内存分成大小不等的 slabs chunks (先分成大小相等的 slabs ,然后每个 slab 被分成大小相等 chunks ,不同 slab 的 chunk 大小是不相等的 )。 chunk 的大小依次从一个最小数开始,按某个因子增长,直到达到最大的可能值。 如果最小值为 400B ,最大值是 1MB ,因子是 1.20 ,各个 slab 的 chunk 的大小依次是: slab1 - 400B slab2 - 480B

索引调优 第三篇:索引统计

我是研究僧i 提交于 2020-03-02 07:56:20
数据库引擎是高度优化的闭环系统,基于执行计划的反馈,查询优化器在一定程度上自动优化现有的执行计划。查询优化的核心是索引优化,数据库引擎通过计数器统计关于索引操作的数据,统计的信息包括:使用次数、物理存储、底层操作的计数,以及缺失索引等,这些统计数据存储在内存中,是数据库引擎执行情况的真实反馈,高度概括了索引的执行情况,有意识地利用索引的统计信息,有针对性地优化现有的业务逻辑代码,调整查询的执行计划,能够提高数据库的查询性能。 一,统计索引的使用次数 在用户成功提交查询语句时,执行计划中每一个单独的索引操作(Seek,Scan,Lookup或Update)都会被统计到 sys.dm_db_index_usage_stats 中,例如, user_updates 计数器统计索引执行Insert,Update或Delete操作的次数,查找计数器( user_seeks, user_scans, user_lookups )统计在索引上执行的seek,scan和lookup操作的次数,如果查找计数器远远小于 user_updates 计数器,这说明基础表会执行大量的更新操作,维护索引更新的开销比较大,数据库引擎利用索引提升查询性能的空间有限。 在计数时,每一个单独的seek、scan、lookup或update操作都被计算为对该索引的一次使用,并使该视图中的相应计数器加1。 索引的Seek

Jvm 垃圾回收机制

僤鯓⒐⒋嵵緔 提交于 2020-03-01 22:47:09
判断一个对象是否可回收? 引用计数: 每当一个对象被引用时,其引用计数加一,当引用计数为0时GC回收内存将对象销毁。 缺点:无法回收互相引用的对象(互相调用其引用数永远不为0) 根可达算法 垃圾回收算法: 标记-整理算法: 适用于回收率低的区域 标记存活对象,将所有的存活对象压缩到内存的另一端。之后清理边界之外的所有空间。 复制算法:适用于回收率高的区域 将内存分为两半,每次只是用一半的内存,回收时将正在使用的内存中的存活的对象复制到另一半中,再清理内存。 在Hotsop虚拟机中的垃圾回收算法: 分代回收机制:将内存分为新生代和老年代,其中的新生代分为eden、幸存者区域(from和to),老年代(Old)。新生代:幸存者=8:1 在新生代中采用复制算法,每次只使用幸存者区域的一块,在回收时将eden和使用的一块幸存者区域存活的对象复制到另一块幸存者区域中,再清理,如果另一块幸存者区域放不下就进入老年代。 在老年代采用标记整理算法,将存活对象压缩内存的一边,清理另一边内存。 HotSpot启动回收时机: HotSpot采用根可达算法,在确定Root节点时需要停止所有线程的执行,在HotSpot中在解析代码时会将引用保存到一个OopMap数组中,以便虚拟机方便找到引用的区域。 在GC时不能有引用关系的变化,又不能频繁保存更新OopMap,HotSpot在代码中设置安全点

06.进程的虚拟内存管理.md

牧云@^-^@ 提交于 2020-03-01 22:15:45
正好遇到 华庭(庄命强)的glibc内存管理Ptmalloc2 源代码分析 一文,非常开心。真是大佬。我只是借着这篇文章稍微整理一下,为了以后自己回顾的时候能够更好的排查问题。 6.1 linux进程内存布局 x86 平台 Linux 进程内存布局   Linux 系统在装载 elf 格式的程序文件时,会调用 loader 把可执行文件中的各个段依次 载入到从某一地址开始的空间中(载入地址取决 link editor(ld)和机器地址位数,在 32 位机 器上是 0x8048000,即 128M 处)。如下图所示,以 32 位机器为例,首先被载入的是.text 段, 然后是.data 段,最后是.bss 段。这可以看作是程序的开始空间。程序所能访问的最后的地 址是 0xbfffffff,也就是到 3G 地址处,3G 以上的 1G 空间是内核使用的,应用程序不可以直 接访问。  &emsp应用程序的堆栈从最高地址处开始向下生长,.bss 段与堆栈之间的空间是空闲的, 空闲空间被分成两部分,一部分为 heap,一部分为 mmap 映射区域,mmap 映射区域一般 从 TASK_SIZE/3 的地方开始,但在不同的 Linux 内核和机器上,mmap 区域的开始位置一般是 不同的。Heap 和 mmap 区域都可以供用户自由使用,但是它在刚开始的时候并没有映射到 内存空间内,是不可访问的

PCIe调试心得_DMA part2

筅森魡賤 提交于 2020-03-01 22:15:20
作者: East FPGA那点事儿 上一章讲述了PCIe总线DMA的原理和XAPP1052存在的问题。 本章以服务器常用的4通道1000M以太网卡为例讲述如何提高DMA的效率。 1.内存重分配 Windows操作系统会划分一部分硬盘空间作为虚拟内存,将长时间不用得应用程序或内存交换到硬盘中,而释放出一部分内存空间供其他应用程序使用,提高计算机的性能。 或者操作系统会定进行内存碎片整理,将应用程序中零散的内存收集起来重新分配,减少内存碎片。 但是如果被交换或整理的是DMA使用的内存就麻烦了。操作系统已经为该内存重新分配了物理地址,而原内存分配给了其他应用程序,此时DMA再使用该内存,必然导致死机蓝屏现象。XAPP1052就没有很好的解决该问题,在程序中设置禁止将该内存交换到硬盘或整理。 2.内存大小 XAPP1052中申请到的物理连续内存大小为4KB。因为DDR内存内部是以块为单位,最小块为4KB,所以在操作系统中比较容易申请到4KB的物理连续内存。 4KB这个大小太小了。以太网数据小包为64B,大包为1512B,假如连续收到3个大包,那么应该怎样利用4KB的内存呢? 一种方式是一片4KB内存只存放2包数据,剩余内存浪费,第二片4KB内存存放第三包数据;另一种方式是将第三包数据拆分,前一半数据存放在第一片内存,后一半数据存放在第二片内存。 第一种方式将浪费976B,内存利用率非常低

ByteBuf和Channel和Pipeline

无人久伴 提交于 2020-03-01 22:13:02
BytetBuf ByteBuf就是JDK nio中Buffer的新轮子 buffer 的主要目的进行流量整形,把突发的大数量较小规模的 I/O 整理成平稳的小数量较大规模的 I/O,以 减少响应次数 ByteBuffer: 长度固定,一旦分配完成,它的容量不能动态扩展和收缩,当需要编码的POJO对象大于ByteBuffer的容量时,会发生索引越界异常; ByteBuffer只有一个标识位控的指针position,读写的时候需要手工调用flip()和rewind()等,使用者必须小心谨慎地处理这些API,否则很容易导致程序处理失败; ByteBuffer的API功能有限,一些高级和实用的特性它不支持,需要使用者自己编程实现。 需要的话,可以自定义buffer类型; 通过组合buffer类型,可实现透明的zero-copy; 提供动态的buffer类型,如StringBuffer一样,容量是按需扩展; 如果c<t,则n从阈值t(4MB)开始,以每次增加2倍的方式扩容,直到双倍后的大小小于c; 如果c>t,则n=c/t*t+t 无需调用flip()方法;方法反转(讲Buffer从读模式变成写模式) 常常比 ByteBuffer (JDK的)快 使用了读写两个指针,分别记录读写的位置,复杂操作更简单 堆内存和直接内存