Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (109)
games submitted by our members
Games in WIP (536)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2
  ignore  |  Print  
  Taming Java GC to prevent stutter, an in-depth post on memory management  (Read 1823 times)
0 Members and 1 Guest are viewing this topic.
Offline Zarkonnen

Senior Member


Medals: 6
Projects: 3



« Posted 2014-04-23 12:13:05 »

Spurred on by this post, here is an in-depth post on memory management in Airships.

Excerpt:

The game is written in Java, where unused data is automatically deleted in a process called garbage collection. This is nice, but comes with a big drawback: you can't control when garbage collection (GC) happens, and it can take too long.

The game runs at 60 frames per second, giving each frame a bit more than 16 milliseconds to advance the game state and redraw the screen. If GC kicks in during a frame and takes 30 milliseconds, the game stutters noticeably.

So this is something that needs fixing.

Read the rest
Offline Roquen
« Reply #1 - Posted 2014-04-23 13:43:24 »

From quick skim this all looks questionable.  About the only reason I'd object pool would be to simulate structures given that same sized object will be allocated address-first if they happen prior to the first GC.
Offline Gibbo3771
« Reply #2 - Posted 2014-04-23 13:44:35 »

Is the modern JVM and CPU so efficient that it makes object pooling almost obsolete? and that home brew object pooling is more likely to lead to performance issues rather than resolving them?

"This code works flawlessly first time and exactly how I wanted it"
Said no programmer ever
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline StrideColossus
« Reply #3 - Posted 2014-04-23 13:57:15 »

From quick skim this all looks questionable.  About the only reason I'd object pool would be to simulate structures given that same sized object will be allocated address-first if they happen prior to the first GC.

Questionable implies the OP and the blog post are a subjective viewpoint, whereas s/he has has cold, hard evidence for a bottle-neck and a means of measuring whether the solution resolves or mitigates it (or even makes it worse).  Object-pooling (or any other performance 'improvement') has it's place if there is a real performance bottle-neck due to GC, especially on mobile devices.

What do you mean by simulate structures btw?

Is the modern JVM and CPU so efficient that it makes object pooling almost obsolete? and that home brew object pooling is more likely to lead to performance issues rather than resolving them?

On the other hand this is also valid, the more complex the code the more risk you add, and ofc pooling can lead to nasty memory leaks if implemented poorly.
Offline Grunnt

JGO Wizard


Medals: 66
Projects: 8
Exp: 5 years


Complex != complicated


« Reply #4 - Posted 2014-04-23 14:19:23 »

I know the rule is "premature optimization is the root of all evil" but I think this post is actually quite nice and described a well-targeted (if possibly not that neccessary) optimization.

It would be nice, however, to measure improvement in terms of reduction in GC time spent, but that's pretty hard to do.

Offline Roquen
« Reply #5 - Posted 2014-04-23 14:53:54 »

