GC优化的Java应用程序的音频 [英] Tuning GC for Java audio application

查看:155
本文介绍了GC优化的Java应用程序的音频的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到,在java中播放音频的时候,在GC MarkSweepCompact期过长而导致的沉默时间很短,这是不可接受的。所以,我需要使用一个低暂停GC。我试过并行和CMS,他们似乎更好地工作,因为我想暂停更短,他们没有做充分收集尽可能多的默认值。

I've noticed that when playing audio in java, MarkSweepCompact stage in gc is too long and results in short periods of silence, which is unacceptable. So I need to use a low pause gc. I've tried Parallel and CMS, they seem to work better because I suppose the pause is shorter and they don't do full collection as often as the default one.

到目前为止,我测试了我与ParallelGC下列选项程序:

So far I've tested my program with the following options for ParallelGC:

-XX:+UseParallelGC 
-XX:MaxGCPauseMillis=70

和ConcurrentMarkSweep:

and for ConcurrentMarkSweep:

-XX:+UseConcMarkSweepGC
-XX:+CMSIncrementalMode
-XX:+CMSIncrementalPacing

我也试过G1GC,但它仍处于试验阶段在Java 6两种模式选项:

I also tried G1GC, but it's still experimental in java 6. Options for both modes:

-Xms15m
-Xmx40m
-XX:+UnlockExperimentalVMOptions
-XX:+CMSClassUnloadingEnabled
-XX:+TieredCompilation
-XX:+AggressiveOpts
-XX:+UseAdaptiveSizePolicy
-Dsun.java2d.noddraw=false
-Dswing.aatext=true
-XX:MaxPermSize=25m
-XX:MaxHeapFreeRatio=10
-XX:MinHeapFreeRatio=10

这是GC在这种情况下更好?可以任何设置最佳的CPU性能和最小的内存使用情况,以及优化?

Which GC is better in this situation? Can any of these settings be optimized for best CPU performance and minimal memory usage as well?

修改:要承认我的记录时间的音频数据写入到输出线,通常是92到120毫秒之间的停顿(我写16384字节=〜92ms),广告时完全GC运行时,它是200 + MS:

EDIT To recognize the pause I record time to write audio data to the output line, usually it's between 92 to 120 ms (I'm writing 16384 bytes = ~92ms), ad when Full GC is run, it's 200+ ms:

65.424: [Full GC (System) [PSYoungGen: 872K->0K(2432K)] [PSOldGen: 12475K->12905K(16960K)] 13348K->12905K(19392K) [PSPermGen: 15051K->15051K(22272K)], 0.2145081 secs] [Times: user=0.20 sys=0.00, real=0.21 secs] 
Was writing 16384 bytes, time to write 263 ms

EDIT2 我的应用程序分配格局是这样的:加载一堆在启动对象,然后开始玩,我想最后由GUI分配的对象,因为直视/暂停音频没有太大变化的GC图。这是visualgc中显示了并行GC:

EDIT2 Allocation pattern for my app is the following: it loads bunch of objects at startup, then it starts playing and I guess most of the objects after that are allocated by the gui, because staring/pausing the audio doesn't change the GC graph much. This is what visualgc shows with parallel gc:

图为在启动时启动,我开始播放。标记是

The graph starts at startup and I start playback. Labeled are

1)声音延迟和完整的GC,我认为这增加了老大小:

1) sound delay and full gc, I think it increased Old size:

101.646: [Full GC [PSYoungGen: 64K->0K(6848K)] [PSOldGen: 15792K->12773K(19328K)] 15856K->12773K(26176K) [PSPermGen: 15042K->14898K(23808K)], 0.2411479 secs] [Times: user=0.19 sys=0.00, real=0.24 secs]

2)我打开应用程序窗口,暂停播放。真的没什么变化,稍后它增加了伊甸园的大小。

2) I open the app window and pause playback. Nothing really changes, a bit later it increases eden size.

3)我打开窗户,并再次开始播放。

3) I open the windows and start playback again.

所以,我需要增加分配的老根的大小?我怎么做?我与运行-XX:NewRatio = 10 -XX:NewSize =10米

So I need to increase allocated Old Gen size? How do I do that? I'm running with -XX:NewRatio=10 and -XX:NewSize=10m

感谢您。

推荐答案

日志您提供太小,无法提供实时分析,但它说,它用了200毫秒做v小的老根是基本满。这意味着你的堆太小,或者你有内存泄漏。没有太多可以做,以调整GC算法,在这种情况下。因此,该答复的其余部分是你如何能获得更多的信息出来的应用程序和/或如何调整GC一旦你已经消除了内存泄漏或有更大的堆。

The log you provide is too small to provide real analysis but it says that it spent 200ms doing v little as the old gen is basically full. This means your heap is too small or you have a memory leak. There is not much you can do to tune the GC algorithm in this situation. Therefore the rest of this reply is about how you can get more information out of the app and/or how to tune GC once you have eliminated the memory leak or have a bigger heap.

在很大程度上,低暂停意味着尽你所能保持的集合,因为只有年轻的集合。

To a large extent, low pause means doing all you can to keep the collections as young collections only.

您真正需要的,当你开始和结束的写作,然后关联,与在此期间发生在JVM中的STW暂停,否则,你真的不知道什么可能导致该问题或如何严重的问题确实是记录准确

You really need to log exactly when you start and finish writing and then correlate that with the STW pauses that occur in the JVM during that period otherwise you really have no idea what might be causing the issue or how severe the issue really is.

