How to Stop PHP Sleep() Affecting My Whole PHP Code

Does adding sleep() to a loop alleviate server resources?

In a nutshell, yes, but don't worry about it.

While sleep is executing, CPU processing of your script virtually stops. So yes, it will alleviate processing resources. (The script is still in memory, so those resources are still used, but that shouldn't be a problem on a modern machine.)

If your goal is to do this every 60 seconds, the best practice would be make your PHP a cron script, and run it at low priority.


Configure Cron for a low priority PHP script:

nano crontab -e

Add the following:

* * * * *   /usr/bin/nice -n 12 php -q /path/file.php

And replace the /path/file.php with the full path to your PHP script.


Ensure your PHP script is ready

Edit your script's file permissions to allow execution.

chmod ug+rwx /path/file.php

(Again replacing /path/file.php with your actual PHP script's full path.)

Lastly, it's a good idea to make these the very first 2 lines in your PHP script, if you intend to run it this way:

#!/usr/bin/php5
<?php

PHP, wake up process which is sleeping

This can be done using the process signal SIGCONT to inform the script it needs to wake up. Note that this requires the php extension pcntl and may be platform dependent (tested on macOS Big Sur):

SleepingScript.php

<?php

if (!extension_loaded('pcntl')) {
echo 'Unable to wake up!\n';
} else {
// While we aren't doing anything with the CONT signal, we need
// it to be handled so that the process can wake up from sleep
pcntl_signal(SIGCONT, function () {});
}

// Save this to file, redis, or something else
echo posix_getpid() . "\n";

// Sometimes time_nanosleep isn't available on your platform
// If it's not, you'll need to substitute using sleep/usleep and maybe hrtime
$seconds = 120;
$nanoseconds = 0;
$nano = time_nanosleep($seconds, $nanoseconds);

if ($nano === true) {
echo "Slept for $seconds seconds, $nanoseconds nanoseconds.\n";
} elseif ($nano === false) {
echo "Sleeping failed.\n";
} else {
echo "Interrupted by a signal.\n";
echo "Time remaining: {$nano['seconds']} seconds, {$nano['nanoseconds']} nanoseconds.";
}

WakeScript.php

<?php

// Get saved pid. This could be from file, redis, or something else.
// Here we're going to use the first argument for ease
$pid = (int)$argv[1];

// While normally used to kill a process, posix_kill really just sends a signal.
// We'll send SIGCONT to wake up the other script
posix_kill($pid, SIGCONT);

And here's what it looks like in action. First in one terminal:

$ php SleepingScript.php 
93357

And going to a second terminal:

$ php WakeScript.php 93357

And back to the original terminal:

$ php SleepingScript.php 
93357
Interrupted by a signal.
Time remaining: 111 seconds, 712678616 nanoseconds.

Should i use Sleep() or just deny them

The sleep does not use any CPU or Memory which is not already used by the process accepting the call.

The problem you will face with implementing sleep() is that you will eventually run out of file descriptors while the attacker site around waiting for your sleep to time out, and then your site will appear to be down to any other people who tries to connect.

This is a classical DDoS scenario -- the attacker do not actually try to break into your machine (they may also try to do that, but that is a different storry) instead they are trying to harm your site by using up every resource you have, being either bandwidth, file descriptors, thread for processing etc. -- and when one of your resources are used up, then you site appears to be down although your server is not actually down.

The only real defense here is to either not accept the calls, or to have a dynamic firewall configuration which filters out calls -- or a router/firewall box which does the same but off your server.

Prevent PHP script using up all resources while it runs?

A normal script can't hog up 100% of resources, resources get split over the processes. It could slow everything down intensly, but not lock all resources in (without doing some funky stuff). You could get a hint by doing top -s in your commandline, see which process takes up a lot.

That leads to conclude that something locks all further processes. As Arkascha comments, there is a fair chance that your database gets locked. This answer explains which table type you should use; If you do not have it set to InnoDB, you probally want that, at least for the locking tables.

It could also be disk I/O if you write huge files, try to split it into smaller read/writes or try to place some of the info (e.g. if it are files with lists) to your database (assuming that has room to spare).

It could also be CPU. To fix that, you need to make your code more efficient. Recheck your code, see if you do heavy operations and try to make those smaller. Normally you want this as fast as possible, now you want them as lightweight as possible, this changes the way you write code.

If it still locks up, it's time to debug. Turn off a large part of your code and check if the locking still happens. Continue turning on code untill you notice locking. Then fix that. Try to figure out what is costing you so much. Only a few scripts require intense resources, it is now time to optimize. One option might be splitting it into two (or more) steps. Run a cron that prepares/sanites the data, and one that processed the data. These dont have to run at syncronical, there might be a few minutes between them.

If that is not an option, benchmark your code and improve as much as you can. If you have a heavy query, it might improve by selecting only ID's in the heavy query and use a second query just to fetch the data. If you can, use your database to filter, sort and manage data, don't do that in PHP.

What I have also implemented once is a sleep every N actions.

If your script really is that extreme, another solution could be moving it to a time when little/no visitors are on your site. Even if you remove the bottleneck, nobody likes a slow website.

And there is always the option of increasing your hardware.

Does sleep time count for execution time limit?

You should try it, just have a script that sleeps for more than your maximum execution time.

<?php
sleep(ini_get('max_execution_time') + 10);
?>

Spoiler: Under Linux, sleeping time is ignored, but under Windows, it counts as execution time.



Related Topics



Leave a reply



Submit