Quote
Is the modern JVM and CPU so efficient that it makes object pooling almost obsolete?
The JVM is much better than it used to be.  Non-escaping objects and scalar replacement.  Object pooling (we're assuming HotSpot here...and ignoring android) is difficult to get right and most people will slow things down for all their extra effort and in some cases drastically slow things down (in a relative sense).

Quote
Questionable implies the OP and the blog post are a subjective viewpoint, whereas s/he has has cold, hard evidence for a bottle-neck and a means of measuring whether the solution resolves or mitigates it (or even makes it worse).
Questionable here implies: not credible.  There's no support for the cause of problem nor if the solution actually addresses the supposed problem.  Great that the apparently problem went away for OP.
Offline Zarkonnen

Senior Member


Medals: 6
Projects: 3



« Reply #6 - Posted 2014-04-23 21:25:11 »

Yeah, I'm not using object pooling at all here, I just found three places where I was allocating objects for no good reason. And yeah, I measured before and after my modifications to make sure I was actually catching the right things. And yes, it did definitely remove noticeable spikes in frame times. Smiley

As lots of people say, the GC is very good these days, and you don't often have to worry about this kind of stuff outside of Android - but in this case, the game was allocating so many objects there were actually noticeable GC pauses messing up the feel of the game.
Offline princec

JGO Kernel


Medals: 343
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #7 - Posted 2014-04-23 22:17:42 »

That should probably have been tuneable out rather than having to make code changes, I think.

Cas Smiley

Offline theagentd
« Reply #8 - Posted 2014-04-24 00:40:09 »

I'm temporarily using this abomination of a function to do some collision detection, and it generates over a gigabyte of garbage each second. Due to this I get an average of 2-3 garbage collections per second, and most of them are taking more than 7ms. The funny thing is that the fantastically amazing Hotspot should be able to get rid of every single allocation of Vector3s thanks to escape analysis, but it's not. For VM commands, I only use -server.
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
   void solveCollision(Triangle triangle){
     
      Vector3 center = new Vector3(position).add(0, height*0.5f, 0);

      Vector3 v0 = triangle.transformV0(center, diameterOverHeight);
      Vector3 v1 = triangle.transformV1(center, diameterOverHeight);
      Vector3 v2 = triangle.transformV2(center, diameterOverHeight);
     
      Vector3 point = closestPointTriangle(new Vector3(), v0, v1, v2);
     
     
      float length = point.len();
      mad(delta, point, -0.1f * Math.max(0, (wallCollisionRadius - length) / length));
      //mad(position, point, -0.1f * Math.max(0, (wallCollisionRadius - length) / length));
     //mad(velocity, point, -1f * Math.max(0, (wallCollisionRadius - length) / length));
  }
   
   public static Vector3 closestPointTriangle(Vector3 p, Vector3 a, Vector3 b, Vector3 c) {
      // Optimized version as found in book Real time collision detection
     // b - a
     Vector3 ab = new Vector3(b).sub(a);
     
      // c - a
     Vector3 ac = new Vector3(c).sub(a);
     
      // p - a
     Vector3 ap = new Vector3(p).sub(a);
     
      float d1 = ab.dot(ap);
      float d2 = ac.dot(ap);
     
      if (d1 <= 0.0f && d2 <= 0.0f) {
         return a;  
      }
     
      // p - b
     Vector3 bp = new Vector3(p).sub(b);
     
      float d3 = ab.dot(bp);
      float d4 = ac.dot(bp);
     
      if (d3 >= 0.0f && d4 <= d3) {
         return b;  
      }
     
      float vc = d1 * d4 - d3 * d2;
     
      if (vc <= 0.0f && d1 >= 0.0f && d3 <= 0.0f) {
         float v = d1 / (d1 - d3);
         
         // a + (ab * v)
        return mad(new Vector3(a), ab, v);
      }
     
      // p - c
     Vector3 cp = new Vector3(p).sub(c);
     
      float d5 = ab.dot(cp);
      float d6 = ac.dot(cp);
     
      if (d6 >= 0.0f && d5 <= d6) {
         return c;  
      }
     
      float vb = d5 * d2 - d1 * d6;
     
      if (vb <= 0.0f && d2 >= 0.0f && d6 <= 0.0f) {
         float w = d2 / (d2 - d6);
         
         // a + (ac * w)
        return mad(new Vector3(a), ac, w);
      }
     
      float va = d3 * d6 - d5 * d4;
     
      if (va <= 0.0f && (d4 - d3) >= 0.0f && (d5 - d6) >= 0.0f) {
         float w = (d4 - d3) / ((d4 - d3) + (d5 - d6));
         
         // b + (c - b) * w
        return mad(new Vector3(b), new Vector3(c).sub(b), w);
      }
     
      float denom = 1.0f / (va + vb + vc);
      float vn = vb * denom;
      float wn = vc * denom;
     
      // a + ab * vn + ac * wn
     // this can be done with one line
     
      Vector3 abvn = new Vector3(ab).scl(vn);
      Vector3 acwn = new Vector3(ac).scl(wn);
     
      // return result
     return new Vector3(a).add(abvn).add(acwn);
   }

Myomyomyo.
Offline Cero
« Reply #9 - Posted 2014-04-24 03:15:22 »

gigabytes per seconds, the fuck.

you should be chained into a room just with an atari 2600 or c64 for a month >_>

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline theagentd
« Reply #10 - Posted 2014-04-24 03:31:28 »

gigabytes per seconds, the fuck.

you should be chained into a room just with an atari 2600 or c64 for a month >_>

The funny thing is that I'm not even joking.
Quote

FPS: 107
Frame time: 6.776 ms
Render time: 0.98 ms
[GC 1219204K->10420K(1339392K), 0.0005439 secs]
Spike: 14.525339
[GC 1162420K->10476K(1272320K), 0.0012033 secs]
FPS: 123
Frame time: 7.724 ms
Render time: 1.038 ms
[GC 1108204K->10492K(1232384K), 0.0004678 secs]
Spike: 11.786918
[GC 1056508K->10452K(1171456K), 0.0012414 secs]
Spike: 17.237722

Two collections of around 950MBs per second. However, other than those 2 functions I do not generate any garbage whatsoever in my entire engine, excluding strings for printing out debugging information.

Myomyomyo.
Offline BurntPizza
« Reply #11 - Posted 2014-04-24 03:37:17 »

I wonder how useful a Javaagent or something that transforms method parameters and local variables that are of a marked type containing only primitive fields (e.g. Vectors, Colors) into those primitive fields wherever the object is referenced. Basically inlines all instance fields and methods of those types.

You can keep the OOP niceties in the source, but the bytecode is raw primitives everywhere.
You guys think that would be useful? I'll have to test whether or not it even helps small-object-heavy-code performance much first though.

Obviously it could be done manually but why when you can have an automatic tool  Pointing

I too have had multiple Gb/s going on before, crazy.
Offline theagentd
« Reply #12 - Posted 2014-04-24 04:04:06 »

Riven is working on just that; support for structs that can be on the stack.

Myomyomyo.
Offline Roquen
« Reply #13 - Posted 2014-04-24 10:42:14 »

The thing about the blog post is that it's not providing enough information to be useful to anyone beyond the author.  Here's why.

The JRE version isn't specified, we don't know if it's 32-bit or 64-bit or if any parameters have been set.  We don't know if the game is multithread or not.  All of this basic information is important.

My experience is that the majority of the time people blaming some unexpected pauses on the GC is simply because they haven't really examined the problem and in fact is its not the GC at all.  The target audience of the post will have no clue about how to identify if the GC is performing a stop-the-world event causing the observed behavior.  So the post should specify the method used (or a link to) to identify the problem.  Anyone that doesn't perform this step is simply randomly modifying code is an unreasonable attempt to correct problem which may in fact not exist.

Now the post claims to see stop-the-world events taking up to 30 ms.  That's a really long pause for a game runtime and well beyond my expectations.  Modern GCs are quite good at not requiring long stop-the-world events.  We've come a long way since semi-space collectors.  See here for overview of G1 Collector for instance.  There's tons of resources on the various GCs behaviors.  To see such a long pause I'd guess that the app might be spamming short life time small objects (which are not deduced to be non-escaping) which lead to heap fragmentation and along comes a larger allocation which can't be serviced without compacting.  If the game was otherwise performing fine then the first step should have been to tweak GC parameters rather than modifying the code.  Low risk and small time requirement even if it doesn't pay off.

I just found three places where I was allocating objects for no good reason.
Your methodology is potentially flawed. It ignores escape analysis AND you're running in the IDE.  You need a nod to escape analysis.  You have to insure that allocating methods have run at least CompileThreshold or be dumping compilations to know that you're see allocations that will actually happen after warm up.  The issue with the IDE is that it can prevent a method from being compiled (details vary) and therefore explode time requirements and allocations.

For the correction steps taken.  Nuking the "Direction" class makes sense.  It was more work to do that way in the first place and it doesn't have any upsides.  Beyond the burden it causes the GC, it introduces unnecessary indirection and significantly increases random memory reading/write...all pretty undesirable and big time sinks.  Likewise for the Color class...I silly code design choice.  Now for for-each statements.  It seems very unlikely to have a meaningful impact after warm up.
Offline matheus23

JGO Kernel


Medals: 106
Projects: 3


You think about my Avatar right now!


« Reply #14 - Posted 2014-04-24 11:18:42 »

Now the post claims to see stop-the-world events taking up to 30 ms.  That's a really long pause for a game runtime and well beyond my expectations.

Hm... I agree. theagentd had 7ms pauses with a GB of garbage... so 30 ms would mean even more garbage. I honestly don't believe the author anymore ...  persecutioncomplex

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline Roquen
« Reply #15 - Posted 2014-04-24 11:41:32 »

Don't misunderstand me.  The author could be correct about the STW event and the "fix", even though the method as stated was flawed.  And the STW pauses occurring possibly were reduced.  What I'm saying is I don't have the information to take it as a given and the post needs to be beefed up to be useful to its target audience.  Small memory allocations in java are undesirable and it's a reasonable idea to avoid them if the amount of work is roughly the same.
Offline 65K
« Reply #16 - Posted 2014-04-24 11:43:55 »

Hm... I agree. theagentd had 7ms pauses with a GB of garbage... so 30 ms would mean even more garbage. I honestly don't believe the author anymore ...  persecutioncomplex
Do both of them have the same system specs ?

Offline princec

JGO Kernel


Medals: 343
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #17 - Posted 2014-04-24 11:47:05 »

On the subject of escape analysis... I am becoming sceptical that it is working at all. theagentd's quite right in that all the allocations should be stack-allocated as they're going nowhere. Why are the heap allocs not being replaced with stack allocs? What's the magic to print out the appropriate debug information?

Cas Smiley

Offline ags1

JGO Ninja


Medals: 46
Projects: 2
Exp: 5 years


Make code not war!


« Reply #18 - Posted 2014-04-24 12:10:07 »

Hm... I agree. theagentd had 7ms pauses with a GB of garbage... so 30 ms would mean even more garbage. I honestly don't believe the author anymore ...  persecutioncomplex
Do both of them have the same system specs ?

TheAgentD has at least one awesome system fwiw... his 7ms would definitely take over 20ms on my system:

http://www.headline-benchmark.com/results/0f004cfc-1942-4647-97cd-1a3970ade933

... although maybe he's traded it in for a netbook :-)

Offline Roquen
« Reply #19 - Posted 2014-04-24 12:16:15 »

It's virtually impossible to keep up with changes.  You'd pretty much have to keep up-to-date reading the dev mailing list.  Looking through the code is a complete nightmare.  It was working reasonably the last time I explicitly looked.

Ideally use a debug build (any takers to build and maintain)? Then you could: -XX:+UnlockDiagnosticVMOptions -XX:+PrintEscapeAnalysis -XX:+PrintEliminateAllocations (well assuming they are still there...not a given)

Production options that come to mind:
+PrintAssembly to examine specific methods
+BCEATraceLevel: set to 3 (it looks like) for max info spewing
+MaxBCEAEstimateLevel: number of nested calls to inspect.
+MaxBCEAEstimateSize: max bytecode size to be considered.


The source is: /hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp
Offline DrHalfway
« Reply #20 - Posted 2014-04-24 12:28:48 »

Some of those complex collision detection functions can be a nightmare on the GC to the point where I modified some of them to use local floating point x,y,z values and static reusable Vector3 objects and manual math where applicable. A complete nightmare to write and even a bigger nightmare to maintain, it makes for some of the ugliest code, however, for sake of performance... I'm even looking for openCL alternatives for some of those functions.

Offline TeamworkGuy2

Junior Member


Medals: 10



« Reply #21 - Posted 2014-04-24 14:50:22 »

On the subject of escape analysis... I am becoming sceptical that it is working at all.

From my limited experience with the sun/oracle vm, I believe you are correct.  There's plenty of talk on the internet about escape analysis and the JVM, but I don't think there's much of anything actually implemented in the JVM. (i.e. it's mostly speculative hype Cranky).
I'd been annoyed lately that I had previously wrote a good chunk of my collision detection code to take floats, but this thread is a good reminder that it was probably a good way to design it.