东西我马上做;


  1. 更改日志,让你输出一行通过脚本轻松解析的(也许开始时间,结束时间,持续时间)

  2. 添加PrintGCApplicationStoppedTime和PrintGCApplicationConcurrentTime切换,让你得到的记录的每个 STW暂停,而不仅仅是GC事件

  3. 使用最新的JVM(即 6u23 ),因为已经有很多的改进,在过去的一年热点或两个所以有一点使用一老一

  4. 如果你是内存受限的,但如果可以的话,我肯定会增加堆大小你不说,40M是pretty小,所以你没有太多的空间发挥

  5. 运行与 visualgc的应用程序连接,它给出了一个较为COM $ P对正在发生的事情海事组织你把所有的不同意见了在同一时间
  6. $ phensive视图
  1. change your logging so that you output a single line easily parseable by a script (perhaps starttime,endtime,duration)
  2. add the PrintGCApplicationStoppedTime and PrintGCApplicationConcurrentTime switches so that you get a record of every STW pause and not just GC events
  3. use the latest JVM (i.e. 6u23) as there have been a lot of improvements to hotspot over the last year or two so there point using an older one
  4. You don't say if you're memory constrained but I'd definitely increase the heap size if you can, 40M is pretty small so you don't have much space to play with
  5. Run the app with visualgc connected, it's gives a more comprehensive view on what is going on IMO as you have all the different views up at one time

关键是确定你正在运行的空间和理由。这个问题的答案可能在于你的应用程序的分配模式一样,它是产生这样你通过你的小伊甸园燃烧的真的很快短命对象的负载?是tenuring门槛太高了,这样你通过生存空间乒乓效应的对象,他们得到终身不管怎样,从而迫使频繁终身GCS(慢)前?

The key thing is determine where you're running out of space and why. The answer to that likely lies in what the allocation pattern of your app is like, is it generating a load of short lived objects such that you're burning through your tiny eden really quickly? is the tenuring threshold too high such that you're ping ponging objects through the survivor spaces before they get tenured anyway and thus forcing frequent tenured gcs (slow)?

其他一些事情要牢记......

A few other things to bear in mind...


  • ICMS(增量)的目的是为在1个或2个核心机的使用,这是否说明你的机器?多少个核心,你有吗?你可能只是想删除一个选项

  • CMS确实有一个单线程阶段(INIT标记),这可能会伤害你

  • CMS通常prefers比其他收藏家更大的堆,你是pretty小

visualgc的图形编辑后加入到质疑
因为你是内存受限的,那么你需要让你有空间的最佳利用,要做到这一点的唯一途径将是通过反复的标杆......最好有一个可重复的测试。

Edit after visualgc graph added to question Since you're memory constrained then you need to make best use of the space you have, the only way to do this is going to be through repeated benchmarking... ideally with a repeatable test.


  • 您可以使用 -Xmn 来指定设置年轻一代的尺寸,其余的将给予终身。

  • 您可能要调整你的生存空间的使用,让你让他们得到更充分的他们交换前,让对象住在那里更长他们获得终身前

    • -XX:TargetSurvivorRatio = 90 设置这么一个生存空间需要90%全被复制之前,显然是有一个权衡这里的成本之间复制和使用空格

    • 使用 -XX:+ PrintTenuringDistribution 来显示每个空间的大小,事情如何,你也可以看到这一点visualgc的

    • 使用 -XX:+ MaxTenuringThreshold 来指定对象可以多少次生存的一个年轻的集合(从1生存空间复制到另一个),它是终身前,如如果你知道你只能得到短暂的垃圾或生活永远那么这个设置​​为1的东西是明智

    • you can use -Xmn to specify set the size of the young generation, the remainder will be given to tenured.
    • you might want to tune your use of the survivor spaces so that you let them get fuller before they're swapped and to let objects live there for longer before they get tenured
      • -XX:TargetSurvivorRatio=90 sets it so a survivor space needs to be 90% full before it is copied, obviously there is a trade off here between the cost of copying and using the space
      • use -XX:+PrintTenuringDistribution to show the size of each space and how things are, you can also see this in visualgc
      • use -XX:+MaxTenuringThreshold to specify how many times an object can survive a young collection (be copied from 1 survivor space to another) before it is tenured, e.g. if you know you only get short lived garbage or stuff that lives forever then setting this to 1 is sensible

      • 对于CMS这可能涉及调整 -XX:CMSInitiatingOccupancyFraction =< VALUE> ,例如设定为80,将在终身的80%入住触发CMS(注:这是一个坏的事情得到错误的,所以你可以preFER让热点管理此;设置太小,它收集往往查杀性能,将其设置过大,可能引发太晚造成计划外的全部收集与相当长的停顿时间

      • for CMS this may involve tweaking -XX:CMSInitiatingOccupancyFraction=<value>, e.g. set to 80 and it will trigger CMS at 80% occupancy of tenured (NB: this is be a bad thing to get wrong so you may prefer to let hotspot manage this; set it too small and it collects too often killing performance, set it too big and it may trigger too late causing an unscheduled full collection with correspondingly long pause time

      终于搞定探查和工作在哪里的垃圾是从,你可能会发现更容易以控制垃圾产生再浇精力投入到黑洞,可以GC优化的速度来了!

      Finally get a profiler and work out where the garbage is coming from, you might find it is easier to control the rate at which garbage is generated then pouring effort into the black hole that can be GC tuning!

      这篇关于GC优化的Java应用程序的音频的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