View source for Talk:XanderCat

From Robowiki
Revision as of 22:43, 25 May 2011 by Skotty (talk | contribs) (responded to GrubbmGait)

Talk:XanderCat
Jump to navigation Jump to search

Congrats on breaking the 50% barrier. Seems that you have the planning of your bot on scheme, now it's just the translation into the right code. One small remark: You don't have to have 'zillions of versions' present in the rumble, the details of older versions still are available when not in the participants list anymore. Comparisons between two versions are quite easy to do like [1] . Just click on your bot in the rankings, then the details and a few older versions are shown. Good luck with your further development! --GrubbmGait 08:37, 25 May 2011 (UTC)

Thanks GrubbmGait, though I'm not sure how much praise I deserve for being officially average. :-P I'm trying out a slightly revised version today, version 2.1. No major component changes, but it modifies the bullet firing parameters, driving parameters, some segmentation parameters, and has improved gun selection. Skotty 20:43, 25 May 2011 (UTC)

Contents

Thread titleRepliesLast modified
Wacky Version Problems with RoboJogger/RoboRunner104:29, 3 April 2017
New Garbage Collection Mitigation Strategy415:16, 26 October 2013
Garbage Collection and Skipped Turns2320:54, 24 October 2013
Shielding Success Rates Mystery2700:49, 28 February 2013
First page
First page
Previous page
Previous page
Last page
Last page

Wacky Version Problems with RoboJogger/RoboRunner

Forgot how slow this can go. :-/ I've been trying all day to record some new statistics using the Robocode means for saving file to disk, but I'm getting really bizarre version issues. I've been updating my robot version with each change -- 12.8.1, then 12.8.2, then 12.8.3. Each time I clear robot cache, package the new version, clear the old stats file that was saved from the prior version (as in, physically delete it, so I know the old stats are gone), and then run a new challenge with the new version. However, I keep getting garbage from older versions coming out in the results. Sometimes mixed, like it's randomly running different versions.

I've started trying to record the version information to the stats file each battle. I keep seeing this in the saved information:

Old: xander.cat.XanderCat 12.8.1*; New: xander.cat.XanderCat 12.8.7.

What that means, is it thinks the last battle was run with 12.8.1*, even though the entire challenge was run with 12.8.7. And that may actually be sort of true, because I'm getting some info in the stats file that I removed around version 12.8.4 but it shows up again, like it ran an older version for one or more of the prior battles.

At the moment, I'm totally confused by it. I'm not even sure how to debug it further at the moment.

Skotty (talk)04:13, 3 April 2017

As sometimes happen, writing about it made me figure it out. What was happening, that I didn't realize, was that the newer version of Robocode has an option to include the data files in the packaged robot, which is checked by default. So it was packaging data from an old version of XanderCat that I had run from Eclipse, which was totally screwing with my robot frameworks attempt to manage the robot data.

If you want to save any persistent data to the data files, make sure you uncheck the option to include data when packaging the robot!

Can't believe how much time I wasted figuring that out today.

Skotty (talk)04:29, 3 April 2017
 

New Garbage Collection Mitigation Strategy

I spent some time working on a system to pool frequently used objects in an attempt to mitigate the first round garbage collection problem my robot suffers from. My first attempt had some merit, but the changes involved are a lot more significant than I would like. I'm just not happy with it.

Recently, however, I came up with another idea that may be much simpler and effective. However, I still need to test out the idea. Instead of managing object pools, what if I just dump old objects into a "waste basket" that hangs onto those objects and releases them at a controlled pace -- probably slowly at first and releasing them faster as the rounds progress and the waste basket begins to fill up. Or perhaps empty the waste basket at safe times, like the end of a round or at times when XanderCat has a solid advantage already. This would use more memory overall but may be far simpler and less error prone. I'm going to sideline my prior pooled objects work and try this route for XanderCat 12.7.

Skotty (talk)17:56, 24 October 2013

Sounds like it has potential, but isn't your primary GC issue at the very beginning of the match? Or did we already conclude that was intractable?

Voidious (talk)19:52, 24 October 2013
 

That might work, but I have my doubts. Unless you're calling System.GC() all the time it seems likely that the garbage collector will wait for a bunch to pile up and do it in bursts regardless of how controlled of a pace you release your references at (and calling System.GC() all the time would also likely cause it's own issues). I'd say the real solution needs to involve just plain not using so many tiny objects in the first place.