I've experimented with OpenCL and on my computer (3GHz Athlon II, GTS 450) it's often faster to send large chunks of calculates to the GPU then wait around for the CPU to run them (of course there's the extra work of having to write an OpenCL program to model your calculations, but it's often worth it for performance critical sections of code).
Especially calculations involving trig and vector or matrix operations where Java's strict IEEE 754 compliance tends to hurt performance without benefiting game oriented data that can accept non-IEEE exact floating-point results.

There's a basic tutorial on LWJGL.org's wiki about OpenCL: http://lwjgl.org/wiki/index.php?title=OpenCL_in_LWJGL
Online Riven
« League of Dukes »

JGO Overlord


Medals: 752
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #22 - Posted 2014-04-24 18:09:46 »

There's plenty of talk on the internet about escape analysis and the JVM, but I don't think there's much of anything actually implemented in the JVM. (i.e. it's mostly speculative hype Cranky).
Here is some code that is actually triggering the escape analysis to enable scalar replacement:

(after warming the VM... waiting for the performance to peak, averaging the results of a few runs...)

-XX:-DoEscapeAnalysis (disabled)
1  
2  
testVec3: 3676ms
testLocals3: 652ms


-XX:+DoEscapeAnalysis (enabled)
1  
2  
testVec3: 641ms
testLocals3: 644ms


