内存碎片

垃圾收集算法

假如想象 提交于 2020-02-08 16:59:07
收集算法思想: 垃圾收集算法的实现涉及大量的程序细节,仅介绍几种算法的思想以及发展过程。 标记-清除算法 最基础的后手算法,算法可分为标记、清除两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象,标记算法即二次标记过程。 不足之处: ①效率问题,标记和清除两个过程的效率都不高 ②空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾回收动作 复制算法 解决标记-清除算法效率问题,讲可用内存划分为内存大小相同的两块,每次只使用其中一块。当一块内存用完时,就将还存活着的对象复制到另外一块上面,然后再把使用过的内存一次性清理。这样使得内存分配实现简单、运行高效,仅需要按顺序分配内存空间即可。 缺点:内存可用空间缩小为原来的一半。 解决方案:将该类算法应用于新生代(新生代对象98%“朝生夕死”),无需按1:1划分,可将新生代内存划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用一块Eden空间与一块Survivor空间。每当回收时对正在使用的Eden和Survivor空间进行垃圾收集,存活的对象将一次性复制到空闲的另一块Survivor空间(大对象将直接进入老年代)。 担保:10%的内存区域并不是每次都足以容纳继续存活的新生代对象

完全用Linux工作-王垠

别说谁变了你拦得住时间么 提交于 2020-02-08 10:34:54
《完全用Linux工作》作者:王垠 完全用 GNU/Linux 工作 理解 GNU/Linux 更多精彩请直接访问 SkySeraph个人站点 : www.skyseraph.com 注:本文是清华“牛仔”王垠的“成名作”,在网上引起很大的争议。对他崇拜地五体投地者有,对他嗤之以鼻者也有,总之成了一年多以前Linux 爱好者的圈子里的一个很有意思的现象。之后他对这篇文章进行了很大的修改,已经没有了原来那种意气风发。现存的版本如白开水一般无味,请参见: http://learn.tsinghua.edu.cn/homepage/2001315450/ 尽管他原来的观点有所偏激,但我还是很欣赏他原来的风格。 “UNIX 是简单的,你不需要成为天才也能理解这种简单。” 由于GNU/Linux这个词太长,下面如果没有特别指明,“Linux”就是指“GNU/Linux”。 在这个年代,恐怕没有人需要我来介绍 Linux 是什么了吧?如果你觉得“ Linux 只不过是跟 DOS 差不多的东西”,那你恐怕很久在山洞里没见天日了吧?请问问你旁边的 Linux 用户, Linux 到底是个什么地位? 那为什么我还要写一篇这样的文章?因为,我发现还有很多人不不理解 Linux 和 UNIX ,虽然他们也在用它,但是他们有时会问:“为什么 Linux 不能像 Windows 那样 …… ?”,“怎么

为什么栈的速度比堆快

自闭症网瘾萝莉.ら 提交于 2020-02-08 03:58:53
在栈上分配的内存系统会自动地为其释放,例如在函数结束时,局部变量将不复存在,就是系统自动清除栈内存的结果。但堆中分配的内存则不然:一切由你负责,即使你退出了new表达式的所处的函数或者作用域,那块内存还处于被使用状态而不能再利用。好处就是如果你想在不同模块中共享内存,那么这一点正合你意,坏处是如果你不打算再利用这块内存又忘了把它释放掉,那么它就会霸占你宝贵的内存资源直到你的程序退出为止。 栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。 C/C++中,所有的方法调用都是通过栈来进行的,所有的局部变量,形式参数都是从栈中分配内存空间的。实际上也不是什么分配,只是从栈顶向上用就行,就好像工厂中的传送带(conveyorbelt)一样,StackPointer会自动指引你到放东西的位置,你所要做的只是把东西放下来就行.退出函数的时候

《go语言从入门到进阶实战》_徐波