(It's kind of one of my pet peeves about Java, that the language encourages extensive object use, yet if you use it "too extensively" the code will have performance issues to due excessive allocation/deallocation overhead. In some languages (such as C++) one has the option of combining multiple objects into the same block of allocation, but because all object instances are references in Java there's no such luxury, ironically meaning that high performance java code needs to use simpler/fewer OOP structures than high performance C++ code in order to match the performance)

Rednaxela (talk)17:20, 25 October 2013

Also a pet peeve of mine about Robocode at this point. It has a really strict time limit per turn with a programming language that doesn't give you much control at that small of a scope. And even if it did, a rolling average would be soooo much nicer, and skipped turns are such a burden to deal with.

Voidious (talk)18:28, 25 October 2013
 

Automated garbage collection is about getting the job done faster/cheaper. Machine code always has more potential for performance than any language and/or paradigm. But in practice, due to overwhelming complexity issues, lower level languages tend to deliver worse software overall.

If you want high performance Java, increase the size of the heap, and/or change the ratio between regions, which solves 99% of garbage collection issues.

We could make it standard in RoboRumble to have a heap optimized for real-time. Using "-Xmn511m -Xmx512m" or "-Xmn1023m -Xmx1024m" in roborumble.bat would do the job very well. Not as fun as programmatic object pooling systems though.

MN (talk)15:16, 26 October 2013
 
 

Garbage Collection and Skipped Turns

Starting a new thread to discuss my efforts to deal with the skipped turn issue that is apparently related to garbage collection eating up allowed run time. This was previously discussed in thread "Shielding Success Rates Mystery", for anyone who wants to see where it all started.

I purposely did not contribute to the rumble over the last few days after the pairings for XanderCat 12.6 were lost. I originally ran many of the original pairings on my PC that does not have the skipped turns issue. Most of the re-run pairings were likely run by Voidious, whose system does exhibit the skipped turns issue.

The difference between the two is quite significant. With clients that don't exhibit the skipped turns issue, XanderCat achieved an APS of 87.7. With clients that do exhibit the shipped turns issue, XanderCat achieved an APS of 86.5. The difference -- 1.2 APS -- is quite significant. With the current rumble participants, it makes the difference between 5th and 8th place.

Most of the difference is due to the skipped turns causing the bullet shielding system to fail much of the time. But likely the skipped turns in general -- ignoring the bullet shielding -- also contribute a small amount.

I had previously fixed a few performance bottlenecks to make XanderCat run quite a bit faster (v 12.3), with much lower turn time peaks, but this only achieved a marginal improvement. I now need to shift to figuring out how to reduce the amount of garbage my framework apparently creates. This is not a real easy problem to address, because it is a very unique Java problem that rarely ever needs to be addressed in the real world, so there is not a lot of information or research available online to help on this.

I think one thing I can do is to eliminate as many intermediate local variables as I can. For example, variables with only method scope that are used to break something into multiple easier to maintain steps. These extra method scope variables may be contributing to the garbage collection, especially in the first round. Eliminating them may help to fix the problem, but at the expensive of either combining multiple lines together into more complex lines or making the variables have a wider than necessary scope (declaring them as part of the class), thus eating more memory overall but eliminating the possibility of it triggering garbage collection.

I don't know if these steps will help, but I will probably give it a try. I am also not sure if there are other ways to reduce garbage collection, but maybe I will come across some other ideas. I may actually create a second branch in my source tree for this work, something I never thought I would do for Robocode. I want to keep the current version, as I think it will constitute better code and perhaps someday the garbage collection issue will be addressed by changes to Robocode itself; but if my garbage reduction efforts work, for now I will operate off of a garbage reduced branch.

Skotty23:43, 3 April 2013

This seems like a really crappy thing to push onto you as a bot author. I do think our time is probably better spent coming up with a proposal to change Robocode itself and submitting that (as idea, design, or code) to Fnl. There could be a very simple and elegant solution that would work, like "allow 10x the CPU constant for the first 100 ticks". (Disabling CPU limits in first 100 ticks seems problematic, since you want to at least interrupt bots that hit infinite loops.) Another idea is having Robocode run its own GC cycle right before the match starts, in case bots are being penalized for GC of the game engine.

