Here is my pseudo code
For loop repeat 30 times
Call and execute API script which takes less than 1 second
I want the system to sleep for some moment(less than 1 second)
Loop end
I want the above script should finish execution in minimum of 30 seconds (2-3 seconds longer is not a problem but must not less).
Can you write a sample code for me(only time related)
Here's a little program that implements the essence of what I believe you are looking for:
$minTime = 30;
$perSec = 10000;
$start = microtime(TRUE)*$perSec;
print("This must take $minTime seconds.\n");
// Replace this loop with what you actually need done
for ($i=0; $i<10; $i++) { print("Doing stuff #{$i}... "); sleep(1); }
// Check difference in timestamps to calculate remaining time
$remain=($minTime*$perSec-(microtime(TRUE)*$perSec-$start))/$perSec;
var_dump(['remain' => $remain]);
if ($remain > 0) {
print("\n$remain seconds remaining... ");
sleep($remain);
}
print("DONE\n");
This code has been updated to use microtime() instead of time(), which only permitted intervals of integer seconds. On systems that support gettimeofday() we can work with microseconds, instead.
Related
I have a thousand (for example, could be more) strings and for each string, there is a field associated with it which represents time interval.
For each one of the strings, I need to perform a task which takes the string as input and produces some output, every X minutes (X being the time interval mentioned above).
If it was a single value of time interval for all the strings, then I would set up a single cron job and that would suffice; but I have a different value of time interval for each of the strings.
So I'll set up a thousand or more cron jobs. That does not feel right. So what would be the best way to solve this problem?
You might want to look into using a library that already did this instead of re-inventing the wheel yourself.
https://packagist.org/packages/peppeocchi/php-cron-scheduler
But, if you'd really want to code it yourself you'll need to have "two variables" one with last executed which has to be read from a file or database in between execution cycles, one with interval and have cron call your script every second/minute
Take a look at the proof of concept code here. Untested but it should point you in to how it should work in theory.
class Job
{
protected $interval = 0;
protected $lastrun = 0;
protected $job = null;
protected $filename = null;
public function __construct($id, $interval,callable $job)
{
$this->interval = $interval;
$this->job = $job;
$this->filename = __DIR__.'/'.$id.'.job';
$this->lastrun = file_get_contents($this->filename) ? : 0;
}
public function attemptRun($time)
{
if($time - $this->lastrun >= $this->interval) {
$this->run($time);
}
}
protected function run($time)
{
file_put_contents($this->filename, $time);
$this->job();
}
}
$jobs = [
new Job('addition', 10, function() { $a = 1; $b = 2; $c = $a + $b;}),
new Job('subtraction', 20, function() { $a = 1; $b = 2; $c = $a - $b;}),
];
var $currentTime = time();
foreach($jobs as $job) {
$job->attemptRun($currentTime);
}
Cron job: Run it every minute.
Let's say you have 3 strings in the format string_value-execute after certain minutes-
some_string-5
some_string_2-10
some_string_3-15
So, execution time if we start from 0 will have a series like this-
0
5 (execute first)
10 (execute first as well as second string)
15 (execute first and third string)
20 (execute first as well as second string)
25 (execute only first)
30 (execute first,second,third)
Database part:
Have 2 tables.
First table- has a single column having current cron minute.
second table- Have column as string , interval duration , next_execution_time
Now, insert into first table whenever you run it.
Secondly, do a "Select * from table_name where next_execution_time = current_got_fetched_from_first_table".
Introduce new strings- When you are doing so, insert as first start interval = current_cron_time + interval_duration to execute.
P.S- When processing completes, you also need to update the second table with their respective next_execution_time.
I have PHP array which I use to draw a graph
Json format:
{"y":24.1,"x":"2017-12-04 11:21:25"},
{"y":24.1,"x":"2017-12-04 11:32:25"},
{"y":24.3,"x":"2017-12-04 11:33:30"},
{"y":24.1,"x":"2017-12-04 11:34:25"},
{"y":24.2,"x":"2017-12-04 11:35:35"},.........
{"y":26.2,"x":"2017-12-04 11:36:35"}, ->goes up for about a minute
{"y":26.3,"x":"2017-12-04 11:37:35"},.........
{"y":24.1,"x":"2017-12-04 11:38:25"},
{"y":24.3,"x":"2017-12-04 11:39:30"}
y=is temperature and x value is date time,
as you can see temperature doesn't change so often even if, it change only for max 0.4. But sometimes after a long period of similar values it change for more than 0.4.
I would like to join those similar values, so graph would not have 200k of similar values but only those that are "important".
I would need an advice, how to make or which algorithm would be perfect to create optimized array like i would like.
perfect output:
{"y":24.1,"x":"2017-12-04 11:21:25"},.........
{"y":24.1,"x":"2017-12-04 11:34:25"},
{"y":24.2,"x":"2017-12-04 11:35:35"},.........
{"y":26.2,"x":"2017-12-04 11:36:35"}, ->goes up for about a minute
{"y":26.3,"x":"2017-12-04 11:37:35"},.........
{"y":24.1,"x":"2017-12-04 11:38:25"}
Any help?
As you specified php I'm going to assume you can handle this on the output side.
Basically, you want logic like "if the absolute value of the temperature exceeds the last temperature by so much, or the time is greater than the last time by x minutes, then let's output a point on the graph". If that's the case you can get the result by the following:
$temps = array(); //your data in the question
$temp = 0;
$time = 0;
$time_max = 120; //two minutes
$temp_important = .4; //max you'll tolerate
$output = [];
foreach($temps as $point){
if(strtotime($point['x']) - $time > $time_max || abs($point['y'] - $temp) >= $temp_important){
// add it to output
$output[] = $point;
}
//update our data points
if(strtotime($point['x']) - $time > $time_max){
$time = strtotime($point['x']);
}
if(abs($point['y'] - $temp) >= $temp_important){
$temp = $point['y'];
}
}
// and out we go..
echo json_encode($output);
Hmm, that's not exactly what you're asking for, as if the temp spiked in a short time and then went down immediately, you'd need to change your logic - but think of it in terms of requirements.
If you're RECEIVING data on the output side I'd write something in javascript to store these points in/out and use the same logic. You might need to buffer 2-3 points to make your decision. Your logic here is performing an important task so you'd want to encapsulate it and make sure you could specify the parameters easily.
I need to call the script function open() when the counter exceeds 5, but when I load my webpage, it shows me a fatal error : Maximum execution time of 30 seconds exceeded. Is that my while loop problem?
$result = mysqli_query($dbconnect, "SELECT id, temp, hum, lum FROM weather ORDER BY id DESC LIMIT 5");
while($row = mysqli_fetch_assoc($result)){
$weather["temp"] = $row["temp"];
$weather["lum"] = $row["lum"];
$tempcounter = 0;
while ($weather["temp"] > 27) {
$tempcounter++;
}
if($tempcounter > 5){
echo"<script>open()</script>";
}}
Your while loop is infinite. The loop will start if $weather["temp"] is bigger than 27 and inside you increment the tempcounter but never change $weather["temp"] so it will always be bigger than 27 and never get out of the loop.
You could put $weather["temp"] in a variable. Then inside the loop increment it also. But most importantly you need to reverse your condition. If you increment you need to check < and if you decrement you can check >.
If you increment:
$weatherTemp = $weather["temp"];
while ($weatherTemp < 27) {
$weatherTemp++;
}
If you decrement:
$weatherTemp = $weather["temp"];
while ($weatherTemp > 27) {
$weatherTemp--;
}
And then you can declare $tempcouter like this:
$tempcounter = $weatherTemp - $weather["temp"]; //Temperature needed to get to 27
if($tempcounter > 5){
echo"<script>open()</script>";
}
Code is not tested it might not work has it is.
If what you want to do is get the difference between 27 and your temperature you are not using the right logic here. You could simply take 27 minus your temperature form the query. If the result is negative just change it to positive and you get the difference.
I think it is time over problem.
You can fix this problem by 2 methods.
Set max_execution_time to large value ex. 300 or larger
Begin of your php script call set_time_limit function
set_time_limit(0);
In this loop:
$tempcounter = 0;
while ($weather["temp"] > 27) {
$tempcounter++;
}
You're not updating $weather["temp"], so it will loop forever if that condition is satisfied.
For a school assignment we need to write a PHP script that counts for 1 second.
The following code I wrote should do exactly that was my thought:
$startTijd = time();
$teller = 0;
while($startTijd == time()){
echo 'Iteratie: ' . $teller . '<br>';
$teller++;
}
However, every time I run this or any PHP script similar to it that uses the time() function inside a while loop I get a 502 bad request from the server when I try to visit the page.
Your code as it is would not work (would not count one second exactly), because time() has a granularity of one second, and you have no guarantees that you landed on your page exactly at the tick of a second. So you need to synchronize.
To be clear, imagine calling time() several times, and let's suppose time() outputs in HH:MM:SS instead of Unix timestamps for legibility's sake:
Code
print time()
print time()
print time()
...
Output:
01:15:17
01:15:17
01:15:17
...
01:15:18
01:15:18
01:15:18
...
Your program probably currently does not work correctly because even in the little time that the loop runs, it generates a fantastic quantity of output (as can be seen above, time() remains "valid" for up to a whole second, and in that time a loop can execute lots of times). If there's some sort of resource limit on the PHP process, it's possible that this drives the process over its quota, resulting in the 502 error. You can check that by removing the echo from the loop, and just adding echo "Done." at the end.
You want to count between the instant in time in which time() transitions from 01:15:17 to 01:15:18, up to the instant when it again transitions to 01:15:19. Those instants will be separated by exactly one second.
What you would need to do is:
$startTijd = time()+1; // It is now maybe 01:15:17.93. We want to start
// counting at 01:15:18, so we need to wait for it.
while($startTijd !== time()) {
// Do nothing except maybe a very brief sleep to save CPU
usleep(5); // this is optional anyway.
}
// It is now 01:15:18.000003 and $startTijd is 01:15:18
$teller = 0;
// time() will remain equal to 01:15:18 for one second,
// while wall clock time increases from 01:15:18.000003 to 01:15:18.999999
while ($startTijd == time()) {
// Don't output anything here
$teller++;
}
// New transition detected.
// It is now e.g. 01:15:19.000137 and time() says 01:15:19.
echo 'Iteratie: ' . $teller . '<br>';
Alternately you can use microtime(true):
$teller = 0;
$endTijd = microtime(true) + 1.0;
while ($endTijd >= microtime(true)) {
// Don't output anything here
$teller++;
}
echo 'Iteratie: ' . $teller . '<br>';
Your code makes no sense... your while statment is only true if you computer is fast enough.
$startTijd = 100; # you set here the time represented by a number
while(100 == time() #101) { # here time is some milliseconds or seconds in the future
so after a second your while stops so that make not so much sense. Then use
while(true) {
and stop the while with a condition insight the while loop.
I want to run a script every two hours, so I use this cron jon command:
0 */2 * * *
The script should use key X when running the first time, and on the following run it should use key Y, and then X again and so on.
My initial idea was to use the server time, and according to whether the hour is odd or even number, it will choose different key:
$h = date('G');
if ( $h & 1 ) {
$key = "X"; } // odd
else {
$key = "Y"; } // even
But since I run it every two hours in the first place, it is bound to use only one of these keys always, so it's not good.
What's a good way to achieve this?
You can write a file "flag.txt" to filesystem, and check if he exists. If it exists, use X and delete file, if it not exists, create file and use Y.
I think that this should work, but I have no tested it. But doing this with date is the easiest to do.
1 to 12 with date
$dDate = date("g");
Lets say that it fires on 0/2/4/6/8/10/12
$iResult = $dDate % 2;
If any of the given fire times is given $iResult will be 0 so in this case
if($iResult != 0) {
//Do X
} else {
//Do Y
}