内存碎片

VC++中内存对齐

不想你离开。 提交于 2020-03-24 03:01:27
我们经常看到求 sizeof(A) 的值的问题,其中A是一个结构体,类,或者联合体。 为了优化CPU访问和优化内存,减少内存碎片,编译器对内存对齐制定了一些规则。但是,不同的编译器可能有不同的实现,本文只针对VC++编译器,这里使用的IDE是VS2012。 #pragma pack()是一个预处理,表示内存对齐。布局控制#pragma,为编译程序提供非常规的控制流信息。 /**********结构体的大小的规则*************/ 结构体大小是处理器位数和结构体内最长数据元素所占字节数二者中较小的那一个的整数倍。 比如说,假设处理器位数为n,结构体内最大数据元素所占字节数为m。 处理器为32位,n = 4;结构体内最大数据类型为short,m = 2; n > m;结构体大小为m的整数倍,反之亦然。 注意:有些虽然是64位的操作系统,但是编译器却是32位的,此时位数为32. 1 class A{ 2   int a; 3   char b; 4   short c; 5 }; sizeof(A)为8,为4的整数倍。 1 struct B{ 2 short a; 3 short b; 4 short c; 5 }; sizeof(B)为6,为2(sizeof(short))的整数倍。 注意:C++中的结构体与类只有一个区别,就是结构体成员默认是public

高性能-GC

╄→尐↘猪︶ㄣ 提交于 2020-03-24 02:21:33
带着问题去思考!大家好 相对.NET 来说。CLR去处理了,C,C++这些就需要手动去垃圾回收。   GC大部分容易察觉的性能问题。其实很多问题实际是哪个都是由于对垃圾回收器的行为和预期结果理解有误。在,NET环境中,你需要更多的关注内存的性能,那么接下里我们主要是讲内存性能问题。   GC实际上会调整体提高内存堆[1]的性能,因为他能高效的完成内存分配和碎片整理工作。   在Windows的本机代码模式下,内存堆维护着一张空闲内存块的列表,用于内存的分配,尽量用低碎片化的内存堆,因为长时间运行,还要考虑内存碎片问题,内存占用率会持续增长。所以本机代码程序用大量代码实现了自己的内存分配机制,把默认的malloc函数给替换掉   在.NET环境中,内存分配的工作量会很小,因为内存总是整段分配的。所以不会比内存的扩大,减小和比较增加多少开销,不存在遍历空闲内存列表,几乎不会出现内存碎片,GC内存堆的效率还会更高的,因为连续分配的多个对象往往在内存堆中也是连续存放,提高就近访问的可能性。   在默认的内存分配流程中,有一小段代码会先检查目标对象的大小,看看内存分配缓冲区中所剩的内存够不够,如果内存分配缓冲区已耗尽,就会交由GC分配程序来检索足以容纳目标对象的空闲内存。然后一个新的分配缓冲区就会被保留下来。   接下里看下内存分配的过程 class MyObject { int x;

堆和栈的区别(转过无数次的文章)

这一生的挚爱 提交于 2020-03-23 11:08:04
一、预备知识—程序的内存分配 一个由C/C++编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其 操作方式类似于数据结构中的栈。 2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回 收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的 全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另 一块区域。 - 程序结束后由系统释放。 4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放 5、程序代码区—存放函数体的二进制代码。 二、例子程序 这是一个前辈写的,非常详细 //main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char *p2; 栈 char *p3 = "123456"; 123456/0在常量区,p3在栈上。 static int c =0; 全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); 分配得来得10和20字节的区域就在堆区。

Java JVM 相关基础知识

别来无恙 提交于 2020-03-22 13:35:00
1.JMM Java内存模型 每条线程都有自己的工作内存[Working Memory] 线程的工作内存保存了被该线程使用的变量的主内存副本拷贝 线程对变量的所有线程之间也无法直接访问对方工作内存的变量,线程间变量值的传递均需要通过主内存来完成。 2.java的堆和栈 1)堆 heap:可动态申请的内存空间(其记录空闲内存空间的链表由操作系统维护);     其中的内存在不需要时可以回收,以分配给新的内存请求,其 内存中的数据是无序的 ;     一般由使用者自由分配,malloc 分配的就是堆,需要手动释放;     被所有线程共享的一块内存区域,在虚拟机启动时创建, 此内存区域的唯一目的就是存放对象实例 。 2)栈 stack:先进后出的数据结构,通常用于保存方法(函数)中的参数,局部变量.;     在 java 中,所有基本类型和引用类型都在栈中存储.栈中数据的生存空间一般在当前 scopes 内(就是由{...}括起来的区域);      先分配的内存必定后释放 ;     一般由系统自动分配,存放函数的参数值,局部变量等,自动清除 3.方法区 本地方法栈 1)方法区 Method Area:和Java 堆一样,别名叫做 Non-Heap(非堆),是各个线程共享的内存区域;           它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据