I'll try to get to another round of tests and find out how much I need to raise the CPU constant to get normal performance out of XanderCat.

Voidious00:39, 4 April 2013
 

I've had to deal with this quite a bit when writing games in c#. Similar to Java the GC can case obvious stalls. The easiest way is to stop calling the "new" function at run time by using pooling. For instance at the start of a match, or a round create a container object which contains N pooled objects which you know you create often, eg wave objects. At the point you wish to use one, take it from the pool, initialise it, use it, then return it to the pool when finished at any point later on.

Because you have not called new, and then nulled the object, the memory used does not go up, it stays constant, thus no GC is run. It's obviously impractical to pool everything so you just do the worst offenders which are things that you create often and throw away.

Wolfman01:30, 4 April 2013

That seems like a great approach. And you can even create the pools in a static block, which I'm pretty sure runs before the match starts and won't count against any of your CPU time.

Voidious04:44, 4 April 2013
 

Speaking of static blocks, I've noticed that they get run on Robocode/rumble startup for every single bot, which is partly why it takes so long to start when there are lots of bots in the /robocode/robots directory. I also suspect that code in static blocks isn't subject to the security manager, since it can print to the main console. Does somebody feel like writing a test bot to see if this theory is correct?

Skilgannon10:56, 4 April 2013
 

Local variables are stored in the stack and not the heap, so they don't affect garbage collection.

You should look after "new" abuse, like Wolfman said. Although sometimes the instantiation is implicit and simply searching for the "new" keyword doesn't always work.

There are heap profiling tools which locate automatically where too many objects are being instantiated.

MN04:33, 4 April 2013
 

Local variables are stored on the stack but any time you use new it will go on the heap afaik:

public void MyFunc(Object a) {

  Object b = a; // Variable b is on the stack, pointing at a.
  b = new Object(); // Memory allocated on heap, referenced by variable b on the stack

}

This is my understanding of it. Please correct me if I am wrong!

Wolfman07:57, 4 April 2013
 

This is correct.

My understanding of the snippet above is that you have 3 variables. 2 local in the stack (references "a" and "b") and 1 in the heap (Object instance).

Some variables stay in the stack only, like primitives (double, float, int...).

MN15:46, 4 April 2013

Where would a primitive array like an int[] end up?

Tkiesel16:17, 4 April 2013

Java treats an array as an object, so on the heap.

However, these days the JVM is more intelligent than you guys are giving it credit for, eg. it has Escape Analysis to determine if objects should be put on the stack if they stay local.

Skilgannon16:25, 4 April 2013

You do not have permission to edit this page, for the following reasons:

  • The action you have requested is limited to users in the group: Users.
  • You must confirm your email address before editing pages. Please set and validate your email address through your user preferences.

You can view and copy the source of this page.

Return to Thread:Talk:XanderCat/Garbage Collection and Skipped Turns/reply (14).

I've actually been debating writing a Robocode simulator to make robot profiling much easier. What it would do is to pretend to run a robot battle with your robot against either another opponent, or perhaps some imaginary robot, using a combination of mock objects and simulation. It would run without any security at all, no sandbox, nor would their be skipped turns, so you would only want to run it with trusted robots. But it would be much easier to run a profiler against. The simulated battle may not be a perfect simulation, but as long as it's close, it should work and be useful.

Skotty23:06, 5 April 2013
 

When I do profiling in Robocode, I run a battle of a bot against itself. Then I filter the results by package so engine data is filtered out and only data from my bots appear in the profiling report.

MN01:10, 6 April 2013
 
 

Yes. However anything that you are creating during a function and keeping hold of for a few frames and then releasing is going to be allocating on the stack. Stuff like "Wave" objects, "Bullet" objects or whatever else you use in your bot will cause GC stalls if you create lots, use for a while and then null. This is where the pooling comes into force. I would definitely recommend pooling objects such as waves etc if you are having trouble with stalls and then go from there.

-wolfman

Wolfman16:32, 4 April 2013
 

See, my bot always had a skipped turns problem, and now you're giving me a possible solution. You're drawing me right back in to wanting to start Robocoding again, dangit! *laughing*

Tkiesel16:39, 4 April 2013

Yes, yes, come to the dark side, make your code ugly but fast, like mine :-p

Skilgannon16:42, 4 April 2013
 

