Jump to content

while loop reaching nginx limit


NICON

Recommended Posts

I have a while loop in a script that is running for a very long time due to the large values that are passing through it. Below is the link to the pastebin code and code embedded in this forum.

Loop Statement Snipet

if (!$user_class->invincible) {
	if (!$defender->invincible) {
		while ($yourhp > 0 && $theirhp > 0) {
			$damage = round($defender->moddedstrength) - $user_class->moddeddefense;
			$damage = ($damage < 1) ? 1 : $damage;
			if (!$wait) {
				$yourhp = $yourhp - $damage;
				++$number;
				$log[] = $number . ":&nbsp;" . $defender->formattedname . " hit you for " . prettynum($damage) . " damage using their " . $defender->weaponname . ". <br />";
			} else
				$wait = 0;
			if ($yourhp > 0) {
				$damage = round($user_class->moddedstrength) - $defender->moddeddefense;
				$damage = ($damage < 1) ? 1 : $damage;
				$theirhp = $theirhp - $damage;
				++$number;
				$log[] = $number . ":&nbsp;" . "You hit " . $defender->formattedname . " for " . prettynum($damage) . " damage using your " . $user_class->weaponname . ". <br />";
			}
		}
		$log = array_slice($log, -10, 10, true);
		foreach($log as $text)
			echo $text;
	} else
		$yourhp = 0;
} else
	$theirhp = 0;

My issue is that $yourhp and $theirhp can be in the 100's of thousands causing this to loop half a million plus times.

I was curious if there was a way to only show the first few lines and last few lines of this but still retain the increment value that's created?

Thanks so much in advance.

NICON

Link to comment
Share on other sites

14 hours ago, requinix said:

Even 10,000,000 times through the loop should execute in a split second.

How long as we talking? What if you remove the $log? And what version of PHP?

The current version running on the server is 5.5.9. It executes for roughly 30 to 40 seconds then gives an error screen. If I remove the $log in the while loop it does execute properly. Just wont give any output on the screen as to the results of this section of code.

Link to comment
Share on other sites

if ($number <= 9 || $yourhp <= 0) {
	$log[] = $number . ":&nbsp;" . $defender->formattedname . " hit you for " . prettynum($damage) . " damage using their " . $defender->weaponname . ". <br />";
}

if ($number <= 9 || $theirhp <= 0) {
	$log[] = $number . ":&nbsp;" . $defender->formattedname . " hit you for " . prettynum($damage) . " damage using their " . $defender->weaponname . ". <br />";
}

Adding these 2 if statements in limits the amount of data stored in the array... Which may have been the issue all along just way to much info in the array? I was getting a 500 error because of it.

Link to comment
Share on other sites

Appending lots of entries to an array can hurt performance, especially in old versions of PHP.

You don't even need a loop for all this anyways: the damage dealt is constant so with some simple math you can calculate exactly (a) how many rounds it would take and (b) the final health values for both sides.

if (!$user_class->invincible && !defender->invincible) {
	$yourdamage = max(1, round($user_class->moddedstrength) - $defender->moddeddefense);
	$theirdamage = max(1, round($defender->moddedstrength) - $user_class->moddeddefense);

	$yourrounds = ceil($theirhp / $yourdamage);
	$theirrounds = ceil($yourhp / $theirdamage);
	$rounds = min($yourrounds, $theirrounds);

	$yourhp = $yourhp - $theirdamage * $rounds;
	$theirhp = $theirhp - $yourdamage * $rounds;

	// ...
} else if ($user_class->invincible) {
	$theirhp = 0;
} else {
	$yourhp = 0;
}

Two parts left: constructing the logs you want to show and adjusting for $wait.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.