1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
   private static void testVec3(float start) {
      Vec3 vec3 = new Vec3(start, start, start);
      for(int i = 0; i < iterations; i++) {
         vec3.add(new Vec3(1, 2, 3)).mul(new Vec3(0.75f, 0.75f, 0.75f));
         vec3.add(new Vec3(1, 2, 3)).mul(new Vec3(0.75f, 0.75f, 0.75f));
         vec3.add(new Vec3(1, 2, 3)).mul(new Vec3(0.75f, 0.75f, 0.75f));
      }
   }

   private static void testLocals3(float start) {
      float vx = start;
      float vy = start;
      float vz = start;

      for(int i = 0; i < iterations; i++) {
         {
            vx += 1;
            vy += 2;
            vz += 3;

            vx *= 0.75f;
            vy *= 0.75f;
            vz *= 0.75f;
         }
         {
            vx += 1;
            vy += 2;
            vz += 3;

            vx *= 0.75f;
            vy *= 0.75f;
            vz *= 0.75f;
         }
         {
            vx += 1;
            vy += 2;
            vz += 3;

            vx *= 0.75f;
            vy *= 0.75f;
            vz *= 0.75f;
         }
      }
   }



So, yeah, it works... but it's rare to the point of being damn lucky to see it in a real-world case.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Online Riven
« League of Dukes »

