如何避免在Java游戏垃圾收集延迟? (最佳实践) [英] How can I avoid garbage collection delays in Java games? (Best Practices)

查看:87
本文介绍了如何避免在Java游戏垃圾收集延迟? (最佳实践)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是为Android平台的Java性能优化的互动游戏。有一次,有绘画和互动的垃圾收集打嗝。通常它是一个第二的不到十分之一,但有时也可以是一样大的200ms上非常慢的设备

I'm performance tuning interactive games in Java for the Android platform. Once in a while there is a hiccup in drawing and interaction for garbage collection. Usually it's less than one tenth of a second, but sometimes it can be as large as 200ms on very slow devices.

我使用的是DDMS探查器(Android SDK的一部分)来搜索出在我的内存分配来自和我内心的绘图和逻辑回路切除它们。

I am using the ddms profiler (part of the Android SDK) to search out where my memory allocations come from and excise them from my inner drawing and logic loops.

最坏的罪犯一直喜欢做短的环路,

The worst offender had been short loops done like,

for(GameObject gob : interactiveObjects)
    gob.onDraw(canvas);

在环路被执行每一次有一个迭代分配。我使用的是现在我的对象数组(的ArrayList )。如果我想在一个内部循环树或哈希我知道,我必须要小心,甚至重新实现使用Java集合框架,因为我负担不起额外的垃圾收集他们,而不是。可能会出现的,当我在看优先级队列。

where every single time the loop was executed there was an iterator allocated. I'm using arrays (ArrayList) for my objects now. If I ever want trees or hashes in an inner loop I know that I need to be careful or even reimplement them instead of using the Java Collections framework since I can't afford the extra garbage collection. That may come up when I'm looking at priority queues.

我也有,我想显示成绩和进步使用 Canvas.drawText 麻烦。这是不好的,

I also have trouble where I want to display scores and progress using Canvas.drawText. This is bad,

canvas.drawText("Your score is: " + Score.points, x, y, paint);

由于字符串字符阵列和 StringBuffers 将被分配到各地,使其工作。如果你有几个文本显示项目和运行框架60次,第二次是开始积少成多,并会增加你的垃圾收集打嗝。我觉得这里最好的选择是保持的char [] 阵列和德code你的 INT 手动把它和连接字符串到开始和结束。我想听到的话,有什么东西干净。

because Strings, char arrays and StringBuffers will be allocated all over to make it work. If you have a few text display items and run the frame 60 times a second that begins to add up and will increase your garbage collection hiccups. I think the best choice here is to keep char[] arrays and decode your int or double manually into it and concatenate strings onto the beginning and end. I'd like to hear if there's something cleaner.

我知道一定有其他人在那里处理这个。你如何处理它,什么是陷阱,你已经发现了对Java或Android的交互方式运行的最佳做法?这些GC问题都足以让我错过手动内存管理,但不是很多。

I know there must be others out there dealing with this. How do you handle it and what are the pitfalls and best practices you've discovered to run interactively on Java or Android? These gc issues are enough to make me miss manual memory management, but not very much.

推荐答案

我对Java的手机游戏......避免GC'ing对象(反过来的的触发器的最佳方式工作该GC在一个点或那样的的杀人游戏的perfs)仅仅是为了避免在首位的游戏主循环创建它们。

I've worked on Java mobile games... The best way to avoid GC'ing objects (which in turn shall trigger the GC at one point or another and shall kill your game's perfs) is simply to avoid creating them in your main game loop in the first place.

有没有干净的方式来处理这一点,我先举个例子...

There's no "clean" way to deal with this and I'll first give an example...

通常情况下,你有,比如说,4球在屏幕上,在(50,25),(70,32),(16,18),(98,73)。好了,这里是你的抽象(简化为了这个例子中):

Typically you have, say, 4 balls on screen at (50,25), (70,32), (16,18), (98,73). Well, here's your abstraction (simplified for the sake of this example):

n = 4;
int[] { 50, 25, 70, 32, 16, 18, 98, 73 }

您啪的第2个球而消失,你的INT []变成:

You "pop" the 2nd ball which disappears, your int[] becomes:

n = 3
int[] { 50, 25, 98, 73, 16, 18, 98, 73 }

(注意如何,我们甚至不关心清洗的第4球(98,73),我们简单的跟踪,我们已经离开球的数量)。

(notice how we don't even care about "cleaning" the 4th ball (98,73), we simply keep track of the number of balls we have left).

手册对象的跟踪,可悲。这它是如何做的最新表现良好的Java游戏是出在移动设备上。

Manual tracking of objects, sadly. This how it's done on most current well-performing Java games that are out on mobile devices.

现在的字符串,这里就是我想要做的:

Now for strings, here's what I'd do:

    使用
  • 在游戏初始化,predraw的的drawText(...)的*只有一次*数字0到9,你保存在的BufferedImage [10] 阵列。
  • 在游戏初始化,predraw一次的你的分数是:
  • 如果在你的分数是:的真正需要重新绘制(因为,比如说,它是透明的),然后从您的pre-存储的BufferedImage重绘
  • 环路来计算得分的数字和添加,之后的你的分数是:的,每个数字手动逐一(由每个时间复制相应的数字(0到9)从你的的BufferedImage [10] 在这里你pre-保存它们。
  • at game initialization, predraw using drawText(...) *only once* the numbers 0 to 9 that you save in a BufferedImage[10] array.
  • at game initialization, predraw once "Your score is: "
  • if the "Your score is: " really needs to be redrawn (because, say, it's transparent), then redraw it from your pre-stored BufferedImage
  • loop to compute the digits of the score and add, after the "Your score is: ", every digit manually one by one (by copying each the time the corresponding digit (0 to 9) from your BufferedImage[10] where you pre-stored them.

这给你最好的两个世界:你得到重用的 DrawText的(...)的字体和你在你的主循环创造正好为零的对象(因为你的回避调用的 DrawText的(...)的本身的可以的很好是crappily发生,好了,不用废话)。

This gives you best of both world: you get the reuse the drawtext(...) font and you created exactly zero objects during your main loop (because you also dodged the call to drawtext(...) which itself may very well be crappily generating, well, needless crap).

另外一个利这个的零对象创建绘制分数的是,细心的图像缓存和重新使用的字体是不是真正的手动对象分配/释放的,它实际上只是小心缓存。

Another "benefit" of this "zero object creation draw score" is that careful image caching and reuse for the fonts is not really "manual object allocation/deallocation", it's really just careful caching.

这是不是干净,这不是好的做法,但是这是它是如何在顶尖的手机游戏做(比如说,Uniwar)。

It's not "clean", it's not "good practice" but that's how it's done in top-notch mobile games (like, say, Uniwar).

和速度非常快。该死的快。不是更快的什么的包括创建对象。

And it's fast. Darn fast. Faster than anything involving the creation of object.

PS:其实,如果你仔细看一些手机游戏,你会发现,往往字体其实并没有系统/ Java的字体,但专为每款游戏(在这里我只是给你一个做完美的像素字体例如如何缓存系统/ Java的字体,但很明显,你也可以缓存/重用像素完美/位图字体)。

这篇关于如何避免在Java游戏垃圾收集延迟? (最佳实践)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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