4 ms·
Don't worry, Microsoft will fix it when it's rewritten in C#. :) I kid, I kid <I hope>. Actually, I wish Minecraft had been open-source like Notch was original
by cromwellian 12y ago
Don't worry, Microsoft will fix it when it's rewritten in C#. :) I kid, I kid <I hope>.
Actually, I wish Minecraft had been open-source like Notch was originally talking about. The community could fix most of these issues, in lieu of introducing new features.
- MichaelGG 12y agoAccording to the post, the problem is passing objects as parameters instead of individual values as separate arguments. Each time they do this, that allocates an object. C# has value types, unlike Java. So the BlockPos structure wouldn't need an allocation, just some stack space.
- bhouston 12y agoWhy the heck did they decide to pass around objects instead of parameters? This sounds weird, sort of like an internal a framework that has gone too far.
- eropple 12y agoIt sounds like something coming from a really weird misunderstanding of Java and its perf characteristics. For most Java projects, immutable, semantically-useful objects make a lot of sense (indeed, Scala does this all over the place). For a game, not so much; you're going to end up object-thrashing all day and unlike on the web you have very hard latency requirements that make this extremely undesirable.
- e12e 12y agoI've not really looked much at how java handles memory, but I thought the basic pattern for all Objects was pass-by-reference: the method gets a pointer to the object. Is it a means of guaranteeing immutable access that such a pointer becomes a pointer to a (deep?) copy of the object allocated on the heap?
- eropple 12y agoThey're pass-by-ref, but if you have to create an object every time you want to refer to a block, anywhere, you're gonna have a bad time. With mutable objects, like libgdx does for its vector classes and similar, you can do object pooling to reuse them and avoid the GC thrash.
- e12e 12y agoI thought the general idea with a voxel/block world was that "world state" could/should be a 3d array/"matrix" of blocks (possibly with empty blocks collapsed to null references)? So of you're using objects, that's what you'd put in the array. I can see how an array of 8 bit ints (basically an enum of block type) would be a lot more compact and/or that some kind of packed representation would be (on the face of it) vastly more compact - but if that's what they're doing, wouldn't it make much more sense to stuff the abstraction into static methods (functions) rather than marshall (full) objects left and right?
- eropple 12y agoYeah, now how do you define a location in that voxel space? In Java, you can pass XYZ and parameters or you can create an object (in this case, BlockPos). Every object is heap-allocated, and the heavy use of transitory objects (like, say, every frame) creates a lot of garbage that'll need to be cleaned up.
- e12e 12y agoRight. I was just thinking that the most straightforward, naive, approach in java was to have an array of Objects (so you'd pass around those references), and if you were going to pack everything into a more "primitive" structure (like an array of int8s) it wouldn't make much sense to marshal those into objects, but rather go for a more traditional data structure approach and stuff the complexity into some static methods... or failing that at least use some local, long-lived "proxy"-objects with raw attributes: MyVoxel here = new MyVoxel(x,y,z,normal...); MyVoxel there = new MyVoxel(); // "null" voxel for // some x,y,z here.xyz(x, y, z); for // some offset_x,y,z there.xyz(x+1,...) here.distance(there) // or whatever Which I suppose is essentially caching objects. The idea of having lots of "new" in (inner) loops... just sounds really weird. Even outside of sub-ms-game-land. I'm guessing even assigning (as opposed to just using) primitive values to an object probably can have some nasty effects wrt. needless copying -- but it should probably be a lot more predictable than a GC hit -- possible to optimize, and might not trash CPU cache as bad as one might fear. I suppose it's quite easy to end up in a mess when trying to do a straightforward rewrite from a static/non-java-oo style to a more java-oo-style -- without some careful thought as to what's actually going on... [edit: looking at teamonkey's reply further down... I think I've seen some code in this style, creating lots of short-lived objects. Is it considered idiomatic java, or an anti-pattern? (or both? ;)]
- MichaelGG 12y agoSounds a lot cleaner to me to pass around Point or BlockInfo than separate xyz. Imagine a function that determines which of two blocks wins when sitting on top of a third one. 3 args instead of 12 or something. I can quickly see it being cleaner. It's just a sad effect that the JIT is too stupid to optimize. There's no good reason dist(pointA, pointB) should be any slower than dist(ax,ay,az,bx,by,bz).
- bradleyland 12y agoJava takes OO to heart, so when you see that you're passing around (x,y,z) a lot, you're probably also doing a lot of similar things with (x,y,z) inside your method definitions. The OO answer to this is to wrap (x,y,z) in a class; in this case BlockPos. We haven't seen enough of the code to really say whether any of this is even remotely sane, but we can say that creating tons of immutable objects that are temporary and short-lived is going to have a performance impact. So at best, this sounds like an enhancement to API utility involving a trade-off against performance, and at worst incompetent programming. I'm betting on the former, only the performance trade-off may have been more severe than anticipated. It's also worth keeping in mind that this is probably a "death by a thousand cuts" scenario where this specific case isn't the root cause of the entire performance problem, but one of the contributors.