JGO Overlord


Medals: 752
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #23 - Posted 2014-04-24 18:47:42 »

Due to this I get an average of 2-3 garbage collections per second, and most of them are taking more than 7ms.

[GC 1219204K->10420K(1339392K), 0.0005439 secs]
[GC 1162420K->10476K(1272320K), 0.0012033 secs]
[GC 1108204K->10492K(1232384K), 0.0004678 secs]
[GC 1056508K->10452K(1171456K), 0.0012414 secs]

Not quite 7ms (your frame time was 7ms), but maybe it was a poor sample set. It's actually not so surprising that the GC can clean this up within one millisecond, because it really doesn't have to do much. As you know, the GC doesn't collect any garbage, it merely traces 'live' object references and moves groups of reachable objects to a new region in the heap, and flags everything else 'free' (a heap at a time, since the GarbageFirst collector). Your use case seems to be the ideal case for the latest collector. Having said that, escape analysis would give you your 1ms back Smiley

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline TeamworkGuy2

Junior Member


Medals: 10



« Reply #24 - Posted 2014-04-24 22:15:54 »

Here is some code that is actually triggering the escape analysis to enable scalar replacement:
(after warming the VM... waiting for the performance to peak, averaging the results of a few runs...)
...
So, yeah, it works... but it's rare to the point of being damn lucky to see it in a real-world case.

Well good to know, I tend to make a fool of myself when I mention my experiences without researching first Tongue
Offline RobinB

JGO Ninja


Medals: 44
Projects: 1
Exp: 3 years


Spacegame in progress


« Reply #25 - Posted 2014-04-24 22:33:55 »

I notice (huge) performance improvements when pooling big stuff like bytebuffers.
So in this situation it could be handy, or am i wrong?
Offline theagentd
« Reply #26 - Posted 2014-04-24 23:21:09 »

Not quite 7ms (your frame time was 7ms), but maybe it was a poor sample set. It's actually not so surprising that the GC can clean this up within one millisecond, because it really doesn't have to do much. As you know, the GC doesn't collect any garbage, it merely traces 'live' object references and moves groups of reachable objects to a new region in the heap, and flags everything else 'free' (a heap at a time, since the GarbageFirst collector). Your use case seems to be the ideal case for the latest collector. Having said that, escape analysis would give you your 1ms back Smiley
Right, bad example output. >_> The real problem isn't the stop-the-world pauses, but the interference the garbage collection has on my multithreaded engine. Although the stop-the-world time is pretty low, the garbage collectors take up quite a bit of time on multiple CPU cores. Here's some more interesting output:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
Frame time: 7.473 ms
Render time: 0.91 ms
[GC 100099K->13611K(259072K), 0.0005243 secs]
-Spike: 22.331825
[GC 98091K->13667K(257024K), 0.0005799 secs]
-[GC 96099K->13611K(273920K), 0.0074180 secs]
-Spike: 44.528187
[GC 112939K->13747K(293888K), 0.0004801 secs]
[GC 133043K->13795K(317952K), 0.0005644 secs]
[GC 157155K->13795K(346624K), 0.0004909 secs]
[GC 185827K->13843K(381440K), 0.0005881 secs]
[GC 220691K->13843K(422912K), 0.0005573 secs]
[GC 262163K->13899K(472576K), 0.0005559 secs]