痞子三分冷 提交于 2020-02-08 02:02:57
摘录 Go语言是Google公司开发的一种静态型、编译型并自带垃圾回收和并发的编程语言。 Go语言不使用虚拟机,只有运行时(runtime)提供垃圾回收和goroutine调度等。 Go语言使用自己的链接器,不依赖任何系统提供的编译器、链接器。因此编译出的可执行文件可以直接运行在几乎所有的操作系统和环境中。 从Go 1.5版本之后,Go语言实现自举,实现了使用Go语言编写Go语言编译器及所有工具链的功能。 Go语言可以利用自己的特性实现并发编译,并发编译的最小元素是包。从Go 1.9版本开始,最小并发编译元素缩小到函数,整体编译速度提高了20%。 Go语言的并发是基于goroutine,goroutine类似于线程,但并非线程。可以将goroutine理解为一种虚拟线程。Go语言运行时会参与调度goroutine,并将goroutine合理地分配到每个CPU中,最大限度地使用CPU性能。 在Go语言中,自增操作符不再是一个操作符,而是一个语句。因此,在Go语言中自增只有一种写法: i++ 如果写成前置自增“++i”,或者赋值后自增“a=i++”都将导致编译错误。 在多个短变量声明和赋值中,至少有一个新声明的变量出现在左值中,即便其他变量名可能是重复声明的,编译器也不会报错。 布尔型无法参与数值运算,也无法与其他类型进行转换。 切片发生越界时,运行时会报出宕机,并打出堆栈

Java--基础知识之JVM

走远了吗. 提交于 2020-02-08 01:34:21
一、什么是JVM 1、概念 JVM,即Java Virtual Machine(Java虚拟机),是Java和的核心和基础,是在Java编译器和操作系统平台间的虚拟处理器。JVM是利用软件方法实现的抽象的、计算机基于下层的操作系统和硬件平台可以在上面执行Java程序的字节码程序。 2、特点 JVM有完善的硬件架构(如处理器、堆栈、寄存器),其存在是为了支持与操作系统无关,实现Java跨平台。 3、Java的跨平台性 真正跨平台的是Java程序而非JVM。不同平台下安装了不同版本的JVM。编写的Java源码在编译后生成class文件(字节码文件),JVM是负责将这些字节码文件翻译成特定平台下的机器码然后运行,即在不同平台下安装对应的JVM,就可以运行编写的Java程序。而这个过程中Java程序没有做任何改变,只是通过JVM在不同平台上运行罢了,可以说是“一次编译,多处运行”。 4、启动与消亡 JVM负责运行一个Java程序,当启动一个Java程序时,也产生一个虚拟机实例,当程序关闭时这个虚拟机实例也消亡。 JVM运行起点:Java虚拟机实例通过调用某个初始类的main方法来运行Java程序,这个main方法是共有的、静态的、返回值为void类型,并传入一个字符串数组作为参数。 5、两种线程 (1)守护线程:通常由虚拟机自己使用,比如执行垃圾收集任务的线程

JVM基础快速入门篇

妖精的绣舞 提交于 2020-02-07 21:00:16
Java是一门可以跨平台的语言,但是Java本身是不可以实现跨平台的,需要JVM实现跨平台。javac编译好后的class文件,在Windows、Linux、Mac等系统上,只要该系统安装对应的Java虚拟机,class文件都可以运行。达到”一次编译,到处运行”的效果。 一、JVM是什么? 而JVM到底是什么呢?引用百度百科对JVM的介绍: JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 二、JVM架构知识 1.JVM主要包含 类装载器、运行时数据区(内存模型)、执行引擎 。里面内存模型有可以细分包括本地方法栈、堆、栈(线程)、方法区(元空间)、程序计数器。如图所示: 1. 类装载器的作用就是负责加载class文件,class文件在文件开头有特定的文件标示,将class文件字节码内容加载到内存中,并将这些内容转换成方法区中的运行时数据结构并且ClassLoader只负责class文件的加载 ,至于它是否可以运行,则由执行引擎(Execution Engine)决定。类加载器又有四大类加载器: 启动类加载器(Bootstrap ClassLoader):负责加载JRE核心类库,像JRE中的rt.jar等(C/C++); 扩展类加载器

Go内存管理

走远了吗. 提交于 2020-02-07 06:59:31
1.前言 编写过C语言程序的肯定知道通过malloc()方法动态申请内存,其中内存分配器使用的是glibc提供的ptmalloc2。 除了glibc,业界比较出名的内存分配器有Google的tcmalloc和Facebook的jemalloc。 二者在避免内存碎片和性能上均比glic有比较大的优势,在多线程环境中效果更明显。 Golang中也实现了内存分配器,原理与tcmalloc类似,简单的说就是维护一块大的全局内存,每个线程(Golang中为P)维护一块小的私有内存,私有内存不足再从全局申请。 另外,内存分配与GC(垃圾回收)关系密切,所以了解GC前有必要了解内存分配的原理。 2.内存分配概览 3.基础概念 3.1预分配内存 为了方便自主管理内存,做法便是先向系统申请一块内存,然后将内存切割成小块,通过一定的内存分配算法管理内存。以64位系统为例,Golang程序启动时会向系统申请的内存,预申请的内存划 分为spans、bitmap、arena三部分。其中arena即为所谓的堆区,应用中需要的内存从这里分配。其中spans和bitmap是为了管理arena区而存在的。 arena的大小为512G,为了方便管理把arena区域划分成一个个的page,每个page为8KB,一共有512GB/8KB个page; spans区域存放span的指针,每个指针对应一个page

