0

Can php.exe run for applications that run for weeks or months together, continuously, without crashing?

Ex: A UDP or a HTTP/TCP server (or Network) application. I hear it has not been developed for long running applications all the time. I believe we can do multi-threading/parallel using pthreads/events in both linux and Windows to support the load generated for processes and develop long running apps. But not sure how stable that would be. Anyone who can comment and provide some resource directions for development using pthreads and long running PHP apps?

Gary
  • 2,293
  • 2
  • 25
  • 47

1 Answers1

6

PHP

Versions of PHP below 5.3 didn't have a garbage collector, this caused seemingly simple code (loops, recursion) to consume huge amounts of memory:

<?php
class Foo
{
    public $var = '3.14159265359';
}

$baseMemory = memory_get_usage();

for ( $i = 0; $i <= 100000; $i++ )
{
    $a = new Foo;
    $a->self = $a;
    if ( $i % 500 === 0 )
    {
        echo sprintf( '%8d: ', $i ), memory_get_usage() - $baseMemory, "\n";
    }
}
?>

Below is the memory usage for 5.2 and 5.3 side by side:

5.2 vs 5.3 memory usage

This makes writing code of any complexity that runs indefinitely as near as makes no difference impossible in versions of PHP below 5.3.

For versions of PHP equal to or greater than 5.3, there is absolutely nothing about Zend that prohibits the execution of long running scripts, even indefinite execution.

There are still things to think about; If you infinitely append to some array, you will need an infinite amount of memory to store that array.

One just needs to be careful, even innocuous changes can have an effect on consumption, so establish a pattern of frequent regression testing during development, so that you can see where problems are introduced immediately.

Code and image taken from PHP manual.

pthreads v3

I'm going to answer in the context of pthreads v3, PHP7+.

pthreads might consume more memory than you are expecting. PHP is a shared nothing environment, pthreads must not break that architecture and so unlike a normal multi-threaded application, threads cannot share the same address space.

pthreads makes it appear as if they do, the way it does that is not important for the answer.

With normal Thread programming, consumption should not be so difficult to control, but with Worker and Pool programming, it may not be so obvious.

Take the following code:

<?php
class Job extends Threaded {
    public function run() {
        printf("Job in Thread %lu (%d) bytes\n",
            Thread::getCurrentThreadId(),
            memory_get_usage(false));
    }
}

$pool = new Pool(16);
$monitor = new Threaded();

do {
    for ($i=0; $i<100; $i++)
        $pool->submit(new Job());   

    while ($pool->collect())
        continue;

    printf("Main context (%d) bytes\n",
        memory_get_usage(false));

    $monitor->synchronized(function() use($monitor) {
        $monitor->wait(1000000);
    }); 
} while (true);
?>

The calls using $monitor should be convention, the nicest way to force a Thread, even the main context, to sleep.

If it were not for the calls to ::collect, consumption would soon become out of control.

The ::collect method is actually part of the Worker class, the Pool is calling it by proxy for all the Worker objects it is using.

The prototype can be taken as:

public function collect(callable $collector = Worker::collector);

When a Job is popped from the queue for execution inside the Worker context that is executing it, it is inserted into a garbage list.

When ::collect is called, the garbage list for the Worker is traversed, passing each Job to $collector passed (or not) as argument.

If the Worker is doing the kind of work that would make it dangerous to collect garbage at that time, the call to ::collect will return early, and you should try again if the return value from ::collect is > 0.

The $collector should return true if the Job can be removed from the garbage list (therefore freeing associated resources if no other references exist), the default Worker::collector returns true, assuming that an object in the garbage list is ready for destruction at the earliest opportunity.

All of this allows long running, rather complex pthreads based applications to run indefinitely.

The same kind of considerations must be made as for normal PHP, with an additional (little) bit of leg work.

kelunik
  • 6,750
  • 2
  • 41
  • 70
Joe Watkins
  • 17,032
  • 5
  • 41
  • 62
  • Thanks, I see your point. Thanks for the concept. This is exactly what I was looking for. I want to know, when I execute the new thread is this parallel thread async or sync? I believe pthreads are synchronous. But here is what I am actually deciphering: http://php.net/manual/en/intro.pthreads.php Synchronization: All of the objects that pthreads creates have built in synchronization in the ( familiar to java programmers ) form of ::wait and ::notify. Calling ::wait on an object will cause the context to wait for another context to call ::notify on the same object. – Gary Nov 26 '15 at 05:36
  • Let me give an example: If I am starting a thread for say a logging class that independently logs application routes, function calls, errors, etc; will I be able to execute logging independently and async (apart from it being parallel execution), if I dont call ::wait? (on say eg: $monitor object's synchronized call's wait method?) – Gary Nov 26 '15 at 05:42
  • fyi... I am following http://stackoverflow.com/questions/13846192/php-threading-call-to-a-php-function-asynchronously/13872965#13872965 – Gary Nov 26 '15 at 05:47
  • async and parrallel mean very specific things, the words are not interchangeable. I can't make sense of what you are saying ... http://blog.krakjoe.ninja/2015/07/the-universe-is-not-aware.html pthreads are proper, kernel level, threads, they execute in parallel. If you have more questions, it would be better if you opened new questions, rather than continuing the conversation here. – Joe Watkins Nov 26 '15 at 07:01
  • I appreciate effort for parallel & async diff. I understand that completely. What I wanted to know was - is pthreads async or sync executed parallel threads? I believe you answered it - since it is a kernel level thread in parallel it(execution) has to be sync (blocking) execution like OS processes. Let me try if I can use pthreads with libevent for async and parallel, myself. My logging function right now is crashing my php with higher concurrency/usage. React-PHP and Rachet seem to have implemented async&parallel(but advise against long running http server). http://socketo.me/docs/http – Gary Nov 26 '15 at 11:48