内存池

元气小坏坏 提交于 2020-03-21 19:57:59
http://blog.csdn.net/neustar1/article/details/7478311 利用C/C++开发大型应用程序中,内存的管理与分配是一个需要认真考虑的部分。 本文描述了内存池设计原理并给出内存池的实现代码,代码支持Windows和Linux,多线程安全。 内存池设计过程中需要考虑好内存的分配与释放问题,其实也就是空间和时间的矛盾。 有的内存池设计得很巧妙,内存分配与需求相当,但是会浪费过多的时间去查找分配与释放,这就得不偿失; 实际使用中,我们更多的是关心内存分配的速度,而不是内存的使用效率。基于此,本文按照如下思想设计实现内存池。 主要包含三个结构:StiaticMemory, MemoryChunk和MemoryBlock,三者之间的关系如下图所示: 1.内存的分配: (1)如果分配大小超过1024,直接采用malloc分配,分配的时候多分配sizeof(size_t)字节,用于保存该块的大小; (2)否则根据分配大小,查找到容纳该大小的最小size的MemoryChunk; (3)查找MemoryChunk的链表指针pList,找到空闲的MemoryBlock返回; (4)如果pList为NULL,临时创建MemoryBlock返回; (5)MemoryBlock头部包含两个成员,pChunk指向的所属的MemoryChunk对象,size表明大小

内存管理

主宰稳场 提交于 2020-03-21 19:46:18
不光还是游戏引擎,任何一个项目都有必要做好内存管理,至少可以监控内存使用量和内存泄露。而对于游戏引擎而言更是如此,在游戏引擎里面动态分配释放内存的地方不在少数,做好内存管理对于提高引擎运行效率是十分必要的。 内存管理就是做两件事,负责内存的分配和释放,再有就是对内存的分配释放进行监控,据此来解决内存泄露和掌握内存使用情况。 先说说内存分配释放,这也是内存管理最重要的部分。一般来说内存管理只管理小内存的分配释放,大内存则无需管理制作监控即可。过多的小内存分配释放会造成系统内存碎片从而可能分配不下内存,与此同时过多的调用系统的内存分配释放函数也是低效。malloc,free这些函数本身就很慢。 现在问题的本质出来了,内存管理关的就是小内存的分配释放,要采用某种办法避免经常性的调用系统的分配释放函数,简单来说就是要解决这个问题。具体办法是这样的,以Unreal的内存管办法为例,他认为32k以下的内存都是小内存,>32k的不作管理。当申请size大小的内存时他一次性分配64k,这样就获得了64k/size个内存块,这就是一个池,当再次分配同样大小的内存时则从这个池中取不仅新真正的内存分配,当池满了则在分配64k以同样的方法管理,当池空了的时候释放这64k的内存。可以看出他的内存分配单位是64k,且只有在池满了或者池空后才做真正的内存分配释放。 再说说内存监控,这一块可发挥的空间非常大

STL中的内存分配器原理

丶灬走出姿态 提交于 2020-03-21 18:52:44
题记:内存管理一直是C/C++程序的红灯区。关于内存管理的话题,大致有两类侧重点,一类是内存的正确使用,例如C++中new和delete应该成对出现,用RAII技巧管理内存资源,auto_ptr等方面,很多C/C++书籍中都使用技巧的介绍。另一类是内存管理的实现,如linux内核的slab分配器,STL中的allocator实现,以及一些特定于某种对象的内存管理等。最近阅读了一些内存管理实现方面的资料和源码,整理了一下,汇编成一个系列介绍一些常用的内存管理策略。 1. STL容器简介 STL提供了很多泛型容器,如vector,list和map。程序员在使用这些容器时只需关心何时往容器内塞对象,而不用关心如何管理内存,需要用多少内存,这些STL容器极大地方便了C++程序的编写。例如可以通过以下语句创建一个vector,它实际上是一个按需增长的动态数组,其每个元素的类型为int整型: stl::vector<int> array; 拥有这样一个动态数组后,用户只需要调用push_back方法往里面添加对象,而不需要考虑需要多少内存: array.push_back(10); array.push_back(2); vector会根据需要自动增长内存,在array退出其作用域时也会自动销毁占有的内存,这些对于用户来说是透明的,stl容器巧妙的避开了繁琐且易出错的内存管理工作。 2.