Frame time screenshot:

A normal frame takes 7.473 ms to render (CPU time). The first spike is the 22.331825 ms spike, the second one is the 44.528187 ms spike as seen in the graph and the output. Also note the 7.4ms GC spike. The frame time is also suffering from much more micro-stuttering than usual. The graph should be pretty much flat (except for the GC spike), not this jumpy.

Myomyomyo.
Offline Roquen
« Reply #27 - Posted 2014-04-25 07:46:53 »

I notice (huge) performance improvements when pooling big stuff like bytebuffers.
So in this situation it could be handy, or am i wrong?
Special case reuse of objects will be manageable for most people so yeah this is a more than reasonable thing to do.

Ages ago in one of our "what features does java need" threads I talked about contracts and one of the examples I gave was one for the compiler:  @NoReference.  Which would allow a programmer to explicitly state where reference cannot escape.  This suggestion requires the verifier to make some trivial checks and then EA doesn't have to deduce anything about the marked reference.  There are non-escaping objects that the deduction will never catch (because it would take too much time and/or memory) but the programmer (can) know cannot escape.  win.
Offline princec

JGO Kernel


Medals: 343
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #28 - Posted 2014-04-25 10:09:32 »

AIUI from the Excelsior guys escape analysis is linear-time to calculate so I don't think there's a case where it'll take "too long" to detect escapes, which means I think that directive might be redundant and the real problem is just that the Hotspot implementation either doesn't work right or maybe it just needs some more aggressive tuning parameters eg. bytecode depth increasing - perhaps the default is unrealistically shallow (I'm thinking here that they've optimised the server VM for its most usual use case which is EJB deployments where they probably don't care quite so much about small 20ms spikes in GC as we game devs do).

BTW anything with a finalize() method on it or that is referenced by any form of *Reference causes GC on such objects to "slow down" by like a factor of "100" (random high figure selected from thin air) as such objects fall outside the usual usage pattern of Java objects. This means DirectByteBuffers in particular, but if you're constructing and forgetting DirectByteBuffers every frame you're not using them as intended anyway.

Cas Smiley

Offline princec

JGO Kernel


Medals: 343
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #29 - Posted 2014-04-25 10:12:28 »

(I'm thinking here that they've optimised the server VM for its most usual use case which is EJB deployments where they probably don't care quite so much about small 20ms spikes in GC as we game devs do)
Further musing on this... they have probably run some profiling on some "test cases" and determined that the extra compilation time spent doing escape analysis eventually overtakes the total time spent in GC beyond a certain point, and beyond that it's simply more sensible to let the latest GC do its thing. Just speculation, mind.

FWIW I've had recent experience of the G1GC in Battledroid, and it cut my framerates in half. So there we go.

Cas Smiley

Pages: [1] 2
  ignore  |  Print  
 
 

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CogWheelz (18 views)
2014-07-30 21:08:39

Riven (23 views)
2014-07-29 18:09:19

Riven (15 views)
2014-07-29 18:08:52

Dwinin (12 views)
2014-07-29 10:59:34

E.R. Fleming (33 views)
2014-07-29 03:07:13

E.R. Fleming (12 views)
2014-07-29 03:06:25

pw (43 views)
2014-07-24 01:59:36

Riven (43 views)
2014-07-23 21:16:32

Riven (30 views)
2014-07-23 21:07:15

Riven (31 views)
2014-07-23 20:56:16
List of Learning Resources
by SilverTiger
2014-07-31 18:29:50

List of Learning Resources
by SilverTiger
2014-07-31 18:26:06

List of Learning Resources
by SilverTiger
2014-07-31 13:54:12

HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!