Java内存

試著忘記壹切 提交于 2020-02-06 16:06:36
Java 虚拟机在执行 Java 程序的过程中会把他所管理的内存划分为若干个不同的数据区域。Java 虚拟机规范将 JVM 所管理的内存分为以下几个运行时数据区:程序计数器、Java 虚拟机栈、本地方法栈、Java 堆、方法区。 一,内存区域划分   1.线程共享区域:     (1)Java堆(对象实例),GC的主要区域,会出现OutOfMemoryError     (2)方法区(加载的类信息,常量,静态变量,即时编译器编译后的代码)会出现OutOfMemoryError   2.线程私有区域:     (1)虚拟机栈(操作数栈,动态链接,方法返回地址,局部变量)       用于支持虚拟机进行方法方法调用和方法执行的数据结构。生命周期与线程相同,每个方法执行时会创建一个栈帧并入栈,对于执行引擎,活动线程中,只有栈顶的栈帧是有效的,称为当前栈帧,所关联的方法称为当前方法。       如果申请的栈深度大于虚拟机允许的栈深度则抛出StackOutflowError       如果在动态扩展时,无法申请到足够的内存则抛出OutOfMemoryError       单线程:无论是栈空间太大,还是虚拟机内存太小,抛出的都是StackOutflowError       多线程:抛出OutOfMemoryError         局部变量表:是一组变量值存储空间

Python的基础语法(二)

雨燕双飞 提交于 2020-02-06 01:01:34
0. 前言 接着上一篇 博客 的内容,我将继续介绍Python相关的语法。部分篇章可能不只是简单的语法,但是对初学者很有帮助,也建议读懂。 1. 表达式 由数字、符号、括号、变量等组成的组合。 算术表达式 逻辑表达式 赋值表达式 在Python中,变量无需实现声明,也不需要指定类型。 a = 1 # 无需声明和指定类型 在Python中,赋值即定义,如果一个变量已经定义,赋值相当于重新定义。 2. 内存管理 在其他语言,如C++和C中,内存管理是非常重要的,因为在一段内存地址被释放之后,内存中会留下一个“空洞”,造成内存碎片化。通常地,开发者会利用特定的策略来管理内存,把需要经常变动的值放到一个区域,静态的值放到另一个区域。开发者手动管理维护内存,不仅麻烦,还很容易留下安全隐患。 在Python编程中无须关心变量的存亡,也不关心内存的管理。 Python语言和Java一样,采用了类似的垃圾收集的机制(Garbage Collection)。 简单的理解:首先,在Python中,一切皆对象。Python使用引用计数 ob_refcnt 记录所有对象的引用数。当对象引用数 ob_refcnt 变为0,它就被认为是生命结束了,内存也会被回收。例如在函数运行结束时,局部变量就会被自动销毁,内存被回收。变量赋值给其他对象时,内存被回收。下面举一个例子: num1 = 12 # 定义一个变量

Cracking Digital VLSI Verification Interview 第三章

大憨熊 提交于 2020-02-05 21:49:51
目录 Programming Basics Basic Programming Concepts Object Oriented Programming Concepts UNIX/Linux Programming in C/C++ Programming in PERL Programming Basics Basic Programming Concepts [68] 在任何一种编程语言中,静态(static)变量和自动(automatic)变量,局部(local)变量和全局(global)变量之间有什么区别? 区分这些名词需要两个概念,作用域(scope)和存储持续时间(storage duration),前者定义了在何处可以访问变量,后者定义了在何时可以访问变量。 按照变量的作用域可以区分局部(local)和全局(global)变量。局部变量的作用范围有限,尽在声明它们的代码块中可见。而全局变量在声明后在程序的任何位置都可见。 存储持续时间可以区分自动(automatic)变量和静态(static)变量。静态变量的生命周其一直持续到程序结束,因此可以始终访问。自动变量具有有限的生命周期,只能持续到程序离开定义的块或者作用域为止。 例如:在以下的systemverilog代码中,global_int被声明为类成员,并且在整个类中具有全局作用域,而当取消引用该类的对象时