lxx.Tomcat 3.55 vs cs.ags.Scarlet 1.1c
The highlighted comment was created in this revision.
The duels between lxx.Tomcat 3.55 and cs.ags.Scarlet 1.1c are throwing OutOfMemoryErrors and crashing my clients.
I´m using the standard -Xmx512m parameter in a 64-bit Hotspot JVM (Oracle/Sun).
It's strange - i have no problems in same environment: java version "1.7.0" Java(TM) SE Runtime Environment (build 1.7.0-b147) Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17, mixed mode)
Can you do some more investigations (Tomcat vs Druss & Scarlet vs Druss etc. and see in which battles memory usage will higher) to detect which robot is eats memory and, if it's Tomcat. i will try to fix it
Scarlet uses lots of memory. The longer the battle the more memory used. So battles against top bots will use the most.
Made some tests. I set -Xmx2g, tested the pairings below twice each and tracked how much memory the JVM allocates:
Tomcat vs Scarlet: 1,231,648k, 1,133,508k
DrussGT vs Tomcat: 1,047,452k, 1,043,268k
DrussGT vs Scarlet: 1,251,568k, 1,221,012k
DrussGT vs Diamond: 869,356k, 878,216k
Those numbers are maximum heaps. The actual used heaps are usually between 30% to 70% of those numbers.
So it seems both Tomcat and Scarlet use a lot of memory... hmm. I can see how a battle of one vs the other could cause problems on a memory limited machine. What are the maximum heaps used when run with -Xmx512MB ?
The reason Scarlet uses so much memory is it is just two bots that have been welded together. Each side manages its own information and systems.
Why would that matter? My gun and movement don't really share any data. I might save on the size of a few class files they share, but that's negligible (the whole JAR file is a couple hundred kb).
Unless there's two movements and two guns being initialized and/or processed, but I'd be surprised if that's how you guys have it setup, and it would be easy to fix.
I also do some investigations:
- Tomcat 3.54a vs Tomcat 3.54a: ~320 mb
- Scarlet 1.1c vs Scarlet 1.1c: ~300 mb
- Druss vs Druss: ~129 mb
- Diamond vs Diamond: ~116 mb
Numbers - it's smallest used memory showed by robocode after gc. So both Tomcat & Scarlet is memory consuming robots. I tried to optimise Tomcat, but did not get any success. Anybody have ideas, how i can detect which part of Tomcat uses most part of memory?
Try doing some heap profiling.
Are you using fasttrig? If so, how big are your arrays?
Are you using multi-dimensional arrays? It is very easy to use LOTS of memory. I have many multi-dimensional arrays, but use a lazy initialisation so that memory is only used if it gets written to first.
If you have your own kd-tree, check that it is splitting how you want it to. If it only splits one point off each time, it will get deep very quickly. This uses lots of memory, as each object needs a container and a bounding box.
Check if you have static arrays/lists that could initialised after each round.
Don't keep logs of data that won't get used again. Once it won't be used (eg at the end of the round) clear it explicitly by setting to null or calling .clear()
Check you don't have circular dependencies. Make sure you break the dependency if you delete something.
These are my first thoughts =)
- I use fast trig, but initially Tomcat eats less than 100 mb of memory
- I do not use multi-dimensional arrays
- I use Rednaxela's kD-tree and own R-tree. Splitting in r-tree is fairly well
- I keep static links only to movement & gun logs.
I tried to change double to float everywhere, but it has not any influence on memory usage. My problem, that i have 16 logs with visit data, 16 logs with hit data & 6 logs with tick data, but i can not find way, how to reduce it without APS degradation. But any way, thanks for response:)
I can increase the maximum heap in my clients, although it will change RoboRumble "rules". So I would like the opinion of the people here.
Not much to add, lots of good suggestions already, but do you keep all your waves around forever? I clear the objects between rounds because all the pertinent data is in the kd-trees. I have more than a few trees in both gun and movement, too, for what it's worth. Do you have a big object as the "value" in your trees?
"static links only to movement & gun logs" and your R-tree are what jump out at me. I would try chopping off certain parts of your bot and seeing which brings your memory usage down to earth, though some kind of heap profiler (like MN suggested) would be more elegant. =)
Off-topic: Circular dependencies shouldn't matter, at least in modern JVMs. If the only references are within a circle unreachable from the root of code execution, it will be garbage collected.
No, all waves, bullets, targets etc. are dropped out at end of each round. But yes, "value" objects are pretty big, thanks, i will think about it. I do not understand you about my R-tree.
Voidious, you are genius!:) I detect indirect static link to AdvancedRobot instance, so nothing dropping out and quick fix are frees 100 mb memory. But beautiful solve of this problem are requires big refactoring, so fixed release will be after few days
I don't know about the Nene side of the code, but on the RougeDC side, Scarlet's gun is somewhat heavy on memory. IIRC it's partially because of it's folded single-tick pattern matching. I might look at some heap profiling to see exactly how the memory usage is broken down some time, but I'm pretty busy these days.
In general, I kind of wish Java allowed the security manager to deal with memory usage, because then the robocode engine could have a 'real' rule about memory use. Instead we're just kind of left with "not too much please".
Yeah, I was wondering if it were at all possible to limit memory per bot with the Java classloaders... I guess not? It sucks that one of these two bots is probably being punished just for using more memory than average, even though it might still be well short of its fair share of 256 megs.
Though if we used per bot limits in Melee, I wonder if a lot of us would have issues. You can probably get away with far more than your "fair share" of 51 megs in Melee, since you're usually not facing 9 other memory hungry bots.
Yeah, so far as I can tell java classloaders have no control over object initialization.
Well, for melee, do keep in mind that the default heap size in the shell script that launches robocode is larger so it would be more than 51 megs per bot (can't remember exactly what off hand)
I can only think of a dedicated JVM per bot to achieve this kind of limit. This is how it is done in Java clouds out there.
The challenge comes when you try to integrate the JVMs together to calculate battle state and skipped turns.