【易客吧】_全网激活码总代_激活码商城

您现在的位置是:首页 > 热门资讯 > 正文

热门资讯

优化 GC 算法:提高应用程序性能和效率 (gc优化思路)

用户投稿2024-04-08热门资讯29

简介

废品回收 (GC) 是内存管理中至关重要的一部分,它在确保应用程序正常运行和防止内存泄漏方面发挥着关键作用。GC 算法的实现方式会对应用程序的性能和效率产生显著影响。本文将探讨各种优化 GC 算法的方法,以提高应用程序的性能。

GC 优化思路

优化 GC 算法有几种不同的方法,下面是一些最常见的技巧:

1. 使用分代收集器

分代收集器将对象分配到不同的代,根据其生存时间进行划分。这使 GC 可以专注于收集最容易被回收的对象,从而减少 GC 开销。

2. 减少 GC 暂停时间

GC 暂停时间是指应用程序停止执行以进行 GC 的时间。可以通过使用增量或并发 GC 算法来减少暂停时间。

3. 调整 GC 线程数量

在某些情况下,增加或减少 GC 线程的数量可以改善性能。通过调整线程数量,可以优化 GC 并行处理的程度。

4. 监视和分析 GC 活动

监视和分析 GC 活动对于识别性能问题至关重要。可以使用工具(如 GCViewer 或 YourKit)来收集有关 GC 行为的数据。

5. 调优 GC 参数

许多 GC 算法允许调整各种参数,例如堆大小、收集频率等。通过仔细调优这些参数,可以优化 GC 行为。

特定语言的 GC 优化

除了上述通用技巧之外,还有针对特定语言的 GC 优化方法。以下是针对 Java、C 和 Python 的一些建议:

Java

使用 G1 收集器,因为它提供了良好的暂停时间和吞吐量平衡。启用逃逸分析以识别可以避免 GC 的对象。使用对象池来减少对象分配和回收的开销。

C

使用增量 GC 来减少暂停时间。启用服务器 GC 模式以提高大堆的性能。使用 Large Object Heap (LOH) 来存储大型对象。

Python

使用循环引用检测器来检测和破坏循环引用。使用弱引用来表示不再使用的对象。禁用对未使用的对象的引用计数。

最佳实践

除了特定的优化技术外,遵循以下最佳实践也有助于提高 GC 性能:避免分配过多的对象。尽可能重用对象。将大型对象分配到 LOH(如果适用)。避免创建循环引用。

结论

优化 GC 算法是提高应用程序性能和效率的关键。通过遵循本文中概述的技巧,可以显著减少 GC 开销并提高应用程序的响应能力。利用特定的语言优化和最佳实践,可以进一步提高 GC 性能。

GC策略&内存申请、对象衰老

JVM里的GC(Garbage Collection)的算法有很多种 如标记清除收集器 压缩收集器 分代收集器等等 详见HotSpot VM GC 的种类

现在比较常用的是分代收集(generational collection 也是SUN VM使用的 J SE 之后引入) 即将内存分为几个区域 将不同生命周期的对象放在不同区域里:young generation tenured generation和permanet generation 绝大部分的objec被分配在young generation(生命周期短) 并且大部分的object在这里die 当young generation满了之后 将引发minor collection(YGC) 在minor collection后存活的object会被移动到tenured generation(生命周期比较长) 最后 tenured generation满之后触发major collection major collection(Full gc)会触发整个heap的回收 包括回收young generation permanet generation区域比较稳定 主要存放classloader信息

young generation有eden 个survivor 区域组成 其中一个survivor区域一直是空的 是eden区域和另一个survivor区域在下一次copy collection后活着的objecy的目的地 object在survivo区域被复制直到转移到tenured区

我们要尽量减少 Full gc 的次数(tenured generation 一般比较大 收集的时间较长 频繁的Full gc会导致应用的性能收到严重的影响)

堆内存GC

JVM(采用分代回收的策略) 用较高的频率对年轻的对象(young generation)进行YGC 而对老对象(tenured generation)较少(tenured generation 满了后才进行)进行Full GC 这样就不需要每次GC都将内存中所有对象都检查一遍

非堆内存不GC

GC不会在主程序运行期对PermGen Space进行清理 所以如果你的应用中有很多CLASS(特别是动态生成类 当然permgen space存放的内容不仅限于类)的话 就很可能出现PermGen Space错误

内存申请 对象衰老过程

一 内存申请过程

&# ;JVM会试图为相关Java对象在Eden中初始化一块内存区域

&# ;当Eden空间足够时 内存申请结束 否则到下一步

&# ;JVM试图释放在Eden中所有不活跃的对象(minor collection) 释放后若Eden空间仍然不足以放入新对象 则试图将部分Eden中活跃对象放入Survivor区

&# ;Survivor区被用来作为Eden及old的中间交换区域 当OLD区空间足够时 Survivor区的对象会被移到Old区 否则会被保留在Survivor区

