精华内容
下载资源
问答
  • 解决内存碎片问题

    2017-11-08 22:34:00
    经常的new delete 导致可用内存越来越小, 这就是内存碎块 就是内存有各种各样大小不一样的节点 , 长时间在 new delete 这时候操作系统 在内存, 上分一块内存给你, 分...什么东西需要防止内存碎片呢?一般需要大量...

    经常的new delete 导致可用内存越来越小, 这就是内存碎块
    就是内存有各种各样大小不一样的节点 ,
    长时间在 new delete 这时候操作系统 在内存,
    上分一块内存给你, 分出去了 好几块,内存紧张了, 释放这中间 就有一些内存用不了
    就是有一些很小的空闲内存, 但是你申请的空间 可能就比他们要大,
    什么东西需要防止内存碎片呢?一般需要大量数据节点的,都需要自己的缓冲池
    也就是根据系统的负载开一块很大的内存出来,比如一个在线用户的信息 节点
    因为你一天的活跃用户可能上万,但是当前可能在线的可能只有三千,五千
    也就是你一天 会有成千上万的用户 上线, 如果去冲击系统的new malloc
    ,那么就会造成内存碎片为了 解决这个文件,就要对这些节点做缓冲池**

    解决内存碎片问题

    代码设计

    #define MAX_SESSION_NUM 6000  //缓冲池大小
    #define my_malloc malloc 
    #define my_free free
    
    //用户节点结构体
    struct  session{
        char c_ip[32];
        int c_port;
        int c_sock;
        struct  session * _next;
    
    };
    
    struct {
    
        struct session* online_session;
    
        struct session* cache_mem; //缓存池
    
        struct session* free_list;  //链表头指针
    
    }session_manager ;
    
    //清空内存
        memset(&session_manager, 0, sizoef(session_manager));
        //将6000节点  一次缓冲池分配出来 
        session_manager.cache_mem = (struct session*)my_malloc(MAX_SESSION_NUM * sizeof(struct session));
        memset(session_manager.cache_mem, 0, MAX_SESSION_NUM * sizeof(struct session));
            //把没有使用的list全部放在 free_list 链表
                for (int i = 0; i<MAX_SESSION_NUM;i++){
            session_manager.cache_mem[i]._next = session_manager.free_list;
            session_manager.free_list = &session_manager.cache_mem[i];
    
        }
    
        定义分配器
        static struct session* cache_alloc(){
        struct session*s = NULL;
        //可用的 缓冲池 必须是有节点 才能分配
        if (session_manager.free_list != NULL){
            s = session_manager.free_list;
            //因为free_list 指向缓冲池里最后一个节点
            //分配一个后 这个可用缓冲池 就指向上一个缓冲节点  
            session_manager.free_list = s->_next;
        }
        else{
        //当可用缓冲池用完,防止程序奔溃 在极少数的情况下
        //这时候就要调用系统的分配内存   
        //少次数的调用malloc  不会引发内存碎片
            s = my_malloc(sizeof(struct  session));
    
        }
        //情况当前内存信息  应为可能存在使用情况
        memset(s,0, sizeof(struct session));
        return s;
    }
    
    static void cache_free(struct session* s)
    {
        //判断是从 cache 分配的 还是从系统 malloc分配的
        //只需要判断 他的内存范围 是不是在这个分配的内存里面
        if (s >= session_manager.cache_mem && s < session_manager.cache_mem + MAX_SESSION_NUM)
        {
            //内存不释放  
            //当前使用的 上一个就是申请时 赋值给free_list的
            s->_next = session_manager.free_list;
            //记录当前这个节点
            session_manager.free_list = s;
    
        }
        else{//系统分配的
            my_free(s);
        }
    }
    

    这是上面的调试信息
    解决内存碎片问题

     本文转自超级极客51CTO博客,原文链接:http://blog.51cto.com/12158490/2057439,如需转载请自行联系原作者





    展开全文
  • 垃圾回收算法 ...标记清除算法带来的一个问题是会存在大量的空间碎片,因为回收的空间是不连续的,这样给大对象分配内存的时候可能会提前触发full gc. 复制算法 将现有的内存空间分为两块,每次只...

    垃圾回收算法

    1. 标记清除
      标记——清除算法将垃圾回收分为两阶段:标记阶段和清除阶段。在标记阶段首先通过根节点,标记所有从根节点开始的对象,未被标记的对象就是未被引用垃圾对象。然后,在清除阶段,清除所有未被标记的对象。标记清除算法带来的一个问题是会存在大量的空间碎片,因为回收的空间是不连续的,这样给大对象分配内存的时候可能会提前触发full gc.

    2. 复制算法
      将现有的内存空间分为两块,每次只使用其中的一块,在垃圾回收是将正在使用的内存中的存活对象复制到未被使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收。

    3. 标记整理
      复制算法的高效性是建立在存活对象少、垃圾对象多的前提下。这种情况在新生代经常发生,但是在老年代更常见的情况是大部分对象都是存活对象。如果依然使用复制算法,由于存活的对象较多,复制的成本也将很高。
      标记-压缩算法是一种老年代的回收算法,它在标记-清除算法的基础上做了一些优化。首先也需要从根节点开始对所有可达对象做一次标记,但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外的所有空间。这种方法即避免了碎片的产生,又不需要两块相同的内存空间。因此,它的性价比比较高

    4. 增量算法
      增量算法的基本思想是,如果一次性将所有的垃圾进行处理,需要造成系统长时间的停顿,那么就可以将垃圾收集线程和应用程序交替执行。每次,垃圾收集线程只收集一小片区域的内存空间,接着切换到应用程序线程。依次反复,直到垃圾收集完成。使用这种方式,由于在垃圾回收过程中,间断性的还执行了应用程序代码,所以能减少系统的停顿时间。但是,因为线程切换和上下文转换的消耗,会使得垃圾回收的总体成本上升,造成系统吞吐量的下降

    垃圾回收器

    1. Serial收集器
    Serial收集器是最古老的收集器,它的缺点是当Serial收集器想进行垃圾回收的时候,必须暂停用户的所有进程,即stop the world。到现在为止,它依然是虚拟机运行在client模式下的默认新生代收集器,与其他收集器相比,对于限定在单个CPU的运行环境来说,Serial收集器由于没有现成交互的开销,专心做垃圾回收自然获得最高的单线程收集效率。

    2. ParNew收集器
    ParNew收集器是Serial收集器新生代的多线程实现,注意在进行垃圾回收的时候依然会stop the world,只是相比较Serial收集器而言它会运行多条进程进行垃圾回收。
    ParNew收集器在单CPU的环境中绝对不会有比Serial收集器更好的效果,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU的环境中都不能百分百保证超越Serial收集器。当然,随着可以使用的CPU的数量增加,它对于GC时系统资源的利用还是很有好处的。它默认开启的收集线程数与CPU的数量相同,在CPU非常多的环境下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

    3.Parallel Scavenge收集器
    Parrallel是采用复制算法的多线程新生代垃圾回收器,似乎和ParNew收集器有很多相似的地方。但是Parallel Scanvenge收集器的一个特点是它所关注的目标是吞吐量。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)。停顿时间越短就越适合需要与用户交互的程序,良好的响应速度能够提升用户的体验;而高吞吐量则可以最高效率的利用CPU时间,尽快完成程序的运算速度,主要适合在后台运算而不需要太多交互的任务。

    4.CMS收集器
    CMS收集器是一个比较重要的收集器,现在应用非常广泛,我们重点来看一下,CMS一种获取最短回收停顿时间为目标的收集器,这使得它很适合用于和用户交互的业务。从名字就可以看出,CMS收集器基于标记清除算法实现的。它的收集过程分为四个步骤。

    • 初始标记
    • 并发标记
    • 重新标记
    • 并发清除

    注意初始标记和重新标记还是会stop the world ,但是在耗费时间更长的并发标记和并发清除两个阶段都可以和用户进程同时工作。

    5.G1收集器
    G1收集器是一款面向服务端应用的垃圾收集器。HotSpot团队赋予它的使命是在未来替换掉CMS收集器。与其他GC收集器相比,G1具备如下特点:

    • 并行与并发:G1能够充分利用CPU。多核环境下的硬件优势来缩短stop the world的停顿时间。
    • 分代收集:和其他收集器一样,分代的概念在G1中依然存在,不过G1不需要其他垃圾回收器的配合就可以独自管理整个GC堆。
    • 空间整合:G1收集器有利于程序长时间运行,分配大对象时不会无法得到连续空间而提前触发一次GC.
    • 可预测的非停顿:这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同的关注点,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。

    CMS:采用标记清除算法

    解决这个问题的办法就是可以让CMS在进行一定次数的Full GC(标记清除)的时候进行一次标记整理算法,CMS提供了一下参数来控制:

    -XX:UseCMSCompactAtFullCollection -XX:CMSFullGCBeforeCompaction=5

    也就是CMS在进行5次Full GC(标记清除)之后进行一次标记整理算法,从而可以控制老年带的碎片在一定数量以内,甚至可以配置CMS在每次Full GC的时候都进行内存的整理。

    							***帅气的远远啊***
    
    展开全文
  • 如何解决内存碎片

    千次阅读 2016-03-29 22:20:20
    内存碎片的产生: 内存分配有静态分配和动态分配两种... 因此动态分配将不可避免会产生内存碎片问题,那么什么是内存碎片内存碎片即“碎片的内存”描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使用

    内存碎片的产生:
    内存分配有静态分配和动态分配两种
    静态分配在程序编译链接时分配的大小和使用寿命就已经确定,而应用上要求操作系统可以提供给进程运行时申请和释放任意大小内存的功能,这就是内存的动态分配。
    因此动态分配将不可避免会产生内存碎片的问题,那么什么是内存碎片?内存碎片即“碎片的内存”描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使用,是因为负责动态分配内存的分配算法使得这些空闲的内存无法使用,这一问题的发生,原因在于这些空闲内存以小且不连续方式出现在不同的位置。因此这个问题的或大或小取决于内存管理算法的实现上。
    为什么会产生这些小且不连续的空闲内存碎片呢?
    实际上这些空闲内存碎片存在的方式有两种:a.内部碎片 b.外部碎片 。
    内部碎片的产生:因为所有的内存分配必须起始于可被 4、8 或 16 整除(视处理器体系结构而定)的地址或者因为MMU的分页机制的限制,决定内存分配算法仅能把预定大小的内存块分配给客户。假设当某个客户请求一个 43 字节的内存块时,因为没有适合大小的内存,所以它可能会获得 44字节、48字节等稍大一点的字节,因此由所需大小四舍五入而产生的多余空间就叫内部碎片。
    外部碎片的产生: 频繁的分配与回收物理页面会导致大量的、连续且小的页面块夹杂在已分配的页面中间,就会产生外部碎片。假设有一块一共有100个单位的连续空闲内存空间,范围是0~99。如果你从中申请一块内存,如10个单位,那么申请出来的内存块就为0~9区间。这时候你继续申请一块内存,比如说5个单位大,第二块得到的内存块就应该为10~14区间。如果你把第一块内存块释放,然后再申请一块大于10个单位的内存块,比如说20个单位。因为刚被释放的内存块不能满足新的请求,所以只能从15开始分配出20个单位的内存块。现在整个内存空间的状态是0~9空闲,10~14被占用,15~24被占用,25~99空闲。其中0~9就是一个内存碎片了。如果10~14一直被占用,而以后申请的空间都大于10个单位,那么0~9就永远用不上了,变成外部碎片。

    如何解决内存碎片:
    采用Slab Allocation机制:整理内存以便重复使用
    最近的memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。
    下面来看看Slab Allocator的原理。下面是memcached文档中的slab allocator的目标:he primary goal of the slabs subsystem in memcached was to eliminate memory fragmentation issuestotally by using fixedsizememory chunks coming from a few predetermined size classes.
    也就是说,Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。Slab Allocation的原理相当简单。将分配的内存分割成各种尺寸的块(chunk),并把尺寸相同的块分成组(chunk的集合)

    展开全文
  • python,node.js这样的高级语言怎么解决内存碎片问题呢? 鼓吹node.js的人都会提到node.js有谷歌的v8引擎,他是有多先进,但他没想过v8是为浏览器设计的,他是不会遇到像服务端程序会遇到的内存碎片问题,一个...

    c/c++可以自己管理内存,像nginx可以根据自己的业务特点,为每一个请求分配一个内存池,请求结束,内存池也就可以释放了


    python,node.js这样的高级语言怎么解决内存碎片问题呢?


    鼓吹node.js的人都会提到node.js有谷歌的v8引擎,他是有多先进,但他没想过v8是为浏览器设计的,他是不会遇到像服务端程序会遇到的内存碎片问题,一个页面不可能一直打开着吧,关掉页面,这些内存就全部释放掉了。服务端程序会遇到内存碎片问题,类似于文件系统,一个4kb的块,只用1kb,另外3kb就浪费掉了,也没办法回收。要么就定期整理磁盘,貌似java就会类似于整理磁盘一样挪动对象,需要付出代价就是消耗CPU。v8就什么都没做,其实他也没必要做,因为他是为浏览器设计的,在浏览器应用场景中压根就不会有问题,设计的时候就不会要考虑了。

    现在想一个php还真是最好的编程语言呢(笑),足够简单,每一刻都是崭新的。



    展开全文
  • 老年代 FULL GC垃圾收集后产生内存碎片 无法提供连续的内存空间 如何解决内存碎片问题
  • 内存碎片问题

    2015-05-29 00:37:25
    最近遇到内存碎片问题,查了一些资料,目前来看最好的内存分配的算法还是jemalloc或者tcmalloc,两者在测试效率的时候不分伯仲,但是不知道在碎片率上有没有差别。 目前看过的动态管理内存的算法: 1 libc库中使用...
  • 内存泄露或内存碎片问题解决

    千次阅读 2014-07-04 16:50:22
    内存泄露  内存泄露通常sh
  • android内存碎片问题优化梳理

    千次阅读 2021-04-20 10:19:44
    这里说的碎片是物理内存碎片,而且是外部碎片问题。先说下为什么要关注内存碎片,因为手机系统的内存碎片严重会对相机性能带来了如下不好的影响: 1: 首先是相机的内存分配性能会受影响,会变得耗时很多。 具体...
  • 内存碎片产生原因及解决办法

    万次阅读 2018-09-28 22:42:47
    内存碎片通常分为内部碎片和外部碎片: &amp;nbsp; 1. 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免; &amp;nbsp; 2. ...
  • nginx reload内存碎片问题 相关资料 jemalloc、pmap、redis、systemtap、内存紧缩 问题现象 cache nginx 开启ip 库功能 占用700M 内存,reload 后内存翻倍,无法释放 root 9186 0.2 7.2 2150680 1786272 nginx ...
  • Redis内存碎片

    千次阅读 2018-11-22 09:31:30
    文章目录Redis内存碎片内存碎片内存碎片率高的原因解决方法 Redis内存碎片率 redis4支持内存碎片清理功能使用 内存碎片率 mem_fragmentation_ratio = used_memory_rss / used_memory used_memory :Redis使用其...
  • 内存碎片通常分为内部碎片和外部碎片: 内部碎片是由于采用固定大小的内存分区,当一个进程不能完全使用分给它的固定内存区域时就产生了内部碎片,通常内部碎片难以完全避免; 外部碎片是由于某些未分配的连续内存...
  • 内存碎片

    万次阅读 2012-02-23 09:48:25
    内存碎片的产生:  内存分配有静态分配和动态分配两种... 因此动态分配将不可避免会产生内存碎片问题,那么什么是内存碎片内存碎片即“碎片的内存”描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使
  • 内存泄露 碎片问题

    2016-03-03 17:51:31
    内存泄露 碎片
  • 内存碎片/内存空洞

    千次阅读 2017-06-08 15:25:41
    内存碎片/内存空洞内存碎片: 程序长时间运行后,由于不停的malloc/free操作,尽管不存在内存泄露,但程序所占用的内存空间越来越大,有时候还会导致malloc申请失败,这就是由于内存碎片所导致。产生原因: 非...
  • c++内存泄漏和内存碎片问题

    千次阅读 2017-12-23 20:01:08
    1.内存泄漏的定义    一般我们常说的内存泄漏是指堆内存的泄漏。堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显示释放的内存。应用程序一般使用malloc,realloc...
  • 使用此种方法是否会造成内存碎片及内存耗尽的情况? struct LNODE { u16 buflen; //包长度 u8 ref; //包标志,为1说明该包需要发送 struct LNODE *next; //下包地址 u8 *payload; //该包未发送数据指针 ...
  • c++内存碎片

    2018-01-19 20:19:46
    内存碎片的产生:  内存分配有静态分配和动态分配两种 ... 因此动态分配将不可避免会产生内存碎片问题,那么什么是内存碎片内存碎片即“碎片的内存”描述一个系统中所有不可用的空闲内存,这些碎片之所以不能被使
  • 我们知道,CMSGC在老生代回收时产生的内存碎片会导致老生代的利用率变低;或者可能在老生代总内存大小足够的情况下,却不能容纳新生代的晋升行为(由于没有连续的内存空间可用),导致触发FullGC。针对这个问题,Sun...
  • 如何分配内存 内存碎片处理技术

    千次阅读 2013-08-06 22:43:31
    内存碎片是一个很棘手的问题。如何分配内存决定着内存碎片是否会、何时会、如何会成为一个问题。  即使在系统中事实上仍然有许多空闲内存时,内存碎片还会最终导致出现内存用完的情况。一个不断产生内存碎片的系统...
  • 操作系统里的内存碎片解决办法

    千次阅读 2020-02-06 22:18:56
    内存碎片分为:内部碎片和外部碎片。 内部碎片就是已经被分配出去(能明确指出属于哪个进程)却不能被利用的内存空间; 内部碎片是处于区域内部或页面内部的存储块。占有这些区域或页面的进程并不使用这个存储块。而...
  • 内存碎片解决办法[转]

    千次阅读 2009-03-05 13:16:00
    内存碎片是一个很棘手的问题。如何分配内存决定着内存碎片是否会、何时会、如何会成为一个问题。 即使在系统中事实上仍然有许多空闲内存时,内存碎片还会最终导致出现内存用完的情况。一个不断产生内存碎片的系统,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 83,709
精华内容 33,483
关键字:

如何解决内存碎片的问题