Although its more likely that the stall is caused by your code running too slow rather than blaming it on the GC imho. Can you use eclipse to profile execution and memory of robots? Anyone know? If so a wiki page would be lovely :)

Wolfman17:16, 4 April 2013
 
 

Arrays are objects in java:

public void func() {

  int[] myArray; // myArray variable on the stack
  myArray = new int[5]; // Array object allocated on heap, referenced by myArray variable on the stack

}

Note that member variables of objects are obviously going to take up memory on the heap not the stack - eg if you have 30 primitive member variables (ints, doubles etc) of a class and call new on that class, it will take up more memory allocation than a class that has 1 primitive member variable.

However allocating 30 local primitive variables during a function call allocates those primitive types on the stack alongside you local member reference variables.

Wolfman16:28, 4 April 2013
 

While I am not the saddest person here that this has happened to you (as my robot is right above yours in the rankings with only a little APS between it and yours). But I know I would hate it if this happened to me. However I have tried to design things from the ground up in more recent robots to limit object creation and destruction.

At one point I even reused old objects (aforementioned pooling) instead of creating new ones. That didn't make it into the current version however.

Chase20:54, 24 October 2013
 

Shielding Success Rates Mystery

I started doing some research on my shielding success rates. I started with a small set including Virus, Seraphim, Hydra, Crusader, and Engineer. I did a first test run of 20 seasons. Shielding success occurred on 20/20, 19/20, 20/20, 20/20, and 13/20 seasons respectively. I know why it's not perfect for Engineer, but the other 4 are the mystery. In the RoboRumble, my success rates on the first 4 are currently 5/8, 5/8, 5/8, and 4/7 respectively.

None of the Rumble losses were run by my machine. But all of them were run using client 1.7.3.0. Losses only occurred when run by Voidious and DivineOmega. I'm guessing there is something common about the machines used by you two that is key. Are you both perhaps running under Linux? Also, what version of Java? I need to replicate one of your machines as closely as possible to explore the problem further.

Skotty13:06, 15 February 2013

Maybe their clients are skipping turns. Missed scans hurt bullet shielding a lot.

MN14:40, 15 February 2013

If they want to check that, they sort-of can. It only reports on the last battle that it happened, but if my robot has any skipped turns, it will write a file xander.cat.XanderCat_SkippedTurns.txt file into it's data directory that has the number of skipped turns printed in it. It's not as useful as it could be since it just reports on the last battle that it happened on, but could be worth a check.

Skotty15:55, 15 February 2013
 