&# ;当old区空间不够时 JVM会在old区进行major collection

&# ;完全废品收集后 若Survivor及old区仍然无法存放从Eden复制过来的部分对象 导致JVM无法在Eden区为新对象创建内存区域 则出现 Out of memory错误

二 对象衰老过程

&# ;新创建的对象的内存都分配自eden Minor collection的过程就是将eden和在用survivor space中的活对象copy到空闲survivor space中 对象在young generation里经历了一定次数(可以通过参数配置)的minor collection后 就会被移到old generation中 称为tenuring

&# ;GC触发条件

GC类型 触发条件 触发时发生了什么 注意 查看方式YGC eden空间不足

清空Eden+from survivor中所有no ref的对象占用的内存将eden+from sur中所有存活的对象copy到to sur中一些对象将晋升到old中:to sur放不下的存活次数超过turning threshold中的重新计算tenuring threshold(serial parallel GC会触发此项)

重新调整Eden 和from的大小(parallel GC会触发此项)

全过程暂停应用是否为多线程处理由具体的GC决定 jstat –gcutil gc log FGC

old空间不足perm空间不足显示调用System GC RMI等的定时触发YGC时的悲观策略dump live的内存信息时(jmap –dump:live)

清空heap中no ref的对象permgen中已经被卸载的classloader中加载的class信息如配置了CollectGenOFirst 则先触发YGC(针对serial GC)如配置了ScavengeBeforeFullGC 则先触发YGC(针对serial GC) 全过程暂停应用是否为多线程处理由具体的GC决定是否压缩需要看配置的具体GC jstat –gcutil gc log lishixinzhi/Article/program/Java/hx//

JVM 技术详解:常见的 GC 算法(Parallel/CMS/G1)

学习了 GC 算法的相关概念之后,我们将介绍在 JVM 中这些算法的具体实现。首先要记住的是,大多数 JVM 都需要使用两种不同的 GC 算法——一种用来清理年轻代,另一种用来清理老年代。

我们可以选择 JVM 内置的各种算法。如果不通过参数明确指定废品收集算法,则会使用相应 JDK 版本的默认实现。本章会详细介绍各种算法的实现原理。

串行 GC 对年轻代使用 mark-copy(标记—复制)算法,对老年代使用 mark-sweep-compact(标记—清除—整理)算法。

两者都是单线程的废品收集器,不能进行并行处理,所以都会触发全线暂停(STW),停止所有的应用线程。

因此这种 GC 算法不能充分利用多核 CPU。不管有多少 CPU 内核,JVM 在废品收集时都只能使用单个核心。

要启用此款收集器,只需要指定一个 JVM 启动参数即可,同时对年轻代和老年代生效:

该选项只适合几百 MB 堆内存的 JVM,而且是单核 CPU 时比较有用。

优化 GC 算法:提高应用程序性能和效率 (gc优化思路) 第1张

对于服务器端来说,因为一般是多个 CPU 内核,并不推荐使用,除非确实需要限制 JVM 所使用的资源。大多数服务器端应用部署在多核平台上,选择 串行 GC 就意味着人为地限制了系统资源的使用,会导致资源闲置,多余的 CPU 资源也不能用增加业务处理的吞吐量。

关于串行废品收集器的日志内容,我们在后面的内容《GC 日志解读与分析》之中进行详细的讲解。

并行废品收集器这一类组合,在年轻代使用“标记—复制(mark-copy)算法”,在老年代使用“标记—清除—整理(mark-sweep-compact)算法”。年轻代和老年代的废品回收都会触发 STW 事件,暂停所有的应用线程来执行废品收集。两者在执行“标记和复制/整理”阶段时都使用多个线程,因此得名“ Parallel ”。通过并行执行,使得 GC 时间大幅减少。

通过命令行参数-XX:ParallelGCThreads=NNN来指定 GC 线程数,其默认值为 CPU 核心数。可以通过下面的任意一组命令行参数来指定并行 GC:

并行废品收集器适用于多核服务器,主要目标是增加吞吐量。因为对系统资源的有效使用,能达到更高的吞吐量:

Android性能优化总结