STL的内存分配器

耗尽温柔 提交于 2020-03-21 18:51:25
题记: 内存管理一直是C/C++程序的红灯区。关于内存管理的话题,大致有两类侧重点,一类是内存的正确使用,例如C++中new和delete应该成对出现,用RAII技巧管理内存资源,auto_ptr等方面,很多C/C++书籍中都使用技巧的介绍。另一类是内存管理的实现,如 linux内核 的slab分配器,STL中的allocator实现,以及一些特定于某种对象的内存管理等。 最近阅读了一些内存管理实现方面的资料和源码,整理了一下,汇编成一个系列介绍一些常用的内存管理策略。 1. STL容器简介 STL提供了很多泛型容器,如vector,list和map。程序员在使用这些容器时只需关心何时往容器内塞对象,而不用关心如何管理内存,需要用多少内存,这些STL容器极大地方便了C++程序的编写。例如可以通过以下语句创建一个vector,它实际上是一个按需增长的动态数组,其每个元素的类型为int整型: stl::vector<int> array; 拥有这样一个动态数组后,用户只需要调用push_back方法往里面添加对象,而不需要考虑需要多少内存: array.push_back(10); array.push_back(2); vector会根据需要自动增长内存,在array退出其作用域时也会自动销毁占有的内存,这些对于用户来说是透明的,stl容器巧妙的避开了繁琐且易出错的内存管理工作。 2

stl内存管理

心已入冬 提交于 2020-03-21 18:50:23
STL提供了很多泛型容器,如vector,list和map。程序员在使用这些容器时只需关心何时往容器内塞对象,而不用关心如何管理内存,需要用多少内存,这些STL容器极大地方便了C++程序的编写。例如可以通过以下语句创建一个vector,它实际上是一个按需增长的动态数组,其每个元素的类型为int整型: stl::vector<int> array; 拥有这样一个动态数组后,用户只需要调用push_back方法往里面添加对象,而不需要考虑需要多少内存: array.push_back(10); array.push_back(2); vector会根据需要自动增长内存,在array退出其作用域时也会自动销毁占有的内存,这些对于用户来说是透明的,stl容器巧妙的避开了繁琐且易出错的内存管理工作。 隐藏在这些容器后的内存管理工作是通过STL提供的一个默认的allocator实现的。当然,用户也可以定制自己的allocator,只要实现allocator模板所定义的接口方法即可,然后通过将自定义的allocator作为模板参数传递给STL容器,创建一个使用自定义allocator的STL容器对象,如: stl::vector<int, UserDefinedAllocator> array; 大多数情况下,STL默认的allocator就已经足够了

Java程序性能优化Tip

你说的曾经没有我的故事 提交于 2020-03-21 05:43:24
本博客是阅读<java time and space performance tips>这本小书后整理的读书笔记性质博客,增加了几个测试代码,代码可以在此下载: java时空间性能优化测试代码 ,文件StopWatch是一个秒表计时工具类,它的代码在文末。 1. 时间优化 1.1 标准代码优化 a. 将循环不变量的计算移出循环 我写了一个测试例子如下: import util.StopWatch; /** * 循环优化: * 除了本例中将循环不变量移出循环外,还有将忙循环放在外层 * @author jxqlovejava * */ public class LoopOptimization { public int size() { try { Thread.sleep(200); // 模拟耗时操作 } catch(InterruptedException ie) { } return 10; } public void slowLoop() { StopWatch sw = new StopWatch("slowLoop"); sw.start(); for(int i = 0; i < size(); i++); sw.end(); sw.printEclapseDetail(); } public void optimizeLoop() { StopWatch sw =