Are the tests you run also using 1.7.3.0? (BTW, I'm doing some major bullet-shielding-suffering at the moment...)

Skilgannon16:35, 15 February 2013

Yes. I run 1.7.3.0 as well.

Skotty17:37, 15 February 2013
 

My rumble clients are on a Core i7-3770 running Ubuntu 12.04 (32-bit), and I think OpenJDK 6 (will check when I get home). Now that you mention it, I recall a similarly huge discrepancy for the original BulletCatcher on an old AMD Ubuntu machine I was using as a rumble client (couldn't find the discussion though). I chalked it up to the different JVM or even the CPU and ended up just retiring the machine as a rumble client, since it was a fraction of my overall CPU power.

My first guess is that when two bullets are close enough to parallel, one JVM's Line2D says they intersect and another doesn't. I actually have Ubuntu 32-bit, 64-bit, and Windows 8 64-bit all on that same machine, so I should be able to do some decent tests for you with only the JVM or OS as a variable.

Voidious17:45, 15 February 2013

When the opponent is moving, my robot stands perfectly still (it rotates but doesn't move position). Thus, I haven't verified it, but the two bullets should be perfectly parallel, and this is likely handled differently on different JVMs as Voidious was talking about. However, when both robots are standing still, my shielding shot will miss, so my robot will move slightly when firing a shielding shot against a stationary opponent. I haven't had enough time to figure out what causes this, but I wonder if the answer will give any further clues. I did it this way because it worked, but more investigation is required for me to figure out why.

I could play around with moving slightly for every shielding shot (and moving back right after the shot). I tried this briefly, but found standing still to be more reliable on my machine. But maybe I can tweak it to where it works as well as standing still. If I can, I bet it would avoid the problem.

I will likely need a few more days to play around with this further. In the meantime, if Voidious has time to try out the other JDK, that would answer another piece of the puzzle.

Skotty18:54, 15 February 2013

Standing still works because the enemy gun rotation happens after the bullet is fired, so they shoot from a position of 1 tick ago but use their aim from 2 ticks ago. So if they are moving their angle to you changes and they don't quite shoot at your centre, meaning that you can get your bullet line to intersect with theirs because your bullet comes from your centre (which they aren't aiming for). This is also why it stops working when they stand still, because their last position relative to you lines up with their current position relative to you so you end up shooting parallel.

I'm trying to figure out why my super-advanced precise circle-line intersection methods are failing so horribly at getting shield hits. I get one every now and again, but nothing like what I should be based on the maths and shield size I'm calculating, and nothing like the 3/4 of bullets that a simple linear projection + bullet power adaptation was getting.

Skilgannon19:45, 15 February 2013
 

I would recommend against using Seraphim in a test bed. It is a very buggy robot. So much so that I think it sometimes acts differently in a rumble environment then in a test environment.

But also some versions of Seraphim if I recall add a minor variance to its gun heading it detects it is against a bullet shielder. Is the version your using the same as the one in the rumble? (I expect so, but it cannot hurt to ask.)

Chase19:01, 15 February 2013
 

After some testing, maybe we can come up with a more consistent implementation for checking bullet collisions / line intersections in the Robocode engine. Here's the relevant code snippet: [1] (line 76 calling line 113).

Voidious19:36, 15 February 2013

Here's one that gets rid of the division which I expect is what blows up on poorly conditioned problems:

	private boolean intersect(Line2D.Double line) {
		double x1 = line.x1, x2 = line.x2, x3 = boundingLine.x1, x4 = boundingLine.x2;
		double y1 = line.y1, y2 = line.y2, y3 = boundingLine.y1, y4 = boundingLine.y2;

		double dx13 = (x1 - x3), dx21 = (x2 - x1), dx43 = (x4 - x3);
		double dy13 = (y1 - y3), dy21 = (y2 - y1), dy43 = (y4 - y3);

		double dn = dy43 * dx21 - dx43 * dy21;
                double dn_sign = Math.signum(dn);
                double dn_abs = dn*dn_sign;

		double ua = (dx43 * dy13 - dy43 * dx13) * dn_sign;
		double ub = (dx21 * dy13 - dy21 * dx13) * dn_sign;

		return (ua >= 0 && ua <= dn_abs) && (ub >= 0 && ub <= dn_abs);
	}

It might even be faster, divisions are about the same speed as sqrt.

Skilgannon20:12, 15 February 2013
 

Given that it is using it's own code to determine intersection rather than a JVM method, I wonder if the discrepancy between systems is actually in the data stored in the line objects.

I thought maybe I could tweak it using a small amount of movement to make it work on all systems, but so far my attempts have degraded shielding performance unacceptably. One bit of good news -- I tested and found out that Robocode security does not prohibit robots from reading System properties, so if I can figure out how to correct (at least partially) for the problem on other OSs or JVMs, I can test for them and just make those changes on the appropriate systems.

Skotty01:06, 16 February 2013
 

When I experimented with bullet shielding, my bot calculated minimum and maximum angles which would hit an incoming bullet, and only shoot if the difference between angles was above a threshold. It was there to work around floating point calculation errors, which translate into "parallel" bullets.

If the difference is below the threshold, then moving sideways helps increase the difference. Near 100% bullet shield against TrackFire. But against moving opponents and/or weak powered bullets, sometimes my bot moved until it crashed on the wall, never finding a good angle to shoot. And this is where my experiments are stuck right now.

MN20:35, 15 February 2013
 

Tonight I ran a test on one of my servers in my basement. The OS on it is Fedora 13. I installed Open JDK 6 (command su -c "yum install java-1.6.0-openjdk-devel"). Once installed, it reports itself as:

OpenJDK Runtime Environment (IcedTea6 1.8.8) (fedora-51.1.8.8.fc13-i386) OpenJDK Client VM (build 14.0-b16, mixed mode)

I ran a number of battles and have yet to encounter any shielding failures using XanderCat 12.2. But I need to do a more thorough test to be sure. Tomorrow I will set up RoboJogger and run a bigger series of tests.

Skotty07:29, 16 February 2013
 

Just checked and I'm also on OpenJDK 6:

java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.5) (6b24-1.11.5-0ubuntu1~12.04.1)
OpenJDK Server VM (build 20.0-b12, mixed mode)

Sorry I didn't get to any real testing today, but I will tomorrow. Now I'm really curious to see if I see the same in another JVM or in Windows...

Voidious07:32, 16 February 2013

I see that yours is the Server VM also. I wonder if that makes any difference.

Skotty07:44, 16 February 2013
 

In case it's easier just to copy it from here -- here is a challenge file with 3 opponents that XanderCat 12.2 is nearly perfect against on my machine but only maybe 50 percent successful against on machines that exhibit the performance anomaly.

Shielding Vulnerable
PERCENT_SCORE
35

Shielding Vulnerable {
    apv.test.Virus 0.6.1
    kc.serpent.Hydra 0.21
    trab.Crusader 0.1.7
}
Skotty08:05, 16 February 2013

I finally got my precise intersection with bullet shadows working for bullet shielding, so Voidious, if you're going to run some tests to see if bullet collisions work on your machine, give this a try as well: https://dl.dropbox.com/u/4066735/jk.precise.BulletShieldTest_1.0.jar I'm theoretically getting around half a pixel of shield width, so if that doesn't work then there is something seriously wrong.

Skilgannon09:52, 16 February 2013
 

Hi mate.

I was in the mood to check XanderCat 12.2 on my system and maybe it can help you to detect some uncertainties.

Mac OS X 10.6.8

java version "1.6.0_37"
Java(TM) SE Runtime Environment (build 1.6.0_37-b06-434-10M3909)
Java HotSpot(TM) 64-Bit Server VM (build 20.12-b01-434, mixed mode)

Robocode version: 1.7.4.4
CPU constant: 5426594 nanoseconds

Result vs Virus (png) Last Round Log vs Virus (png) Round start log vs Virus (log)

I started a couple of runs and it looks like almost 50% failed because of massive skipped turns if the round starts. This happens if the client runs on low speed and as well on full speed. If I put the client on debug=on, everything works fine and XanderCat win all rounds like expected. Because of the skipped turns XanderCat misses quite a few bullet catches and decides to move with a different movement - from that point he is almost ever doomed to loose some rounds. I hope it helps a little.


BulletShieldTest 1.0 worked so far very good on my system. He is lost against all 'sloppy' guns (HawkOfFire,SpinBot..) but against well coded targeting he has a quite impressive performance. Of course, he has still some minor flaws but i guess that is not unusual for a test version.

All in all i would say there is no difference in how the JVMs handle intersection but there may be a difference how they handle garbage collection and therefor have a different skipped turn behavior.


Man, I wished I had more time these days :( - take care

Wompi13:29, 16 February 2013

Thank you, Wompi. That is very helpful. From the round log, looks like there are occasional skipped turns (most likely due to the wave surfing drive and guess factor guns, but these sit idle when bullet shielding is active, and bullet shielding is much less processing intensive). However, the first round where most things are initialized is the worst.

So it's probable the problem isn't with the JVM doing the shielding calculations but rather how much time each system is allowing and how long it takes my initialization code to run (which I can work on, but it may also be true that different JVMs take different amounts of time for different types of initialization).

Looking at the info provided by the run time loggers, the averages between my system and yours aren't all that different, but the peaks shown on yours are an order of 5x what they are on mine. The radar peaks are even worse, which is weird. A typical greatest peak for my radar on my system is 0.25 trialing down to less than 0.1 by the 3rd peak, whereas on your system they start at 9.9 and are still above 0.8 by the 5th peak. (note: peaks are over the entire however-many round battle, as are the averages)

Both your system and Voidious' system are using the Server VM, and that makes me suspicious. I need to try out a Server VM and see what happens.

It should be noted that if this is the problem for Voidious, DivineOmega, and perhaps others, it is affecting overall performance (in the first round at least) and not just on the bullet shielding. If I can find a way to fix it, overall rumble performance could improve some.

Skotty15:56, 16 February 2013

I just tried the Server VM on mine but didn't see anything change.

Skotty16:33, 16 February 2013
 
 

Running some tests now. Starting with 20 seasons, single-threaded on the Ubuntu/OpenDJK setup. 10 seasons in and see it failing a lot vs Virus (~76%), rarely vs Crusader (~90%), and working well vs Hydra (96%). I'll post more details and the full RoboRunner logs when I've got some more data, and try it through the UI to see what I can tell about skipped turns.

If it is a skipped turns issue, I know there is one trick to put heavy initialization stuff in a static block and it won't count against your CPU time. I really hate Robocode's skipped turn setup, though I think limiting the CPU time in general is great. I'm definitely taking a different approach in BerryBots. It's probably too late to completely change it in Robocode, but we could at least look at an average over the last 5 or 100 ticks and penalize based on that instead (which is part of what I'm going to do).

Voidious18:34, 16 February 2013

Wow, ok.. So 4 threads was slightly worse overall, but 20 seasons is hardly enough to cover the margin of error. Now testing on Windows, and at 98 overall score after 8+ seasons. This is Oracle Java 7. Also interesting to note that the CPU constant was set to about 5 ms in Windows, vs 7 in Linux. Also this is all on Robocode 1.7.4.0, sorry about that, but I don't think it makes a difference.

Voidious19:24, 16 February 2013
 

Ok, still want to test on Ubuntu 64-bit and with the Oracle JVM on Linux, but here's a bunch of data for now.

config Virus Hydra Crusader Total
Linux/OJDK/1 thread 76.14 +- 8.29 95.93 +- 0.37 89.26 +- 5.17 87.11 +- 2.66
Linux/OJDK/4 threads 81.45 +- 7.6 82.77 +- 6.51 90.91 +- 5.14 85.04 +- 2.92
Windows/1 thread 98.89 +- 0.25 96.09 +- 0.33 98.67 +- 0.34 97.88 +- 0.17
Windows/2 threads 97.18 +- 1.91 96.31 +- 0.35 98.92 +- 0.3 97.47 +- 0.48
Windows/3 threads 95.4 +- 3.19 96.39 +- 0.23 88.88 +- 5.49 93.56 +- 1.55
Windows/4 threads 98.66 +- 0.31 92.2 +- 3.5 92.42 +- 4.31 94.43 +- 1.41

It's worth noting that I feel comfortable running my own benchmarks 6-threaded on this machine and I usually run 4 RoboRumble clients at a time.

Voidious20:33, 16 February 2013

Thank you, Voidious, for all the data. Don't forget to take a peak at skipped turns under Linux/OJDK. It gets printed to the game log, and you can also check what is printed in the SkippedTurns text file it writes to the data directory.

For now, I'm going with the assumption that I need to target reducing initialization overhead due to skipped turns. Once I have that done, I can prepare another version of XanderCat, which if I'm lucky you will be willing to run through your Linux/OJDK setup again to see how it changes things.

Skotty21:05, 16 February 2013
 
 

So, upon not getting to the bottom of this, I stopped running my rumble clients. Where are we with the discrepancy in shielding success on different systems? I don't particularly mind keeping my clients off for now, since I'm not submitting bots, but I do have quite a bit of CPU power I'd be happy to contribute.

I also still want to test with the newer XanderCat, Ubuntu 64-bit, and a different JVM on Ubuntu, but that requires Voidious-time and not just CPU-time. :-)

Voidious22:37, 27 February 2013

Not much new at this point. I greatly reduced my processing overhead in XanderCat 12.3+ in an attempt to improve on the problem (nearly cut average and peak processing times for targeting and surfing in half; see Version CPU Usage section of my XanderCat page; noting that my CPU constant is around 10ms), but since the problem seems linked to garbage collection, I don't think it will result that much of an improvement (I'm guessing far fewer skipped turns in later rounds but still a bunch in the first round, which will still break shielding). I may be able to reduce the amount of garbage collection by trying to eliminate as many local method-scope variables as I can, but that would be a lot of work for something that will likely make the code less readable and I don't even know for certain if it will help. Thus I haven't tried it yet.

Wompi indicated that using -XX:+UseConcMarkSweepGC to use the concurrent mark and sweep garbage collector eliminated the problem, but I don't think anyone was sure whether it was a good idea or not to use this as a solution. Not sure if it could cause other problems.

For now, I don't mind if you restart your clients. XanderCat 12.5 already has over 10K battles and I don't intend to replace it with a newer version for awhile.

Skotty00:29, 28 February 2013
 
 
First page
First page
Previous page
Previous page
Last page
Last page