Undeterministic timeout? [Fall Challenge 2024]

Hello,

I’m currently enjoying the Fall Challenge 2024 - Selenia City, and it’s been really great! :+1:

However, I’m experiencing something that I call an “Undeterministic Timeout.

My current code is fully deterministic, with one exception: I’m checking how long the script is running (in PHP using getrusage()), and when the time exceeds 460ms (due to the rule: “Your program has to return its list of actions within 500 milliseconds each turn”), the analysis is halted, and commands are outputted to prevent a timeout.

BUT—when I run this code repeatedly on Test Case [08] “Grid,” I’m getting different results. For example, sometimes I get:

  • 587,404 points
  • 626,738 points
  • 648,862 points

And sometimes I even hit a timeout!

Similarly, after submitting the code to the Validators, sometimes I get all green results, while other times(resubmiting unchanged code) the “Grid” test case fails (red).

Could someone please clarify how the timeout check works and/or how to prevent these undeterministic timeouts?
(Lowering the limit from 460ms to, say, 250ms isn’t the answer I’m looking for :wink:).

Thank you for reading and for any replies or information!

Code that runs some type of loop until a timeout is nondeterministic by definition, because the exact amount of time hardware takes to do something depends on factors other than the code.

Lowering the limit from 460ms to, say, 250ms isn’t the answer I’m looking for

I’m not sure what answer you are expecting then? If your code is timing out when you exit a loop after 460ms, then you’re using too much time and you need to exit earlier (or you have an undetected infinite loop or other error somewhere).

A couple things that might help are:

  • You could try microtime() or hrtime() instead of getrusage() (I’m not familiar with code timing in PHP, but with timing the specific choice of API used can be important in some contexts);
  • Make sure you are checking the timer often enough (for example, if you are checking once per iteration and an iteration can take close to 40ms in the worst case, then checking against 460ms isn’t helpful);
  • Start your timer immediately after reading the first line of input for a round.

Thinking about it some more–I’m not sure precisely how you are using getrusage(), but as far as I know the timeout is in wall-clock time, not processing time. So that could be the entirety of your issue.

Thank you for your reply.
The truth is, I initially used microtime(), but the results were even worse (more timeouts and/also in other test cases as well), so I switched to getrusage(), which gave better results (fewer timeouts). #wierd

Yes, in extreme cases, I could lower the limit to just 1 ms ;o) instead of 460 ms or 250 ms, but I’m already sacrificing almost 10% of computing time, which I think is a lot! In a forum thread from about 4 years ago, there was a similar discussion, and they were only talking about a 5-10 ms margin, so I’m almost an order of magnitude higher.

That’s why I would like to understand exactly how the timeout check works on the GC/game referee side.

Or if there’s a better way to know how much time is left until a timeout occurs.

And yes, I’m checking for timeouts more frequently than every 40 ms and no, there isn’t any infinite loop.
Anyway, thank you again for your reply and your ideas/thoughts.

Sending a large number of orders was causing ‘timeout’ for me, even when my code returns very quickly.

After a bit of investigating it appears printing an order string >= 10000 characters hits a hard limit that I don’t think is documented in the problem statement.

Grid is the example where this is most likely so it could be your problem too.

2 Likes