常用的Android性能优化方法:一、布局优化: 1)尽量减少布局文件的层级。 层级少了,绘制的工作量也就少了,性能自然提高。 2)布局重用 <include标签> 3)按需加载:使用ViewStub,它继承自View,一种轻量级控件,本身不参与任何的布局和绘制过程。 他的layout参数里添加一个替换的布局文件,当它通过setVisibility或者inflate方法加载后,它就会被内部布局替换掉。 二、绘制优化: 基于onDraw会被调用多次,该方法内要避免两类操作: 1)创建新的局部对象,导致大量废品对象的产生,从而导致频繁的gc,降低程序的执行效率。 2)不要做耗时操作,抢CPU时间片,造成绘制很卡不流畅。 三、内存泄漏优化: 1)静态变量导致内存泄漏比较明显 2)单例模式导致的内存泄漏单例无法被废品回收,它持有的任何对象的引用都会导致该对象不会被gc。 3)属性动画导致内存泄漏 无限循环动画,在activity中播放,但是onDestroy时没有停止的话,动画会一直播放下去,view被动画持有,activity又被view持有,导致activity无法被回收。 四、响应速度优化: 1)避免在主线程做耗时操作 包括四大组件,因为四大组件都是运行在主线程的。 2)把一些创建大量对象等的初始化工作放在页面回到前台之后,而不应该放到创建的时候。 五、ListView的优化: 1)使用convertView,走listView子View回收的一套:RecycleBin 机制 主要是维护了两个数组,一个是mActiveViews,当前可见的view,一个是mScrapViews,当前不可见的view。 当触摸ListView并向上滑动时,ListView上部的一些OnScreen的View位置上移,并移除了ListView的屏幕范围,此时这些OnScreen的View就变得不可见了,不可见的View叫做OffScreen的View,即这些View已经不在屏幕可见范围内了,也可以叫做ScrapView,Scrap表示废弃的意思,ScrapView的意思是这些OffScreen的View不再处于可以交互的Active状态了。 ListView会把那些ScrapView(即OffScreen的View)删除,这样就不用绘制这些本来就不可见的View了,同时,ListView会把这些删除的ScrapView放入到RecycleBin中存起来,就像把暂时无用的资源放到回收站一样。 当ListView的底部需要显示新的View的时候,会从RecycleBin中取出一个ScrapView,将其作为convertView参数传递给Adapter的getView方法,从而达到View复用的目的,这样就不必在Adapter的getView方法中执行()方法了。 RecycleBin中有两个重要的View数组,分别是mActiveViews和mScrapViews。 这两个数组中所存储的View都是用来复用的,只不过mActiveViews中存储的是OnScreen的View,这些View很有可能被直接复用;而mScrapViews中存储的是OffScreen的View,这些View主要是用来间接复用的。 2)使用ViewHolder避免重复地findViewById 3)快速滑动不适合做大量异步任务,结合滑动监听,等滑动结束之后加载当前显示在屏幕范围的内容。 4)getView中避免做耗时操作,主要针对图片:ImageLoader来处理(原理:三级缓存) 5)对于一个列表,如果刷新数据只是某一个item的数据,可以使用局部刷新,在列表数据量比较大的情况下,节省不少性能开销。 六、Bitmap优化: 1)减少内存开支:图片过大,超过控件需要的大小的情况下,不要直接加载原图,而是对图片进行尺寸压缩,方式是 采样,inSampleSize 转成需要的尺寸的图片。 2)减少流量开销:对图片进行质量压缩,再上传服务器。 图片有三种存在形式:硬盘上时是file,网络传输时是stream,内存中是stream或bitmap,所谓的质量压缩,它其实只能实现对file的影响,你可以把一个file转成bitmap再转成file,或者直接将一个bitmap转成file时,这个最终的file是被压缩过的,但是中间的bitmap并没有被压缩。 (,100,bos);七、线程优化: 使用线程池。 为什么要用线程池? 1、从“为每个任务分配一个线程”转换到“在线程池中执行任务” 2、通过重用现有的线程而不是创建新线程,可以处理多个请求在创建销毁过程中产生的巨大开销 3、当使用线程池时,在请求到来时间 ,不用等待系统重新创建新的线程,而是直接复用线程池中的线程,这样可以提高响应性。 4、通过和适当调整线程池的大小 ,可以创建足够多的线程以使处理器能够保持忙碌状态,同时还可以防止过多线程相互竞争资源而使应用程序耗尽内存或者失败。 5、一个App里面所有的任务都放在线程池中执行后,可以统一管理 ,当应用退出时,可以把程序中所有的线程统一关闭,避免了内存和CPU的消耗。 6、如果这个任务是一个循环调度任务,你则必须在这个界面onDetach方法把这个任务给cancel掉,如果是一个普通任务则可cancel,可不cancel,但是最好cancel 7、整个APP的总开关会在应用退出的时间把整个线程池全部关闭。 八、一些性能优化建议: 1)避免创建过多对象,造成频繁的gc 2)不要过多使用枚举,枚举占用的空间比整型大很多 3)字符串的拼接使用StringBuffer、StringBuilder来替代直接使用String,因为使用String会创建多个String对象,参考第一条。 4)适当使用软引用,(弱引用就不太推荐了) 5)使用内存缓存和磁盘缓存。

若对本页面资源感兴趣,请点击下方或右方图片,注册登录后

搜索本页相关的【资源名】【软件名】【功能词】或有关的关键词,即可找到您想要的资源

如有其他疑问,请咨询右下角【在线客服】,谢谢支持!

优化 GC 算法:提高应用程序性能和效率 (gc优化思路) 第2张

发表评论

评论列表

  • 这篇文章还没有收到评论,赶紧来抢沙发吧~
欢迎你第一次访问网站!