精华内容
下载资源
问答
  • IBM机房管理机制,IBM机房管理机制IBM机房管理机制IBM机房管理机制IBM机房管理机制IBM机房管理机制IBM机房管理机制
  • C#内存管理机制 C#内存管理机制 C#内存管理机制
  • Android内存管理机制详解

    万次阅读 多人点赞 2012-12-13 10:37:33
    这是Linux内存管理的一个优秀特性,在这方面,区别于 Windows的内存管理。主要特点是,无论物理内存有多大,Linux都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的...

    本文主要介绍Android内存相关,最新已整理的Google官方文档《Android内存管理机制官方详解文档》,请各位参阅。

    与windows内存区别

            在Linux中经常发现空闲内存很少,似乎所有的内存都被系统占用了,表面感觉是内存不够用了,其实不然。这是Linux内存管理的一个优秀特性,在这方面,区别于 Windows的内存管理。主要特点是,无论物理内存有多大,Linux都将其充份利用,将一些程序调用过的硬盘数据读入内存,利用内存读写的高速特性来提高Linux系统的数据访问性能。而Windows是只在需要内存时,才为应用程序分配内存,并不能充分利用大容量的内存空间。换句话说,每增加一些物理内存,Linux都将能充分利用起来,发挥了硬件投资带来的好处,而Windows只将其做为摆设,即使增加8GB甚至更大。

    android内存的意义

            其实我们在用安卓手机的时候不用太在意剩余内存,Android上的应用是java,当然需要虚拟机,而android上的应用是带有独立虚拟机的,也就是每开一个应用就会打开一个独立的虚拟机。其实和java的垃圾回收机制类似,系统有一个规则来回收内存。进行内存调度有个阀值,只有低于这个值系统才会按一个列表来关闭用户不需要的东西。当然这个值默认设置得很小,所以你会看到内存老在很少的数值徘徊。但事实上他并不影响速度。相反加快了下次启动应用的速度。这本来就是 android标榜的优势之一,如果人为去关闭进程,没有太大必要。特别是使用自动关进程的软件。为什么内存少的时候运行大型程序会慢呢,原因是:在内存剩余不多时打开大型程序时会触发系统自身的调进程调度策略,这是十分消耗系统资源的操作,特别是在一个程序频繁向系统申请内存的时候。这种情况下系统并不会关闭所有打开的进程,而是选择性关闭,频繁的调度自然会拖慢系统。

     

    进程管理软件

            进程管理软件有无必要呢?有的。就是在运行大型程序之前,你可以手动关闭一些进程释放内存,可以显著的提高运行速度。但一些小程序完全可交由系统自己管理。那么如果不关程序是不是会更耗电。android的应用在被切换到后台时,它其实已经被暂停了,并不会消耗cpu资源只保留了运行状态。所以为什么有的程序切出去重进会到主界面。但是一个程序如果想要在后台处理些东西,如音乐播放,它就会开启一个服务。服务可在后台持续运行,所以在后台耗电的也只有带服务的应用了。我们可以把带服务的进程用进程管理软件关闭就可以了。没有带服务的应用在后台是完全不耗电的没有必要关闭。这种设计本来就是一个非常好的设计,下次启动程序时会更快,因为不需要读取界面资源,何必要关掉他们抹杀这个android的优点呢。

    Android进程种类

    1.       前台进程(foreground)

            目前正在屏幕上显示的进程和一些系统进程。举例来说,Dialer,Storage,Google Search等系统进程就是前台进程;再举例来说,当你运行一个程序,如浏览器,当浏览器界面在前台显示时,浏览器属于前台进程(foreground),但一旦你按home回到主界面,浏览器就变成了后台程序(background)。我们最不希望终止的进程就是前台进程。

    2.       可见进程(visible)

            可见进程是一些不再前台,但用户依然可见的进程,举个例来说:widget、输入法等,都属于visible。这部分进程虽然不在前台,但与我们的使用也密切相关,我们也不希望它们被终止(你肯定不希望时钟、天气,新闻等widget被终止,那它们将无法同步,你也不希望输入法被终止,否则你每次输入时都需要重新启动输入法)

    3.       桌面进程(home app)

            即launcher,保证在多任务切换之后,可以快速返回到home界面而不需重新加载launcher

    4.       次要服务(secondary server)

            目前正在运行的一些服务(主要服务,如拨号等,是不可能被进程管理终止的,故这里只谈次要服务),举例来说:谷歌企业套件,Gmail内部存储,联系人内部存储等。这部分服务虽然属于次要服务,但很一些系统功能依然息息相关,我们时常需要用到它们,所以也太希望他们被终止

    5.       后台进程(hidden)

            即是后台进程(background),就是我们通常意义上理解的启动后被切换到后台的进程,如浏览器,阅读器等。当程序显示在屏幕上时,他所运行的进程即为前台进程(foreground),一旦我们按home返回主界面(注意是按home,不是按back),程序就驻留在后台,成为后台进程(background)。后台进程的管理策略有多种:有较为积极的方式,一旦程序到达后台立即终止,这种方式会提高程序的运行速度,但无法加速程序的再次启动;也有较消极的方式,尽可能多的保留后台程序,虽然可能会影响到单个程序的运行速度,但在再次启动已启动的程序时,速度会有所提升。这里就需要用户根据自己的使用习惯找到一个平衡点

    6.       内容供应节点(content provider)

            没有程序实体,进提供内容供别的程序去用的,比如日历供应节点,邮件供应节点等。在终止进程时,这类程序应该有较高的优先权

    7.       空进程(empty)

            没有任何东西在内运行的进程,有些程序,比如BTE,在程序退出后,依然会在进程中驻留一个空进程,这个进程里没有任何数据在运行,作用往往是提高该程序下次的启动速度或者记录程序的一些历史信息。这部分进程无疑是应该最先终止的。

    幽灵刽子手LMK (Low Memory Killer)

     

    执行条件

            剩余内存小于应用定义的APP_MEM值,开始查看adj值列表,kill相应程序。

    实现机制

    Low Memory Killer的源代码在kernel/drivers/staging/android/lowmemorykiller.c中

    module_init(lowmem_init);
    
    module_exit(lowmem_exit);

        模块加载和退出的函数,主要的功能就是register_shrinker和unregister_shrinker结构体lowmem_shrinker。主要是将函数lowmem_shrink注册到shrinker链表里,在mm_scan调用。

    下面详细的介绍这个函数:

    for (i = 0; i < array_size; i++) {
            if (other_file < lowmem_minfree[i]) {
                min_adj = lowmem_adj[i];
                break;
            }
        }

    other_file, 系统的空闲内存数,根据上面的逻辑判断出,low memory killer需要对adj高于多少(min_adj)的进程进行分析是否释放。

     if (nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) {
            lowmem_print(5, "lowmem_shrink %d, %x, return %d\n",
                     nr_to_scan, gfp_mask, rem);
            return rem;
        }

      判断,系统当前的状态是否需要进行low memory killer。

    for_each_process(p) {
            struct mm_struct *mm;
            struct signal_struct *sig;
            int oom_adj;
            task_lock(p);
            mm = p->mm;
            sig = p->signal;
            if (!mm || !sig) {
                task_unlock(p);
                continue;
            }
            oom_adj = sig->oom_adj;
            if (oom_adj < min_adj) {
                task_unlock(p);
                continue;
            }
            tasksize = get_mm_rss(mm);
            task_unlock(p);
            if (tasksize <= 0)
                continue;
            if (selected) {
                if (oom_adj < selected_oom_adj)
                    continue;
                if (oom_adj == selected_oom_adj &&
                    tasksize <= selected_tasksize)
                    continue;
            }
            selected = p;
            selected_tasksize = tasksize;
            selected_oom_adj = oom_adj;
            lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
                     p->pid, p->comm, oom_adj, tasksize);
        }

    对每个sig->oom_adj大于min_adj的进程,找到占用内存最大的进程存放在selected中。

    if (selected) {
            if (fatal_signal_pending(selected)) {
                pr_warning("process %d is suffering a slow death\n",
                       selected->pid);
                read_unlock(&tasklist_lock);
                return rem;
            }
            lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
                     selected->pid, selected->comm,
                     selected_oom_adj, selected_tasksize);
            force_sig(SIGKILL, selected);
            rem -= selected_tasksize;
        }

    发送SIGKILL信息,杀掉该进程。

            在了解了其机制和原理之后,我们发现它的实现非常简单,与标准的Linux OOM机制类似,只是实现方式稍有不同。标准Linux的OOM Killer机制在mm/oom_kill.c中实现,且会被__alloc_pages_may_oom调用(在分配内存时,即mm/page_alloc.c中)。oom_kill.c最主要的一个函数是out_of_memory,它选择一个bad进程Kill,Kill的方法同样是通过发送SIGKILL信号。在out_of_memory中通过调用select_bad_process来选择一个进程Kill,选择的依据在badness函数中实现,基于多个标准来给每个进程评分,评分最高的被选中并Kill。一般而言,占用内存越多,oom_adj就越大,也就越有可能被选中。

    资源配置

    阈值表可以通过/sys/module/lowmemorykiller/parameters/adj和/sys/module/lowmemorykiller/parameters/minfree进行配置,例如在init.rc中:

    # Write value must be consistent with the above properties.
    
       write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15
       write /proc/sys/vm/overcommit_memory 1
       write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144
    
       class_start default

    进程oom_adj同样可以进行设置,通过write /proc/<PID>/oom_adj ,在init.rc中,init进程的pid为1,omm_adj被配置为-16,永远不会被杀死。

     # Set init its forked children's oom_adj.
    
       write /proc/1/oom_adj -16

         Low memory killer的基本原理我们应该弄清了,正如我前面所说的,进程omm_adj的大小跟进程的类型以及进程被调度的次序有关。进程的类型,可以在ActivityManagerService中清楚的看到:

        static final int EMPTY_APP_ADJ;
        static final int HIDDEN_APP_MAX_ADJ;
        static final int HIDDEN_APP_MIN_ADJ;
        static final int HOME_APP_ADJ;
        static final int BACKUP_APP_ADJ;
        static final int SECONDARY_SERVER_ADJ;
        static final int HEAVY_WEIGHT_APP_ADJ;
        static final int PERCEPTIBLE_APP_ADJ;
        static final int VISIBLE_APP_ADJ;
        static final int FOREGROUND_APP_ADJ;
        static final int CORE_SERVER_ADJ = -12;
        static final int SYSTEM_ADJ = -16;

      ActivityManagerService定义各种进程的oom_adj,CORE_SERVER_ADJ代表一些核心的服务的omm_adj,数值为-12,由前面的分析可知道,这类进程永远也不会被杀死。

    在init.rc中: 

    # Define the oom_adj values for the classes of processes that can be
    # killed by the kernel.  These are used in ActivityManagerService.
        setprop ro.FOREGROUND_APP_ADJ 0
        setprop ro.VISIBLE_APP_ADJ 1
        setprop ro.HOME_APP_ADJ 1
        setprop ro.PERCEPTIBLE_APP_ADJ 2
        setprop ro.HEAVY_WEIGHT_APP_ADJ 3
        setprop ro.SECONDARY_SERVER_ADJ 4
        setprop ro.BACKUP_APP_ADJ 5
        setprop ro.HIDDEN_APP_MIN_ADJ 7
        setprop ro.EMPTY_APP_ADJ 15
    
    # Define the memory thresholds at which the above process classes will
    # be killed.  These numbers are in pages (4k).
        setprop ro.FOREGROUND_APP_MEM 2048
        setprop ro.VISIBLE_APP_MEM 3072
        setprop ro.HOME_APP_MEM 3072
        setprop ro.PERCEPTIBLE_APP_MEM 4096
        setprop ro.HEAVY_WEIGHT_APP_MEM 4096
        setprop ro.SECONDARY_SERVER_MEM 10240
        setprop ro.BACKUP_APP_MEM 10240
        setprop ro.HIDDEN_APP_MEM 10240
        setprop ro.EMPTY_APP_MEM 14336
    
    # Write value must be consistent with the above properties.
    # Note that the driver only supports 6 slots, so we have combined some of
    # the classes into the same memory level; the associated processes of higher
    # classes will still be killed first.
        write /sys/module/lowmemorykiller/parameters/adj 0,1,2,4,7,15
    
        write /proc/sys/vm/overcommit_memory 1
        write /proc/sys/vm/min_free_order_shift 4
      write /sys/module/lowmemorykiller/parameters/minfree 2048,3072,4096,10240,10240,14336
    
        # Set init its forked children's oom_adj.
        write /proc/1/oom_adj -16

    ActivityManagerService.java

    打开程序或者有程序进入后台时都会执行updateOomAdjLocked()函数:

      

        以上就是android内存管理机制的内容了,在一些设备内存比较低的情况下,我们可以对其内存进行优化,从而让我们的设备运行的更加流畅。

    展开全文
  • Android 内存管理机制

    千次阅读 2018-09-03 14:41:45
    Linux的内存管理机制:Android毕竟是基于Linux内核实现的操作系统,因此有必要了解一下Linux的内存管理机制。 Android的内存管理相关知识:Android又不同于Linux,它是一个移动操作系统,因此其内存管理上也有...

    本文主要包括三大部分内容:

    内存管理基础:从整个计算机领域简述主要的内存管理技术。
    Linux的内存管理机制:Android毕竟是基于Linux内核实现的操作系统,因此有必要了解一下Linux的内存管理机制。
    Android的内存管理相关知识:Android又不同于Linux,它是一个移动操作系统,因此其内存管理上也有自己的特性,这一部分详细讲述Android的内存管理相关知识,包括 内存管理机制进程管理

    内存管理基础

    概述

    CPU只能访问其寄存器(Register)和内存(Memory), 无法直接访问硬盘(Disk)。 存储在硬盘上的数据必须首先传输到内存中才能被CPU访问。从访问速度来看,对寄存器的访问非常快,通常为1纳秒; 对内存的访问相对较慢,通常为100纳秒(使用缓存加速的情况下);而对硬盘驱动器的访问速度最慢,通常为10毫秒。

    寄存器(Register):CPU内部的高速存储区域

    当一个程序加载到内存中时,它由四个内存区域组成:

    • 堆栈(Stack):存储由该程序的每个函数创建的临时变量
    • 堆(Heap):该区域特别适用于动态内存分配
    • 数据(Data):存储该程序的全局变量和静态变量
    • 代码(Code):存储该程序的指令

    主要的内存管理技术

    • Base and limit registers(基址寄存器和界限寄存器)
    • Virtual memory(虚拟内存)
    • Swapping(交换)
    • Segmentation(分段)
    • Paging(分页)
    Base and limit registers(基址寄存器和界限寄存器)

    必须限制进程,以便它们只能访问属于该特定进程的内存位置。

    每个进程都有一个基址寄存器和限制寄存器:

    • 基址寄存器保存最小的有效存储器地址
    • 限制寄存器指定范围的大小

    例如,process 2的有效内存地址是300040到420940

    那么每个来自用户进程的内存访问都将首先针对这两个寄存器进行一次检查:

    操作系统内核可以访问所有内存位置,因为它需要管理整个内存。

    Virtual memory(虚拟内存)

    虚拟内存(VM)是OS为内存管理提供的基本抽象。

    • 所有程序都使用虚拟内存地址
    • 虚拟地址会被转换为物理地址
    • 物理地址表示数据的实际物理位置
    • 物理位置可以是内存或磁盘

    虚拟地址到物理地址的转换由存储器管理单元(MMU - Memory Management Unit)处理。MMU使用重定位寄存器(relocation register),其值在硬件级别上被添加到每个内存请求中。

    Swapping(交换)

    交换是一种可以暂时将进程从内存交换到后备存储,而之后又可以将其返回内存以继续执行的技术。

    后备存储通常是一个硬盘驱动器,其访问速度快,且大小足以存储内存映像的副本。

    如果没有足够的可用内存来同时保留内存中的所有正在运行的进程,则某些当前未使用CPU的进程可能会被交换到后备存储中。

    交换是一个非常缓慢的过程。 主要耗时部分是数据传输。例如,如果进程占用10MB内存并且后备存储的传输速率为40MB/秒,则需要0.25秒来进行数据传输。 再加上将数据交换回内存的时间,总传输时间可能是半秒,这是一个巨大的延迟,因此,有些操作系统已经不再使用交换了。

    Segmentation(分段)

    分段是一种将内存分解为逻辑片段的技术,其中每个片段代表一组相关信息。 例如,将每个进程按照堆栈,堆,数据以及代码分为不同的段,还有OS内核的数据段等。

    将内存分解成较小的段会增加寻找空闲内存的机会。

    每个段都有一对寄存器:

    • 基址寄存器:包含段驻留在内存中的起始物理地址
    • 限制寄存器:指定段的长度

    **段表(Segment table)**存储每个段的基址和限制寄存器信息。

    使用分段时,虚拟内存地址是一对:<段号,偏移量>

    • 段号(Segment Number):用作段表的索引以查找特定条目
    • 偏移量(Offset):首先与限制寄存器进行比较,然后与基址结合以计算物理内存地址

    Paging(分页)

    有时可用内存被分成许多小块,其中没有一块足够大以满足下一个内存需求,然而他们的总和却可以。这个问题被称为碎片(Fragmentation),许多内存分配策略都会受其影响。

    分页是一种内存管理技术,它允许进程的物理内存不连续。它通过在称为页面(Page)的相同大小的块中分配内存来消除碎片问题,是目前比较优秀的内存管理技术。

    分页将物理内存划分为多个大小相等的块,称为帧(Frame)。并将进程的逻辑内存空间也划分为大小相等的块,称为页面(Page)

    任何进程中的任何页面都可以放入任何可用的帧中。

    **页表(Page Table)**用于查找此刻存储特定页面的帧。

    使用分页时,虚拟内存地址是一对:<页码,偏移量>

    • 页码(Page Number):用作页表的索引,以查找此页面的条目
    • 偏移量(Offset):与基址相结合,以定义物理内存地址

    举一个分页地址转换的例子:

    虚拟内存地址为0x13325328,页表项0x13325包含的值是0x03004,那么物理地址是什么?

    答案:
    物理地址是0x03004328
    页码为0x13325,偏移量为0x328
    相应的帧号是0x03004

    Linux的内存管理机制

    在Linux系统下,监控内存常用的命令是free、top等,下面是一个free命令的执行结果:

    要了解Linux的内存管理,首先要明白上例中各个名词的意义:

    • total:物理内存的总大小。
    • used:已经使用的物理内存多小。
    • free:空闲的物理内存值。
    • shared:多个进程共享的内存值。
    • buffers / cached:用于磁盘缓存的大小(这部分是从物理内存中划出来的)。
    • 第二行Mem:代表物理内存使用情况。
    • 第三行(-/+ buffers/cached):代表磁盘缓存使用状态。
    • 第四行:Swap表示交换空间内存使用状态(这部分实际上是从磁盘上虚拟出来的逻辑内存)。

    free命令输出的内存状态,可以从两个角度来看:内核角度、应用层角度。

    1.从内核角度来查看内存的状态:

    就是内核目前可以直接分配到,不需要额外的操作,即free命令第二行 Mem 的输出。从上例中可见,41940 + 16360492 = 16402432,也就是说Mem行的 free + used = total,注意,这里的free并不包括buffers和cached。

    2.从应用层角度来查看内存的状态:

    也就是Linux上运行的程序可以使用的内存大小,即free命令第三行 -/+ buffers/cache 的输出。再来做一个计算41940+(465404+12714880)=13222224,即Mem行的free + buffers + cached = -/+ buffers/cache行的free,也就是说应用可用的物理内存值是Mem行的free、buffers和cached三者之和,可见-/+ buffers/cache行的free是包括buffers和cached的。

    对于应用程序来说,buffers/cached占有的内存是可用的,因为buffers/cached是为了提高文件读取的性能,当应用程序需要用到内存的时候,buffers/cached会很快地被回收,以供应用程序使用。

    物理内存和虚拟内存

    物理内存就是系统硬件提供的内存大小,是真正的内存。在linux下还有一个虚拟内存的概念,虚拟内存就是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为 交换空间(Swap Space)

    linux的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。而进行这种交换所遵循的依据是“LRU”算法(Least Recently Used,最近最少使用算法)。

    Buffers和Cached有什么用

    在任何系统中,文件的读写都是一个耗时的操作,当应用程序需要读写文件中的数据时,操作系统先分配一些内存,将数据从磁盘读入到这些内存中,然后应用程序读写这部分内存数据,之后系统再将数据从内存写到磁盘上。如果是大量文件读写甚至重复读写,系统读写性能就变得非常低下,在这种情况下,Linux引入了缓存机制。

    buffers与cached都是从物理内存中分离出来的,主要用于实现磁盘缓存,用来保存系统曾经打开过的文件以及文件属性信息,这样当操作系统需要读取某些文件时,会首先在buffers与cached内存区查找,如果找到,直接读出传送给应用程序,否则,才从磁盘读取,通过这种缓存机制,大大降低了对磁盘的IO操作,提高了操作系统的数据访问性能。而这种磁盘高速缓存则是基于两个事实:第一,内存访问速度远远高于磁盘访问速度;第二,数据一旦被访问,就很有可能短期内再次被访问。

    另外,buffers与cached缓存的内容也是不同的。buffers是用来缓冲块设备做的,它只记录文件系统的元数据(metadata)以及 tracking in-flight pages,而cached是用来给文件做缓冲。更通俗一点说:buffers主要用来存放目录里面有什么内容,文件的属性以及权限等等。而cached直接用来记忆我们打开过的文件和程序

    为了验证我们的结论是否正确,可以通过vi打开一个非常大的文件,看看cached的变化,然后再次vi这个文件,感觉一下是不是第二次打开的速度明显快于第一次?

    接着执行下面的命令:

    find /* -name  *.conf
    

    看看buffers的值是否变化,然后重复执行find命令,看看两次显示速度有何不同。

    Linux内存管理的哲学

    Free memory is wasted memory.

    Linux的哲学是尽可能多的使用内存,减少磁盘IO,因为内存的速度比磁盘快得多。Linux总是在力求缓存更多的数据和信息,内存不够时,将一些不经常使用的数据转移到交换分区(Swap Space)中以释放更多可用物理内存,当然,如果交换分区的数据再次被读写时,又会被转移到物理内存中,这种设计思路提高了系统的整体性能。而Windows的处理方式是,内存和虚拟内存一起使用,不是以内存操作为主,结果就是IO的负担比较大,可能拖慢处理速度。

    Linux和Windows在内存管理机制上的区别

    在Linux系统使用过程中,你会发现,无论你的电脑内存配置多么优越,仍然不时的发生可用内存吃紧的现象,感觉内存不够用了,其实不然。这是Linux内存管理的优秀特性,无论物理内存有多大,Linux都将其充分利用,将一些程序调用过的硬盘数据缓存到内存,利用内存读写的高速性提高系统的数据访问性能。而Window只在需要内存时,才为应用分配内存,不能充分利用大容量的内存空间。换句话说,每增加一些内存,Linux都能将其利用起来,充分发挥硬件投资带来的好处,而Windows只将其作为摆设。

    所以说,一般我们不需要太关注Linux的内存占用情况,而如果Swap占用率一直居高不下的话,就很有可能真的是需要扩展内存了

    Android的内存管理机制

    Android使用虚拟内存和分页,不支持交换

    垃圾收集

    无论是ART还是Dalvik虚拟机,都和众多Java虚拟机一样,属于一种托管内存环境(程序员不需要显示的管理内存的分配与回收,交由系统自动管理)。托管内存环境会跟踪每个内存分配, 一旦确定程序不再使用一块内存,它就会将其释放回堆中,而无需程序员的任何干预。 回收托管内存环境中未使用内存的机制称为垃圾回收

    垃圾收集有两个目标:

    • 在程序中查找将来无法访问的数据对象;
    • 回收这些对象使用的资源。

    Android的垃圾收集器不带压缩整理功能(Compact),即不会对Heap做碎片整理。

    Android的内存堆是分代式(Generational)的,意味着它会将所有分配的对象进行分代,然后分代跟踪这些对象。 例如,最近分配的对象属于年轻代(Young Generation)。 当一个对象长时间保持活动状态时,它可以被提升为年老代(Older Generation),之后还能进一步提升为永久代(Permanent Generation)

    每一代的对象可占用的内存总量都有其专用上限。 每当一代开始填满时,系统就会执行垃圾收集事件以试图释放内存。 垃圾收集的持续时间取决于它在收集哪一代的对象以及每一代中有多少活动对象

    虽然垃圾收集速度非常快,但它仍然会影响应用程序的性能。通常情况下你不需要控制代码中何时执行垃圾收集事件。 系统有一组用于确定何时执行垃圾收集的标准。 满足条件后,系统将停止执行当前进程并开始垃圾回收。 如果在像动画或音乐播放这样的密集处理循环中发生垃圾收集,则会增加处理时间。 这种增加可能会导致你的应用程序中的代码执行超过建议的16ms阈值。

    为实现高效,流畅的帧渲染,Android建议绘制一帧的时间不要超过16ms。

    此外,你的代码可能会执行各种工作,这些工作会导致垃圾收集事件更频繁地发生,或使其持续时间超过正常范围。 例如,如果在Alpha混合动画的每个帧期间在for循环的最内部分配多个对象,则大量的对象就会污染内存堆。 此时,垃圾收集器会执行多个垃圾收集事件,并可能降低应用程序的性能。

    共享内存

    Android可以跨进程共享RAM页面(Pages)。 它可以通过以下方式实现:

    • 每个应用程序进程都是从名为Zygote的现有进程分叉(fork)出来的。 Zygote进程在系统引导并加载framework代码和资源(例如Activity Themes)时启动。 要启动新的应用程序进程,系统会fork Zygote进程,然后在新进程中加载并运行应用程序的代码。 这种方法允许在所有应用程序进程中共享大多数的为framework代码和资源分配的RAM页面

    • 大多数静态数据都被映射到一个进程中。 该技术允许在进程之间共享数据,并且还允许在需要时将其Page out。这些静态数据包括:Dalvik代码(通过将其置于预链接的.odex文件中进行直接的memory-mapping),app资源(通过将资源表设计为可以mmap的结构并通过对齐APK的zip条目) 和传统的项目元素,如.so文件中的本地代码。
    • 在许多地方,Android使用显式分配的共享内存区域(使用ashmem或gralloc)在进程间共享相同的动态RAM。 例如,Window surface在应用程序和屏幕合成器之间使用共享内存,而游标缓冲区在Content Provider和客户端之间使用共享内存。

    分配和回收应用的内存

    Android为每个进程分配内存的时候,采用了弹性分配方式,也就是刚开始并不会一下分配很多内存给每个进程,而是给每一个进程分配一个“够用”的虚拟内存范围。这个范围是根据每一个设备实际的物理内存大小来决定的,并且可以随着应用后续需求而增加,但最多也只能达到系统为每个应用定义的上限。

    堆的逻辑大小与其使用的物理内存总量并不完全相同。 在检查应用程序的堆时,Android会计算一个名为“比例集大小”(PSS)的值,该值会考虑与其他进程共享的脏页面和干净页面,但其总量与共享该RAM的应用程序数量成正比。 此PSS总量就是系统认为是你的物理内存占用量。

    Android会在内存中尽量长时间的保持应用进程,即使有些进程不再使用了。这样,当用户下次启动应用的时候,只需要恢复当前进程就可以了,不需要重新创建进程,进而减少应用的启动时间。只有当Android系统发现内存不足,而其他为用户提供更紧急服务的进程又需要内存时,Android就会决定关闭某些进程以回收内存。关于这部分内容,稍后再细说。

    限制应用的内存

    为了维护高效的多任务环境,Android为每个应用程序设置了堆大小的硬性限制。 该限制因设备而异,取决于设备总体可用的RAM。 如果应用程序已达到该限制并尝试分配更多内存,则会收到 OutOfMemoryError

    在某些情况下,你可能希望查询系统以准确确定当前设备上可用的堆空间大小,例如,确定可以安全地保留在缓存中的数据量。 你可以通过调用 getMemoryClass() 来查询系统中的这个数字。 此方法返回一个整数,指示应用程序堆可用的兆字节数。

    切换应用

    当用户在应用程序之间切换时,Android会将非前台应用程序(即用户不可见或并没有运行诸如音乐播放等前台服务的进程)缓存到一个最近最少使用缓存(LRU Cache)中。例如,当用户首次启动应用程序时,会为其创建一个进程; 但是当用户离开应用程序时,该进程不会退出。 系统会缓存该进程。 如果用户稍后返回应用程序,系统将重新使用该进程,从而使应用程序切换更快。

    如果你的应用程序具有缓存进程并且它保留了当前不需要的内存,那么即使用户未使用它,你的应用程序也会影响系统的整体性能。 当系统内存不足时,就会从最近最少使用的进程开始,终止LRU Cache中的进程。另外,系统还会综合考虑保留了最多内存的进程,并可能终止它们以释放RAM。

    当系统开始终止LRU Cache中的进程时,它主要是自下而上的。 系统还会考虑哪些进程占用更多内存,因为在它被杀时会为系统提供更多内存增益。 因此在整个LRU列表中消耗的内存越少,保留在列表中并且能够快速恢复的机会就越大。

    Android对Linux系统的内存管理机制进行的优化

    Android对内存的使用方式同样是“尽最大限度的使用”,这一点继承了Linux的优点。只不过有所不同的是,Linux侧重于尽可能多的缓存磁盘数据以降低磁盘IO进而提高系统的数据访问性能,而Android侧重于尽可能多的缓存进程以提高应用启动和切换速度。Linux系统在进程活动停止后就结束该进程,而Android系统则会在内存中尽量长时间的保持应用进程,直到系统需要更多内存为止。这些保留在内存中的进程,通常情况下不会影响系统整体运行速度,反而会在用户再次激活这些进程时,加快进程的启动速度,因为不用重新加载界面资源了,这是Android标榜的特性之一。所以,Android现在不推荐显式的“退出”应用

    那为什么内存少的时候运行大型程序会慢呢,原因是:在内存剩余不多时打开大型程序会触发系统自身的进程调度策略,这是十分消耗系统资源的操作,特别是在一个程序频繁向系统申请内存的时候。这种情况下系统并不会关闭所有打开的进程,而是选择性关闭,频繁的调度自然会拖慢系统。

    Android中的进程管理

    说到Android的内存管理,就不得不提到进程管理,因为进程管理确确切切的影响着系统内存。在了解进程管理之前,我们首先了解一些基础概念。

    当某个应用组件启动且该应用没有运行其他任何组件时,Android 系统会使用单个执行线程为应用启动新的 Linux 进程。默认情况下,同一应用的所有组件在相同的进程和线程(称为“主”线程)中运行。 如果某个应用组件启动且该应用已存在进程(因为存在该应用的其他组件),则该组件会在此进程内启动并使用相同的执行线程。 但是,你也可以安排应用中的其他组件在单独的进程中运行,并为任何进程创建额外的线程。

    Android应用模型的设计思想取自Web 2.0的Mashup概念,是基于组件的应用设计模式。在该模型下,每个应用都由一系列的组件搭建而成,组件通过应用的配置文件描述功能。Android系统依照组件的配置信息,了解各个组件的功能并进行统一调度。这就意味着,来自不同应用的组件可以有机地结合在一起,共同完成任务,各个Android应用,只有明确的组件边界,而不再有明确的进程边界和应用边界。这种设计,也令得开发者无需耗费精力去重新开发一些附属功能,而是可以全身心地投入到核心功能的开发中。这样不但提高了应用开发的效率,也增强了用户体验(比如电子邮件中选择图片作为附件的功能,可以直接调用专门的图片应用的功能,不用自己从头开发)。

    系统不会为每个组件实例创建单独的线程。运行于同一进程的所有组件均在 UI 线程中实例化,并且对每个组件的系统调用均由该线程进行分派。 因此,响应系统回调的方法(例如,报告用户操作的 onKeyDown() 或生命周期回调方法)始终在进程的 UI 线程中运行(四大组件的各个生命周期回调方法都是在UI线程中触发的)。

    进程的生命周期

    Android的一个不寻常的基本特征是应用程序进程的生命周期并非是由应用本身直接控制的。相反,进程的生命周期是由系统决定的,系统会权衡每个进程对用户的相对重要程度,以及系统的可用内存总量来确定。比如说相对于终止一个托管了正在与用户交互的Activity的进程,系统更可能终止一个托管了屏幕上不再可见的Activity的进程,否则这种后果是可怕的。因此,是否终止某个进程取决于该进程中所运行组件的状态。Android会有限清理那些已经不再使用的进程,以保证最小的副作用。

    作为应用开发者,了解各个应用组件(特别是Activity、Service和BroadcastReceiver)如何影响应用进程的生命周期非常重要。不正确的使用这些组件,有可能导致系统在应用执行重要工作时终止进程。

    举个常见的例子, BroadcastReceiver 在其 onReceive() 方法中接收到Intent时启动一个线程,然后从该函数返回。而一旦返回,系统就认为该 BroadcastReceiver 不再处于活动状态,因此也就不再需要其托管进程(除非该进程中还有其他组件处于活动状态)。这样一来,系统就有可能随时终止进程以回收内存,而这也最终会导致运行在进程中的线程被终止。此问题的解决方案通常是从 BroadcastReceiver 中安排一个 JobService ,以便系统知道在该进程中仍有活动的工作。

    为了确定在内存不足时终止哪些进程,Android会根据进程中正在运行的组件以及这些组件的状态,将每个进程放入“重要性层次结构”中。必要时,系统会首先杀死重要性最低的进程,以此类推,以回收系统资源。这就相当于为进程分配了优先级的概念。

    进程优先级

    Android中总共有5个进程优先级(按重要性降序):

    Foreground Process:前台进程(正常不会被杀死)

    用户当前操作所必需的进程。有很多组件能以不同的方式使得其所在进程被判定为前台进程。如果一个进程满足以下任一条件,即视为前台进程:

    • 托管用户正在交互的 Activity(已调用 Activity 的 onResume() 方法)
    • 托管某个 Service,后者绑定到用户正在交互的 Activity
    • 托管正执行一个生命周期回调的 Service(onCreate()、onStart() 或 onDestroy())
    • 托管正执行其 onReceive() 方法的 BroadcastReceiver

    通常,在任意给定时间前台进程都为数不多。只有在内存不足以支持它们同时继续运行这一万不得已的情况下,系统才会终止它们。 此时,设备往往已达到内存分页状态,因此需要终止一些前台进程来确保用户界面正常响应。

    Visible Process:可见进程(正常不会被杀死)

    没有任何前台组件、但仍会影响用户在屏幕上所见内容的进程。杀死这类进程也会明显影响用户体验。 如果一个进程满足以下任一条件,即视为可见进程:

    • 托管不在前台、但仍对用户可见的 Activity(已调用其 onPause() 方法)。例如,启动了一个对话框样式的前台 activity ,此时在其后面仍然可以看到前一个Activity。

      运行时权限对话框就属于此类。
      考虑一下,还有哪种情况会导致只触发onPause而不触发onStop?

    • 托管通过 Service.startForeground() 启动的前台Service。

      Service.startForeground():它要求系统将它视为用户可察觉到的服务,或者基本上对用户是可见的。

    • 托管系统用于某个用户可察觉的特定功能的Service,比如动态壁纸、输入法服务等等。

    可见进程被视为是极其重要的进程,除非为了维持所有前台进程同时运行而必须终止,否则系统不会终止这些进程。如果这类进程被杀死,从用户的角度看,这意味着当前 activity 背后的可见 activity 会被黑屏代替。

    Service Process:服务进程(正常不会被杀死)

    正在运行已使用 startService() 方法启动的服务且不属于上述两个更高类别进程的进程。尽管服务进程与用户所见内容没有直接关联,但是它们通常在执行一些用户关心的操作(例如,后台网络上传或下载数据)。因此,除非内存不足以维持所有前台进程和可见进程同时运行,否则系统会让服务进程保持运行状态。

    已经运行很久(例如30分钟或更久)的Service,有可能被降级,这样一来它们所在的进程就可以被放入Cached LRU列表中。这有助于避免一些长时间运行的Service由于内存泄漏或其他问题而消耗过多的RAM,进而导致系统无法有效使用缓存进程的情况。

    Background / Cached Process:后台进程(可能随时被杀死)

    这类进程一般会持有一个或多个目前对用户不可见的 Activity (已调用 Activity 的 onStop() 方法)。它们不是当前所必须的,因此当其他更高优先级的进程需要内存时,系统可能随时终止它们以回收内存。但如果正确实现了Activity的生命周期,即便系统终止了进程,当用户再次返回应用时也不会影响用户体验:关联Activity在新的进程中被重新创建时可以恢复之前保存的状态。

    在一个正常运行的系统中,缓存进程是内存管理中唯一涉及到的进程:一个运行良好的系统将始终具有多个缓存进程(为了更高效的切换应用),并根据需要定期终止最旧的进程。只有在非常严重(并且不可取)的情况下,系统才会到达这样一个点,此时所有的缓存进程都已被终止,并且必须开始终止服务进程。

    Android系统回收后台进程的参考条件
    LRU算法:自下而上开始终止,先回收最老的进程。越老的进程近期内被用户再次使用的几率越低。杀死的进程越老,对用户体验的影响就越小。
    回收收益:系统总是倾向于杀死一个能回收更多内存的进程,因为在它被杀时会为系统提供更多内存增益,从而可以杀死更少的进程。杀死的进程越少,对用户体验的影响就越小。换句话说,应用进程在整个LRU列表中消耗的内存越少,保留在列表中并且能够快速恢复的机会就越大。

    这类进程会被保存在一个伪LRU列表中,系统会优先杀死处于列表尾部(最老)的进程,以确保包含用户最近查看的 Activity 的进程最后一个被终止。这个LRU列表排序的确切策略是平台的实现细节,但通常情况下,相对于其他类型的进程,系统会优先尝试保留更有用的进程(比如托管用户主应用程序的进程,或者托管用户看到的最后一个Activity的进程,等等)。还有其他一些用于终止进程的策略:对允许的进程数量硬限制,对进程可以持续缓存的时间量的硬限制,等等。

    在一个健康的系统中,只有缓存进程或者空进程会被系统随时终止,如果服务进程,或者更高优先级的可见进程以及前台进程也开始被系统终止(不包括应用本身糟糕的内存使用导致OOM),那就说明系统运行已经处于一个亚健康甚至极不健康的状态,可用内存已经吃紧。

    Empty Process:空进程(可以随时杀死)

    不含任何活跃组件的进程。保留这种进程的的唯一目的是用作缓存(为了更加有效的使用内存而不是完全释放掉),以缩短下次启动应用程序所需的时间,因为启动一个新的进程也是需要代价的。只要有需要,Android会随时杀死这些进程。

    内存管理中对于前台/后台应用的定义,与用于Service限制目的的后台应用定义不同。从Android 8.0开始,出于节省系统资源、优化用户体验、提高电池续航能力的考量,系统进行了前台/后台应用的区分,对于后台service进行了一些限制。在该定义中,如果满足以下任意条件,应用将被视为处于前台:

    • 具有可见 Activity(不管该 Activity 已启动还是已暂停)。
    • 具有前台 Service。
    • 另一个前台应用已关联到该应用(不管是通过绑定到其中一个 Service,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的 Service,那么该应用处于前台:
      IME
      壁纸 Service
      通知侦听器
      语音或文本 Service
      如果以上条件均不满足,应用将被视为处于后台。详见后台Service限制

    Android系统如何评定进程的优先级

    根据进程中当前活动组件的重要程度,Android 会将进程评定为它可能达到的最高级别。例如,如果某进程同时托管着 Service 和可见 Activity,则会将此进程评定为可见进程,而不是服务进程。

    此外,一个进程的级别可能会因其他进程对它的依赖而有所提高,即服务于另一进程的进程其级别永远不会低于其所服务的进程。 例如,如果进程 A 中的内容提供程序为进程 B 中的客户端提供服务,或者如果进程 A 中的服务绑定到进程 B 中的组件,则进程 A 始终被视为至少与进程 B 同样重要。

    由于运行服务的进程其级别高于托管后台 Activity 的进程,因此,在 Activity 中启动一个长时间运行的操作时,最好为该操作启动服务,而不是简单地创建工作线程,当操作有可能比 Activity 更加持久时尤要如此。例如,一个文件上传的操作就可以考虑使用服务来完成,这样一来,即使用户退出 Activity,仍可在后台继续执行上传操作。使用服务可以保证,无论 Activity 发生什么情况,该操作至少具备“服务进程”优先级。 同理, BroadcastReceiver 也应使用服务,而不是简单地将耗时冗长的操作放入线程中。

    Home键退出和返回键退出的区别

    Home键退出,程序保留状态为后台进程;而返回键退出,程序保留状态为空进程,空进程更容易被系统回收。Home键其实主要用于进程间切换,返回键则是真正的退出程序。

    从理论上来讲,无论是哪种情况,在没有任何后台工作线程(即便应用处于后台,工作线程仍然可以执行)的前提下,被置于后台的进程都只是保留他们的运行状态,并不会占用CPU资源,所以也不耗电。只有音乐播放软件之类的应用需要在后台运行Service,而Service是需要占用CPU时间的,此时才会耗电。所以说没有带后台服务的应用是不耗电也不占用CPU时间的,没必要关闭,这种设计本身就是Android的优势之一,可以让应用下次启动时更快。然而现实是,很多应用多多少少都会有一些后台工作线程,这可能是开发人员经验不足导致(比如线程未关闭或者循环发送的Handler消息未停止),也可能是为了需求而有意为之,导致整个Android应用的生态环境并不是一片干净。

    作为用户,你需要手动管理内存吗?

    你有“内存使用率过高”恐慌症吗?

    无论是使用桌面操作系统还是移动操作系统,很多人都喜欢随时关注内存,一旦发现内存使用率过高就难受,忍不住的要杀进程以释放内存。这种习惯很大程度上都是源自Windows系统,当然这在Windows下也确实没错。然而很多人在使用Linux系统时仍然有这个习惯,甚至到了Android系统下,也改不掉(尤其是Android手机刚出现的几年),Clean Master等各种清理软件铺天盖地。毫不客气的说,Windows毒害了不少人!当然,这也不能怪Windows,毕竟Windows的普及率太高了,而大部分普通用户(甚至一些计算机相关人员)又不了解Windows和Linux在内存管理方面的差别。

    何时需要清理手机的RAM?

    考虑到许多手机厂商都内置了“清理”功能,那这个东西可能也有些道理。事实上,关闭应用程序以节省内存的做法,仅在少数情况下是值得尝试的 —— 当应用崩溃或无法正常运行时。比如以下情况:

    • 你的微信在启动时需要加载很久
    • 某个应用启动时闪退或者运行过程中闪退
    • 系统响应速度非常缓慢

    这些症状可能非常多样化,甚至原因不明的手机发热也可能是由于某个崩溃的应用造成的。

    管理你的手机RAM:结论

    究竟需不需要手动清空内存?答案是:No!

    清空内存意味着你需要不断重启应用,这需要花费时间和电量,甚至会缩短电池寿命。内存占用高其实并非是一件坏事,甚至是需要的。因为Android是基于Linux内核的操作系统,而Linux的内存哲学是:

    Free memory is wasted memory.

    你只需要在手机明显变慢时采取行动。一般来说,系统的自动RAM管理才是最快最高效的,也是Android标榜的优势之一。关闭应用可能释放一些内存,但却对高效使用内存毫无作用。

    Leave the memory management to Android, and it will leave the fun to you.

    参考资料

    浅谈Linux的内存管理机制
    Processes and Threads Overview
    Process and Application Lifecycle
    Overview of Memory Management
    RAM management on Android: why you shouldn’t clear memory

    展开全文
  • Android内存管理机制

    千次阅读 2017-11-26 02:27:10
    1、基于Linux内存管理 ... Android系统是基于Linux 2.6内核开发的开源操作系统,而linux系统的内存管理有其...不过Android系统对Linux的内存管理机制进行了优化,Linux系统会在进程活动停止后就结束该进程,而An

    转载地址:https://www.cnblogs.com/nathan909/p/5372981.html


    1、基于Linux内存管理

      Android系统是基于Linux 2.6内核开发的开源操作系统,而linux系统的内存管理有其独特的动态存储管理机制。不过Android系统对Linux的内存管理机制进行了优化,Linux系统会在进程活动停止后就结束该进程,而Android把这些进程都保留在内存中,直到系统需要更多内存为止。这些保留在内存中的进程通常情况下不会影响整体系统的运行速度,并且当用户再次激活这些进程时,提升了进程的启动速度。

    2、Android内存分配机制

      与java的垃圾回收机制类似,系统有一个规则来回收内存。进行内存调度有个阈值,只有低于这个值系统才会按一个列表来关闭用户不需要的东西。Android系统有六类进程:前台进程、可见进程、次要服务、后台进程、内容供应节点、空进程。有内存管理需求的人可以用MinFreeManager之类的软件进行进程管理,分别为六类进程设定不同的阈值来操纵系统的内存分配机制。不过对于一般用户而言,Android系统默认的分配机制已经可以满足使用需要,因此也不需要再去调整。

      对于一些内存很低的低端Android机而言,系统默认的内存分配机制无法实现很完善的内存调配。所以在运行大型游戏时需要先清理一下内存。然而对于我们的ANDROID系统的手机而言,几百m的总内存和几十m的空余内存已经可以充分的满足系统自动调配的需要,因此完全没有必要老去杀进程、清内存。

      有人认为后台挂着程序很费电,事实上Android的应用在被切换到后台时,它其实已经被暂停了,并不会消耗cpu资源,只保留了运行状态。至于QQ、音乐播放之类的程序可以在后台运行,是因为这些程序在后台开启了服务,而服务可以后台运行,所以没有带服务的应用在后台是完全不耗电的,没有必要关闭。这种设计本来就是一个非常好的设计,下次启动程序时,会更快,因为不需要读取界面资源。

      Android系统这样的设计不仅非常适合移动终端的需要,而且减少了系统崩溃的可能,确保了系统的稳定性。老想着清理内存的同学完全是因为被塞班或者Windows毒害太深,事实上,经常用Taskiller之类的软件关闭后台所有进程,很容易造成系统的不稳定。很多时候出现问题,只要重启就能解决,其原因也在于此。

      总之,牛B的人自己去操纵系统内存分配的阈值,普通用户则是想怎么用就怎么用,完全不用去鸟剩余内存的问题,那些内存清理的程序完全可以扔到一边了。对于如果有同学真的那么喜欢看着自己手机的剩余ram很大的话,可以用autokiller之类的工具,这类工具的原理不是杀进程,而是分配系统内存阈值,很简单很好用。

    3、手机慢的真正原因——CPU

      在Android里,进程和程序是两回事,程序可以一直保留在系统里,但是没有任何进程在后台“运行”,也不消耗任何系统资源。所有的程序保留在内存中,所有可以更快的启动回到它之前的状态。当你的内存用完了,系统会自动帮你杀掉你不用的任务。

      需要明白的是,Android用RAM的方式,跟windows啥的是两回事。在Android的世界里面,RAM被用满了是件'好'事。它意味着你可以快速打开之前打开的软件,回到之前的位置。所以Android很有效的使用RAM,很多用户看到他们的RAM满了,就认为拖慢了他们的电话。而实际上,是你的CPU——当你的软件真正运行时用到的东东——才是拖慢手机的瓶颈。

    4、进程管理软件=祸害?

      很流行的各种进程管理软件都说帮你释放内存是件好事,但这是不正确的。打开这些软件时,他们告诉你“运行”的软件和杀死他们的方法。你也可以在“服务”里面看到到底程序的哪些部分在“运行”,占用了多少内存,剩余多少内存。所有的这些都告诉你,杀掉这些程序能够释放内存。但是这些软件都没有告诉你这些程序到底消耗了多少CPU时钟,而仅仅告诉你能释放多少内存。要知道,用满了内存实际上是件好事,我们要注意的是CPU,真正消耗你的手机资源,消耗电池的东东。

      因此,杀掉程序通常是没有必要的(尤其是用"autokill"方式杀掉程序)。更严重的是,这样做会更快的拖垮你的手机能力和电池性能。不管是手动杀掉进程,还是自动的杀掉进程,重新打开程序,你实际上是在用CPU资源来做这件事。

      事实上,这些进程管理软件消耗了系统资源。而且,这些软件会莫名其妙的杀死其他程序造成乱七八糟的结果(尤其对些小白来说)。所有的这些,告诉我们,你的手机在用它自己的方式工作,特别是你只是个小白用户,用这些进程管理软件耽误的事情比得到的要多。

    5、善用快速启动

      这么说吧,各种程序开发水平是不一样的。很多人以前或者现在使用这些进程管理软件,释放内存,感觉手机快了那么一点。造成这个问题的原因是,你用的软件本身程序写得太烂了,比如,有得程序完全没有必要联网时,还在联着。这个时候,杀掉这些程序,你能得到好处,就是说,只有你知道你在干什么得时候,杀掉让你爱但是很烂的程序才能帮上你。

      事实上,很多开发者,包括ROM开发者,如果用了进程管理程序,当你提交bug报告时,看都不会看一眼(Cyanogen时这么干的,我不知道MIUI是不是),所以能不用就不要用了,除非你真的知道你在干什么。

      如果你真关系你的手机的表现和进程,还是多关注下系统进程,看看里面说各种程序都消耗了多少资源,如果某个程序消耗太多,时不时杀掉它可能会有那么一点帮助。

      总的来说,进程管理软件正确的用途是杀那些出错的程序、会导致死机有BUG的进程以及疑似病毒进程等,而不是一味地追求内存空得多程序在内存里放着,CPU不调用,它就是死的,一般程序你退出了它就不再运行了,不占用CPU资源(占用了CPU时间这个才是要耗电的),这就是2.2以上版本系统那个“快速启动”的工作原理。

    6、再说进程管理

      为什么内存少的时候运行大型程序会慢呢?其实很简单,在内存剩余不多时打开大型程序,会触发系统自身的调进程调度策略,这是十分消耗系统资源的操作,特别是在一个程序频繁向系统申请内存的时候。这种情况下系统并不会关闭所有打开的进程,而是选择性关闭,频繁的调度自然会拖慢系统。所以,论坛上有个更改内存阀值的程序可以有一定改善。但改动也可能带来一些问题,取决于值的设定。

      那么,进程管理软件有无必要呢?有的。就是在运行大型程序之前,你可以手动关闭一些进程释放内存,可以显著的提高运行速度。但一些小程序,完全可交由系统自己管理。谈到这里,可能有的朋友会问,如果不关程序是不是会更耗电。我就说说安卓Android后台的原理,你就明白了。安卓Android的应用在被切换到后台时,它其实已经被暂停了,并不会消耗cpu资源,只保留了运行状态。所以为什么有的程序切出去重进会到主界面。但是,一个程序如果想要在后台处理些东西,如音乐播放,它就会开启一个服务。服务可在后台持续运行,所以在后台耗电的也只有带服务的应用了。这个在进程管理软件里能看到,标签是service。所以没有带服务的应用在后台是完全不耗电的,没有必要关闭。这种设计本来就是一个非常好的设计,下次启动程序时,会更快,因为不需要读取界面资源,何必要关掉他们抹杀这个安卓Android的优点呢?

    7、内存管理中的虚拟机

      还有一个。为什么安卓Android一个应用看起来那么耗内存。大家知道,安卓Android上的应用是java,当然需要虚拟机,而安卓Android上的应用是带有独立虚拟机的,也就是每开一个应用就会打开一个独立的虚拟机。这样设计的原因是可以避免虚拟机崩溃导致整个系统崩溃,但代价就是需要更多内存。

      以上这些设计确保了安卓Android的稳定性,正常情况下最多单个程序崩溃,但整个系统不会崩溃,也永远没有内存不足的提示出现。大家可能是被windows毒害得太深了,总想保留更多的内存,但实际上这并不一定会提升速度,相反却丧失了程序启动快的这一系统特色,很没必要。大家不妨按我说的习惯来用用这个系统。最后推荐一款进程管理软件,systempanel,market上能搜到,界面友好启动快,功能也不错,用于手动关闭进程很好的软件。祝大家玩机愉快,这系统开十天半个月都没问题,不是windows。

    8、HOME键和后退键

      在运行一个程序时,按一下HOME键就可以退到桌面,一般来说按一下退出键也可以退到桌面,这两者有什么区别呢?

    • 按HOME键,看起来似乎是退出了,但是其实这个软件并没有被关闭,而是转为了后台程序(指一般的软件,不讨论特别种类的软件)
    • 按退出键,看起来也是退出没错,但这个软件其实是被转为了空置程序(音乐除外,音乐属于有服务的特殊软件)

      Android的所有5个程序进程的级别高低,空进程是最低的,它存在的目的是为了下次打开这个软件的时候可以更加方便快速(这是个很好的设计目的),而一旦需要清理出更多内存空间时,它也是被系统自动的最优先清除的

      所以,大家明白了吧?一旦需要退出软件时,如果是没有提供退出功能的软件,那么尽量用退出键退出而不是HOME键,并且,最重要的是,没有必要用进程管理类软件主动去清理空置进程,因为它本来就是为了被清理而存在,但在没轮到它被清理之前,还可以发挥重新快速开启的作用,一旦被你主动清理了,就连这点好处都没有了,那么,android系统的设计师又何必要设计出这个空置程序呢?直接释放内存不是更好么?所以,结论就是,既然它存在,就有它存在的好处!就要让我们享受到这个好处!用进程管理主动去清除空置程序绝对是违反android系统的设计本意的,是一种可笑的傻做法!

    8.1 HOME键

      众所周知,android跟iphone不同,咱们的gphone是一个典型的多任务系统,既然是多任务系统,那么自然就会有一个在多任务之间切换的需要,那么大家是否真的都会这个操作呢?

      这时候,就需要用到HOME键了,在一个程序中的时候,比如短信息,看到几个单词不认识,那么就可以选中这段文字,然后复制,按HOME键切换到桌面,然后打开词典,粘贴,查询,查好后再长按HOME键(长按的作用是在几个打开的程序和最近曾打开的程序之间切换),切换回短信息,这时候短信息程序不需要重新打开仍然是你刚才的界面,可以再复制然后长按切换词典继续查询下一个单词。

      这就是HOME键的用法,其实这是一个前后台程序之间切换而已。

      最后,简单的归纳一下所有内容,其实整篇文章的意思就是说,按退出键相当于“真正的”退出关闭程序,按HOME键,看起来似乎是关闭了程序,但是其实只是一种假象,程序只是被降低了仅仅“一”个等级而已,HOME更适合多任务切换用,就这么简单。

    8.2 应用

    1. 按home退出,程序保留状态为后台进程;按返回键退出,程序保留状态为空进程。空进程的oom_adj评值高于后台进程,更容易被系统清理。所以推荐用返回键退出。
    2. UC、愤怒小鸟、都市赛车之类程序本身提供关闭功能的,还是尽量主动关闭。浏览器、电子市场、opera mini等不提供关闭功能的,直接返回键退出就行。

    9、独特的进程管理策略

      Android采取了一种有别于Linux的进程管理策略,有别于Linux的在进程活动停止后就结束该进程,Android把这些进程都保留在内存中,直到系统需要更多内存为止。这些保留在内存中的进程通常情况下不会影响整体系统的运行速度,并且当用户再次激活这些进程时,提升了进程的启动速度。

      那Android什么时候结束进程?结束哪个进程呢?之前普遍的认识是Android是依据一个名为LRU(last recently used最近使用过的程序)列表,将程序进行排序,并结束最早的进程。XDA的楼主又进一步对这个管理机制进行研究,有了如下发现:

    1. 系统会对进程的重要性进行评估,并将重要性以“oom_adj”这个数值表示出来,赋予各个进程;(系统会根据“oom_adj”来判断需要结束哪些进程,一般来说,“oom_adj”的值越大,该进程被系统选中终止的可能就越高)
    2. 前台程序的“oom_adj”值为0,这意味着它不会被系统终止,一旦它不可访问后,会获得个更高的“oom_adj”,作者推测“oom_adj”的值是根据软件在LRU列表中的位置所决定的;
    3. Android不同于Linux,有一套自己独特的进程管理模块,这个模块有更强的可定制性,可根据“oom_adj”值的范围来决定进程管理策略,比如可以设定“当内存小于X时,结束“oom_adj”大于Y的进程”。这给了进程管理脚本的编写以更多的选择。
    4. Android将进程进行了分类:
      1. 前台进程(foreground):目前正在屏幕上显示的进程和一些系统进程。举例来说,Dialer Storage,GoogleSearch等系统进程就是前台进程;再举例来说,当你运行一个程序,如浏览器,当浏览器界面在前台显示时,浏览器属于前台进程(foreground),但一旦你按home回到主界面,浏览器就变成了后台程序(background)。我们最不希望终止的进程就是前台进程。
      2. 可见进程(visible):可见进程是一些不再前台,但用户依然可见的进程,举个例来说:widget、输入法等,都属于visible。这部分进程虽然不在前台,但与我们的使用也密切相关,我们也不希望它们被终止(你肯定不希望时钟、天气,新闻等widget被终止,那它们将无法同步,你也不希望输入法被终止,否则你每次输入时都需要重新启动输入法)
      3. 次要服务(secondary server):目前正在运行的一些服务(主要服务,如拨号等,是不可能被进程管理终止的,故这里只谈次要服务),举例来说:谷歌企业套件,Gmail内部存储,联系人内部存储等。这部分服务虽然属于次要服务,但很一些系统功能依然息息相关,我们时常需要用到它们,所以也太希望他们被终止
      4. 后台进程(hidden):虽然作者用了hidden这个词,但实际即是后台进程(background),就是我们通常意义上理解的启动后被切换到后台的进程,如浏览器,阅读器等。当程序显示在屏幕上时,他所运行的进程即为前台进程(foreground),一旦我们按home返回主界面(注意是按home,不是按back),程序就驻留在后台,成为后台进程(background)。后台进程的管理策略有多种:有较为积极的方式,一旦程序到达后台立即终止,这种方式会提高程序的运行速度,但无法加速程序的再次启动;也有较消极的方式,尽可能多的保留后台程序,虽然可能会影响到单个程序的运行速度,但在再次启动已启动的程序时,速度会有所提升。这里就需要用户根据自己的使用习惯找到一个平衡点
      5. 内容供应节点(content provider):没有程序实体,进提供内容供别的程序去用的,比如日历供应节点,邮件供应节点等。在终止进程时,这类程序应该有较高的优先权
      6. 空进程(empty):没有任何东西在内运行的进程,有些程序,比如BTE,在程序退出后,依然会在进程中驻留一个空进程,这个进程里没有任何数据在运行,作用往往是提高该程序下次的启动速度或者记录程序的一些历史信息。这部分进程无疑是应该最先终止的。

    10、极端情况

      至于为什么开了大程序或者开了好几个程序之后切换会变慢,我的理解如下:

    1. 大程序A已经开启,占用70%内存,如果再想运行一个B,需要50%的内存,则就需要一个将A从内存中释放或者压缩的过程,所以表现出来的就是慢一会儿
    2. A\B\C\D\E共占用内存80%,运行新程序Z需要20%的内存,系统内存因为没见过剩余0的时候,也就是应该剩一部分空闲内存,那么就需要从A~E这几个程序中选择一个或者几个来关闭,这一过程也需要耗费系统资源,所以会慢一会儿
    3. 也就是说你手动去杀程序的时候,就是替系统在释放内存,就算你不杀,在需要内存的时候系统也会自动释放。
    4. 不在后台运行的程序(没服务的),即使不杀也不会耗电。在后台运行的(有服务的)程序,如后台放歌,当然会耗电。
    5. 不是说杀进程没用,不然作者就不会推荐进程管理软件了。哪个带服务耗电哪个后台一直在运行,看服务就能看出来,这样的该杀。
    6. 以qq举例,正常的退,会在进程管理里留下qq的运行状态,但不耗电不占cpu,如果你只是切换出去(按HOME而不是退出)那么自然会耗电,因为程序还在运行。(qq后台一样后台就是qq正常退出的时候和别的软件一样不完全退出会在内存里留着但是不占cpu不费电再次启动就会非常快了这就是为什么android能超越WM6的系统的原因)

    11、MinFreeManager的使用

      进程管理,推荐使用MinFreeManager,市场上就有下载,用于设置这六类进程的管理策略。

      软件运行后有六个输入框,在输入框中只能输入数字,这些数字代表了这类进程的处理策略,比如Foreground App下的输入框显示6,就表示,当可用内存低于6MB时,终止Foreground App。下面的类似,如Empty App下的输入框显示24,则表示,当内存低于24MB时,终止Empty App。

      从软件数值的设置不难看出结束进程的有限顺序:Empty>Content Provider>Hidden>Secondary Server>Visible>Foreground。

    11.1 默认设置存在的一些问题:

      各类进程的管理策略的阀值相当接近:6,8,16,20,22,24,最大的相差也不到8MB,在实际程序运行中,很容易导致多种类型的进程同时被关闭。如可用内存在25时,突然启动照相程序,系统可用内存急速,可能会导致空进程、内容供应节点、后台进程、次要服务等同时被关闭阀值上限较低:一般手机启动后,可用内存在50-100左右,但随着手机的使用,可用内存会逐步减少,最后降低到24MB左右,则系统开始启动进程管理机制,开始结束进程,但这个阀限制设在了24MB,相对来说偏低。其结果会导致系统使用一段时间后,整体速度变慢。很明显的就是,当手机长时间使用后,开启电话拨号,相册,照相机等应用时,系统的反应速度极慢。

    11.2 解决两个矛盾:

    1. 拉开各进程的阀值层次,使得进程管理机制能更有效得工作
    2. 提升阀值上限,空出更多的空余内存,以提升系统整体的运行速度

    11.3 进程管理策略设置原则:

      前台进程、可见进程和次要服务是与用户体验息息相关的内容,这部分的进程管理策略要相对保守,给这些进程留下足够的运行空间

      压榨无用进程,腾出内存空间给主要程序使用

    11.4适应不同的使用需要的几种设置方式

    11.4.1 游戏玩家/重度浏览器使用者配置:

      用户特点:长时间专注于某一特定的,高内存需求的程序,对多任务的需求不高

      配置参数:

    1. Foreground:6
    2. Visible:8
    3. Secondary Server:16
    4. Hiden App:80
    5. Content Provider:90
    6. Empty:100

      配置理念:压榨后台进程,内容供应节点和空进程,将内存尽可能多得留给前台进程和系统,提升游戏速度和浏览器体验

      优点:程序启动和运行的速度最快

      缺点:多任务处理不理想,开启程序较多时,后台进程会被终止

    11.4.2 多任务配置:

      用户特点:同时运行多个应用程序,需要经常在多个程序间切换

      配置参数:

    1. Foreground:6
    2. Visible:8
    3. Secondary Server:16
    4. Hiden App:20
    5. Content Provider:60
    6. Empty:100

      配置理念:压榨空进程,给内容供应节点留有一定空间,最大限度提升后台程序的使用空间,提升多任务的处理能力

      优点:运行多个程序时,由于可支配内存较多,后台程序不容易被终止

      缺点:程序启动的速度和整体系统的运行速度可能会比游戏玩家配置略慢一些,由于经常运行多任务,平时系统的响应速度会受到一定影响

    11.4.3 轻度用户/女生专用配置

      用户特点:手机的主要功能是短信和电话,偶尔用用相机自拍

      配置参数:

    1. Foreground:6
    2. Visible:8
    3. Secondary Server:16
    4. Hiden App:24
    5. Content Provider:32
    6. Empty:48

      配置理念:压榨空进程,给内容供应节点留有一定空间,最大限度提升后台程序的使用空间,提升多任务的处理能力

      优点:比较均衡的配置,提升了系统的可用内存,使得系统的整体速度得到了提高,拉开了各级进程的管理策略层次,使得管理机制更有效率

      缺点:比较均衡的配置,无明显缺点 

    12、总结

    12.1 快速启动

      有着良好windows操作习惯,而又不了解Android内存管理机制的人,在使用Android系统的时候,会很在意系统的内存资源使用情况——去频频清除那些不使用而常驻内存的程序(进程),这样就会忽略掉android的一个独特的优点,进而在不知情的情况下白白消耗宝贵的手机资源。

      手机资源的宝贵,在于它的CPU,在于它的电量。不使用而常驻内存的进程,一般以后台进程和空进程的形式存在内存中(QQ、音乐播放等是开启了service,不同于这一情况),是不会消耗CPU和电量的,相反常驻内存有个显著的长处,是程序在不重复消耗资源的情况下获得了快速启动,这是Android独特的进程管理特点。

      而频频用进程管理软件主动清除后台和空进程是要消耗资源的,而进程的关闭和开启也要消耗相应的资源,简单说来,这就是用一个资源消耗的动作去实现另一个资源消耗的动作,最终导致重启程序时第三个资源消耗动作的发生。

    12.2 HOME键和退出键

      按HOME键,程序转入后台进程;

      按退出键,程序直接转入空进程;

      此时进程获得了快速启动的功能,而不消耗任何资源

    12.3 Android的进程管理机制

    那是不是将程序全部以后台和空进程的形式常驻内存就会将快速启动这一优点发挥到最大?

      不是的,技术的进步,内存再大也是有限的,这就得说到内存管理的另一个机制——进程管理。进程按照优先级分为五类:前台进程、可见进程、服务进程、后台进程、空进程,从左往右优先级的值依次递增,当内存紧张时,那么进程管理机制就会根据优先级的值,从高到低依次关闭,空进程->后台进程->可见进程->服务进程->前台进程,从此可见,那么对空进程和后台进程会消耗内存资源的担忧可以缓一缓了,因为后台和空进程的状态从另一面来说也可以理解为“准备关闭“的进程。

      如此,我们就可将一般的软件交给进程管理机制自身进行管理就好了

    12.4 进程管理软件

      Android进程管理机制如此智能,但相应的软件作为工具的存在还是有着自身的价值。

      1、大量需要内存

      当我们可预见的需要大量内存,如开启一个消耗内存的进程(游戏)、或某一时刻开启大量的进程时,如果这时还交由进程管理机制来处理,那么就会导致机制频繁的检查剩余内存、关闭进程、开启新进程这一流程,这时不明智的。我们可以做的是,事先使用进程管理软件,将要使用的内存一次性清理出来,再来开启相应的进程。

      2、不良软件

      除开上述情况,还有一种情况是,面对不良软件,即在后台运行也开启消耗资源,如弹窗、耗电、走流量等服务进程,而在某一时段又不便卸载的情况下,进程管理软件也能体现相应的价值。

    12.5 开发者选项中的内存管理功能

    Android手机都存在这一功能,里面有着几项与内存管理相关的选项:

    • 不保留活动:对activity进程的限制;
    • 后台进程限制:名字很是直白,这一功能能在一定程度上解决12.4中的问题,但是还是那句话禁用后台进程的话本身就是禁掉了Android系统本身的特色——快速启动;
    • 系统内存优化级别:对后台进程的压缩程度,越是高级压缩越厉害,但相应的程序之间的切换也越容易卡,而且压缩本身也是一个消耗资源的过程。所以如果程序之间切换较为频繁,可禁用这一功能,但是如果有长时玩单一游戏的习惯的话,可以依照自身程序切换频率设置相当的级别。

    http://blog.csdn.net/breaker892902/article/details/22224243


    展开全文
  • Python内存管理机制

    千次阅读 2016-03-05 12:22:54
    Python内存管理机制Python内存管理机制主要包括以下三个方面: 引用计数机制 垃圾回收机制 内存池机制 引用计数举个例子说明引用是什么:a = 1如上为一个简单的赋值语句,1就是对象,a就是引用,引用a指向对象1。 ...

    Python内存管理机制

    Python内存管理机制主要包括以下三个方面:

    • 引用计数机制
    • 垃圾回收机制
    • 内存池机制

    引用计数

    举个例子说明引用是什么:

    a = 1

    如上为一个简单的赋值语句,1就是对象,a就是引用,引用a指向对象1。
    同理:

    b = 1

    b也是对象1的引用。
    通过内置函数id()返回对象的地址。

    print id(a)  #43220320
    print id(b)  #43220320

    当我们创建多个等于1的引用时,实际上是让所有这些引用指向同一个对象。为了检验两个引用指向同一个对象,我们可以用is关键字。is用于判断两个引用所指向的对象是否相同。

    print (a is b)  #True

    在Python中,整数和短小的字符,Python都会缓存这些对象,以便重复使用。赋值语句,只是创造了新的引用,而不是对象本身。长的字符串和其它对象可以有多个相同的对象,可以使用赋值语句创建出新的对象。每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。
    可以使用sys.getrefcount()获得引用计数,需要注意的是,当使用某个引用作为参数,传递给getrefcount()时,参数实际上创建了一个临时的引用。因此,getrefcount()所得到的结果,会比期望的多1。

    from sys import getrefcount
    
    a = [1, 2, 3]
    print(getrefcount(a)) # 2
    
    b = a
    print(getrefcount(b)) # 3
    • 引用计数增加
      1.对象被创建:x=4
      2.另外的别人被创建:y=x
      3.被作为参数传递给函数:foo(x)
      4.作为容器对象的一个元素:a=[1, x, ‘33’]

    • 引用计数减少
      1.一个本地引用离开了它的作用域。比如上面的foo(x)函数结束时,x指向的对象引用减1。
      2.对象的别名被显式的销毁:del x ;或者del y
      3.对象的一个别名被赋值给其他对象:x=789
      4.对象从一个窗口对象中移除:myList.remove(x)
      5.窗口对象本身被销毁:del myList,或者窗口对象本身离开了作用域。

    垃圾回收

    • 引用计数
      引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。比如某个新建对象,它被分配给某个引用,对象的引用计数变为1。如果引用被删除,对象的引用计数为0,那么该对象就可以被垃圾回收。
      不过如果出现循环引用的话,引用计数机制就不再起有效的作用了
    a = []
    b = []
    a.append(b)
    b.append(a)
    print a  # [[[…]]]
    print b  # [[[…]]]

    循环引用可以使一组对象的引用计数不为0,然而这些对象实际上并没有被任何外部对象所引用,它们之间只是相互引用。这意味着不会再有人使用这组对象,应该回收这组对象所占用的内存空间,然后由于相互引用的存在,每一个对象的引用计数都不为0,因此这些对象所占用的内存永远不会被释放。
    Python又引入了其他的垃圾收集机制来弥补引用计数的缺陷:“标记-清除“,“分代回收”两种收集技术。

    • 标记清除
      如果两个对象的引用计数都为1,但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的,也就是说,它们的引用计数虽然表现为非0,但实际上有效的引用计数为0。所以先将循环引用摘掉,就会得出这两个对象的有效计数。
      在实际操作中,并不改动真实的引用计数,而是将集合中对象的引用计数复制一份副本,改动该对象引用的副本。对于副本做任何的改动,都不会影响到对象生命周期的维护。
      这个计数副本的唯一作用是寻找root object集合(该集合中的对象是不能被回收的)。当成功寻找到root object集合之后,首先将现在的内存链表一分为二,一条链表中维护root object集合,成为root链表,而另外一条链表中维护剩下的对象,成为unreachable链表。之所以要剖成两个链表,是基于这样的一种考虑:现在的unreachable可能存在被root链表中的对象,直接或间接引用的对象,这些对象是不能被回收的,一旦在标记的过程中,发现这样的对象,就将其从unreachable链表中移到root链表中;当完成标记后,unreachable链表中剩下的所有对象就是名副其实的垃圾对象了,接下来的垃圾回收只需限制在unreachable链表中即可。

    • 分代回收
      从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作就越少;反之,当需回收的内存块越少时,垃圾检测就将比垃圾回收带来更少的额外操作。
      举个例子来说明:
      当某些内存块M经过了3次垃圾收集的清洗之后还存活时,我们就将内存块M划到一个集合A中去,而新分配的内存都划分到集合B中去。当垃圾收集开始工作时,大多数情况都只对集合B进行垃圾回收,而对集合A进行垃圾回收要隔相当长一段时间后才进行,这就使得垃圾收集机制需要处理的内存少了,效率自然就提高了。在这个过程中,集合B中的某些内存块由于存活时间长而会被转移到集合A中,当然,集合A中实际上也存在一些垃圾,这些垃圾的回收会因为这种分代的机制而被延迟。

    内存池

    python内存机制层次

    • Python的内存机制呈现金字塔形状,-1,-2层主要有操作系统进行操作;
    • 第0层是C中的malloc,free等内存分配和释放函数进行操作;
    • 第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256K时有该层直接分配内存;
    • 第3层是最上层,也就是我们对Python对象的直接操作;

    Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。
    Python内部默认的小块内存与大块内存的分界点定在256个字节,当申请的内存小于256字节时,PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc的行为将蜕化为malloc的行为。当然,通过修改Python源代码,我们可以改变这个默认值,从而改变Python的默认内存管理行为。

    展开全文
  • Spring的事务管理机制

    千次阅读 2020-06-29 18:22:10
    Spring事务管理机制概述 Spring事务管理模块主要包括3个接口 PlatformTransactionManager:事务管理器,主要用于平台相关的事务管理。 TransactionDefinition:事务定义信息(隔离级别、传播、超时、只读)通过配置...
  • 管理机制是Android中的重要机制,是应用开发和系统开发需要掌握的知识点之一。 包指的是Apk、jar和so文件等等,它们被加载到Android内存中,由一个包转变成可执行的代码,这就需要一个机制来进行包的加载、解析、...
  • JVM类加载机制   .java文件编译—&gt;生成JVM能够识别的.class字节码文件—&gt;JVM把.class文件加载到内存—&...JVM内存管理机制   JVM将内存划分为几个部分:PC寄存器(程序计数器)...
  • iOS的内存管理机制ARC和MRC是程序员参加面试基本必问的问题,也是考察一个iOS基本功是 否扎实的关键,这样深入理解内存管理机制的重要性就不言而喻了。 iOS内存管理机制发展史 iOS 5以前 :MRC(手动引用计数) ...
  • Python的内存管理机制

    千次阅读 2017-11-25 12:06:41
    Python的内存管理机制 一、引用计数:通过引用计数来保持对内存中的变量跟踪,Python内部记录中所有在使用对象各有多少个引用。 Python中有个内部跟踪变量叫做引用计数器,每个变量有多少个引用,简称引用计数。当...
  • 操作系统-内存管理机制

    千次阅读 2017-08-09 14:53:19
    本文总结了我对内存管理机制的学习,先从通用的操作系统课本的内存管理机制学习,然后深入到Linux操作系统,对于内存管理机制的实现。通用操作系统内存管理机制这一目我主要参考的是汤小丹老师《计算机操作系统》...
  • Python之内存管理机制

    千次阅读 2017-10-14 22:20:35
    Python的内存管理机制主要包括三个方面:引用计数机制、垃圾回收机制、内存池机制 一、引用计数机制 Python内部使用引用计数来保持追踪内存中的对象,所有对象都有引用计数。 引用计数增加的情况: (1)对象被创建...
  • memcached内存管理机制详解

    千次阅读 2014-12-06 20:12:20
    我们知道,memcached是一个内存缓存系统,因此对于内存的管理是需要使用者了解的。本文将对memcached的内存模型及管理机制做一个详细的描述。
  • js 内存管理机制

    千次阅读 2013-03-18 21:44:01
    1 最近在项目中,由于setInterval 和 闭包的使用,导致对象没有清除,带来很多性能上面的问题,如果能理解浏览器js 对象管理机制,将有效避免问题的出现 2 受限无移动设备的性能问题,很多在pc上没有问题的程序,在...
  • JVM内存管理机制 Jvm内存管理机制 java中是把内存的管理交给java虚拟机来管的,有java虚拟机中的垃圾回收机制来清理内存 Java虚拟机(Java virtualmachine)实现了Java语言最重要的特征:即平台无关性。 平台...
  • Java中的内存管理机制

    千次阅读 2018-06-14 19:07:05
    Java中的内存管理机制Java内存的划分java把内存分为两种栈内存堆内存栈内存在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码中定义一个变量时,java就会在栈中为这个变量...
  • 2.内存管理机制 我们知道C++中并没有什么内存管理机制。对于栈上对象我们无需关心,因为它的空间由系统负责,而堆上对象必须由程序猿负责空间的申请与释放。Qt作为第三方类库,给出了一套很好的内存管理机制。 ...
  • linux内存管理机制以及free命令详解

    千次阅读 2017-11-23 20:32:49
    linux内存管理机制以及free命令详解 一、linux内存管理机制  1.物理内存和虚拟内存  直接从物理内存读写数据要比从硬盘读写数据要快的多,因此,我们希望所有数据的读取和写入都在内存完成,而内存是有限的,这样...
  • Spring事务管理机制

    千次阅读 2018-10-24 19:55:31
    Spring事务管理高层抽象主要包括3个接口,Spring的事务主要是由他们共同完成的: PlatformTransactionManager:事务管理器—主要用于平台相关事务的管理 TransactionDefinition: 事务定义信息(隔离、传播、超时...
  • jvm-内存管理机制(一)

    千次阅读 2018-08-06 18:14:47
    jvm-内存管理机制(一) JVM内存区域主要包括如下部分:程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区。 JVM内存管理也可以理解为–jvm运行时数据区,jvm内存主要管理的就是这片内存区域。 堆(各...
  • 轻量级操作系统FreeRTOS的内存管理机制
  • IA32CPU内存管理机制

    千次阅读 2011-11-20 10:02:26
    最近看了一些Inter32CPU的内存管理机制,做个总结,但是我毕竟是新手,对很多东西也是一知半解,希望大家指教。 1.物理内存的管理,这不考虑MMU的内存管理机制,纯粹的对物理内存的管理,在电脑刚启动时候的实模式...
  • C/C++/Java/C#/Python的内存管理机制整理

    千次阅读 2015-08-13 21:39:07
    一 C语言的内存管理机制
  • Ruby的内存管理机制

    千次阅读 2015-03-03 11:20:49
    原文在此 ...Ruby有自己的内存管理机制,叫做Ruby Heaps。他独立于操作系统的System Heap,包含很多Slots, 其中
  • cocos2dx的内存管理机制

    万次阅读 热门讨论 2014-04-10 13:00:03
    今天看了一下cocos2dx的内存管理机制,有些地方不太好理解搞了挺长的时间,现在感觉自己理解的差不多了,赶快写下自己的思路和互联网的广大朋友分享,如果你发现有错误的地方或者不理解的地方欢迎指正!首先我们必须...
  • Mycat源码篇 : MyCat事务管理机制分析

    万次阅读 2016-08-26 17:25:34
    针对MyCat1.5版本,对MyCat的事务管理机制进行简要分析
  • C语言的内存管理机制

    万次阅读 多人点赞 2018-07-22 15:39:30
    尤其对于移动端开发者来说,硬件资源的限制使得其在程序设计中首要考虑的问题就是如何有效地管理内存资源。本文是作者在学习C语言内存管理的过程中做的一个总结。 变量概念: 全局变量(外部变量):出现在代码...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,261,045
精华内容 504,418
关键字:

管理机制