Friday, 20 November 2015

APC and Me

Fig1. An APC logo.

When it was decided that Zend's Optimizer Plus would be merged into PHP, APC was already in a pretty poor state, there hadn't been a stable release for quite some time.

We were moving towards having a built in (abandoned in php-src/ext) opcode caching solution but it was not obvious that APC was going to keep being maintained.

I think all of us assumed that the bugs that were being experienced were entirely down to the opcode caching parts of APC, since they were the most complex and most frequently altered parts of APC.

So, one day (few nights), I stripped APC of opcode caching.

One of the things I decided I would tidy up was the implementation and usage of locking.

The supported kinds of locks are:
  • File locking
  • Mutex
  • Read/Write Locks
  • Spin Locks
Brief explanations follow.

File Locking


I'm going to assume that everybody reading knows what this is, and even without experience, can sense that it is probably the most inferior in the list.

I sincerely hope that nobody uses file locking today.

The reason it exists is because people deploy PHP in all kinds of places, places we don't get to hear about until something goes wrong. Those places might not have support for anything other than file locking, so it stays.

Mutex


This is your most basic kind of synchronization. Mutex means Mutual Exclusion, so we know that this kind of synchronization is exclusive.

This was the default locking for APC

Read/Write Locks


Read/Write locking allows a shared lock to be acquired for reading, this means many readers can be supported without exclusion. An exclusive lock is only required for writing.

This is the default for APCu

Spin Locks


Speaking as a programmer who spends a lot of time writing multi-threaded code, in various languages: A spin lock is about the worst kind of synchronization imaginable, it is basically a predicated busy wait loop.

This remains in APCu for the same reason file locking does, and I actually have heard of people using it and can't convince them to do otherwise.


Scary Things


I didn't know the APC code base before that first night, had never read any of it before.

Whenever a programmer reads code from a prospective project that another programmer wrote, they have criticisms. Some of them are just our ego talking, some of them are wrong, some of them are probably a mechanism to motivate us to keep working. Hardly any of them are worth mentioning, or doing anything about.

The task at hand is to get the thing working, not fix every problem that nobody ever had.

So I cleaned up, I worked on it for a few days and pushed it to pecl.


OMG


So, this blog post started out as something completely different.

APCu was demonstrably unstable, and I thought this was because it broke a basic rule. It seemed to acquire a read lock, when it should be acquiring a write lock.

There seemed to be a clear path to race conditions, in other words.

While trying to find the code in the APC code base that caused the problem I made this search: apc_cache_release

The APCu version omits atomicity, it omits safety; In my haste to clean up, I have made a horrible mistake.

There was even a pull request, from one of the elders of PHP, that I chose not to merge, for three years.

The worst thing about being wrong is that I inevitably feel dumb as rocks.

The best thing about being wrong is things that didn't make sense before, like this, or this, and many other bugs besides, start to make sense.

So, I've found the reason that APCu was unstable, it was me.

This probably caused a problem for a fairly large number of people.

Sorry about that, I'll get to fixing it ...

I'm afraid I don't have time to blog now, too much work to do :(

Thursday, 12 November 2015

The Problem with Caching

Fig 1. Stampeding Elephants.
We cache things to avoid unnecessary load on our servers. It might therefore surprise you to learn that when you are most vulnerable, the kind of shared memory cache that is APC(u) will stab you in the face ...

APC(u) has had stampede protection for a long time, however, it is perniciously named, and ineffective when it is most needed.

You are most vulnerable to high load when the cache is empty,  because the work you were trying to avoid executing unnecessarily by caching it's result, must execute.

The problem is that the expensive-work-worth-avoiding is going to be executed in more than one process; It will be executed by however many processes you are using that are able to spin up in the time it takes the first process to warm the cache.

If you have large pools of processes, or generation of the entry is expensive, this becomes a very real problem.

The stampede protection built into APC(u) only stops a stampede of the cache, it doesn't stop the stampede, or competition, for CPU time while dozens, possibly hundreds, of processes are attempting to execute the very same code paths, only to fail to store the data, because the current stampede protection will prohibit the write, for most of the processes anyway.

What not to do ...


The most obvious, but most dangerous solution would be to expose a lock and unlock function to userland PHP.

If some process calls lock, and before it gets to call unlock, experiences an uncaught exception, or some other fatal error, it will deadlock the server.

Since so much can result in that kind of fatal error, it doesn't seem worth the risk, considering the price of failure is catastrophic deadlock.


The Solution


APCu >= 5.1.0 (PHP7+) will have the following function:

function apcu_entry(string key, callable generator, int ttl = 0);

If the entry identified by key cannot be found (or is invalidated by the ttl it was stored with), generator is called and the result stored with the optionally specified ttl.

All of this is done while an exclusive lock is held on the cache; This means that if many processes hit the same code path, only one of them will carry out generation.

Used correctly this allows truly atomic cache warming to take place, like so:
<?php
$config = apcu_entry("config", function($key){
 return [
  "child" => apcu_entry("config.child", function($key) {
   return "Hello World";
  }),
  "next" => apcu_entry("config.next", function($key) {
   return "We've only just begun ...";
  }),
  /* ... */
 ];
});

var_dump($config);
?>
Recursion is only natively supported when rwlocks are disabled (--disable-apcu-rwlocks)  at build time, it is otherwise supported with a thread local counter.

This requires much testing, consider this a call for testers ...

Tuesday, 10 November 2015

Help Required with Broken Things

Fig 1. A priceless artefact from antiquity.

Humans are a terrible bunch; Give them ancient, priceless artefacts to care for, and they'll snap the beards off them and stick them back together with pound shop (99c store) epoxy.

In August 2014, that literally happened.

Apparently, the museum has world class conservation equipment, and experts. So repair was carried out internally, at the museum.

Imagine that you were responsible for advertising for the job of "Repair Man for King Tut's Beard".

What would that advert look like ?

Fig 2. Required: Repair Man for King Tut's Beard

Using just the features of blogger, I have conveyed everything important about the problem with a picture and a few words.

The words could have been almost anything "Help Required with Broken Things" would have done the job.

Asking for Help

 

Every one of us depends directly on code that was authored by somebody else. That may have always been the case to some degree, but in the modern ecosystem, we can directly contact the authors the majority of the time; We can open a bug on github, or some other bug tracking software.

Directly interacting with the authors of some code, so quickly, and with such little effort, feels pretty new to me; a product of our collaborative ecosystem.

Another, less obvious product, might be the programming language barriers that are erected by interactions between ecosystems that support, mutually or otherwise, other ecosystems; Such as the internals ecosystem which speaks in C, and the userland ecosystem which speaks in PHP.

Language barrier or not, we appear to make assumptions about the authors of some code, that we know are not true for code that we have authored ourselves.

This can lead us to omit almost everything important from our bug reports, or when asking for help ... 

Our bug reports and questions can tend to have content that amounts to "Help Required with Broken Things".

The Ideal

 

If a bug is caused or effected by configuration or environment, then that's important information, however it is rarely enough to describe the configuration, environment, or even content of your code.

In the cases where only description is enough, it is obvious.

In cases where we think code is paramount, we are mostly aware.

What we are not always sure of, is how to include "our whole application" in a bug report, or question.

Stackoverflow has an excellent description of what reproducing code should look like, and even how to create it.

The Real World

 

We don't live in an ideal world, and we can't always create MCVE's.

I don't want to discourage anyone from reporting bugs or asking questions, at all.

So, open your issue, report your bug, ask your question, with whatever information you have.

But, you already know that it may not be actionable until it contains a MVCE.

A worthy observation is that in the course of trying to create an MVCE, you will, at the very least, find that you are able to describe the problem in more and more detail.

Trying can either lead to reproducing code, or the kind of detail that might make your query actionable.

Please try ...

Tuesday, 22 September 2015

The Worth of Advice

Fig 1. An extremely confusing sign

I've written on my blog, spoken in my talk, told strangers on the train: You should not use multi-threading at the front end of a web application, it does not make sense when the threading model is 1:1.

Regardless of the fact that I wrote pthreads, and I know very well what is suitable and what is not, my advice is ignored: I get endless bug reports and questions with example code containing HTML line breaks, and reports that Apache or FPM is not behaving itself.

This is no real surprise, why should anyone listen to me ...

You ruddy well will listen to me, this morning I released v3.0.6 of pthreads and it disables the ability to load pthreads anywhere but the CLI.

When I first wrote pthreads, I wanted the barrier to entry to be low. Years later, I can see clearly that was a stupid thing to aim for; The barrier to entry is not low no matter what I do.

I thought it's no big deal if someone wants to use pthreads in their webserver, pthreads uses all the right API's it should be safe, even if it's not a good idea.

I was totally wrong. It's not safe, and never will be.

When I say safe here, I don't necessarily mean safe in the re-entrant, thread safety sense. What I mean is logically sound, which includes safe in the concurrency sense of the word.

Rather than trying to focus on making pthreads accessible, I have switched my focus to making pthreads v3 robust, reliable, predictable. These are the things that are really important when you are writing multi-threaded code, ease of use or accessibility shouldn't even be on the list of things you want a multithreading API to be.

I think, I can claim a modicum of success, even though v3 is not widely used yet.

Code that didn't work before, or behaved strangely, just works now. pthreads is faster, it's simpler internally. It is more accessible and easier to use. But, not because I aimed for those things, but because I aimed for predictability.

All the while, people were still able to ignore probably the most important piece of advice I ever give.

To show that my distain for using threads in a webserver runs deep among all programmers that understand the systems they are using, and is not in any way specific to PHP, pthreads, Apache or FPM:

This response was given to a person asking if it's okay to multithread in a web response inside IIS (C#):

http://stackoverflow.com/a/23915256/1658631

Many such questions can be found on stackoverflow, the best answer isn't always the accepted one. People tend to accept what they wanted to hear.

EJB's expressly prohibit the programmer from creating threads by specification, and modern Java doesn't even have a 1:1 model. Obviously, this is mostly because the environment may be migrated (moved within a cluster of servers), moving threads outside of it's managed pool is difficult to imagine. It goes further than prohibiting the creation of threads though, it prohibits the use of synchronization primitives, because what if a node is moved while you retain a lock - all hell breaks loose.

In Java generally, you are discouraged from manually creating threads in Servlets, for all the same reasons I have discouraged it for pthreads.

While it's true that not every environment will actually prohibit it, it runs as deep as can be; Everyone agrees that creating real (1:1) threads in a web response context is a bad idea.

If you're creating threads inside your multi-process, multi-threaded Apache environment, and you see this as a restriction, you're wrong, just like I was wrong to allow it.

Advice is, quite obviously, only worth something if you are going to listen to it.

Maybe I wasn't ignored, maybe pthreads has a farther reach than the advice that accompanies it, I don't know. It doesn't matter now, pthreads won't work in these environments ...

It's okay to be wrong, it's an opportunity to learn, to do things the correct way ... take the opportunity.

I'm going to go back to code now ...

Tuesday, 15 September 2015

What Polly Really Wants

Fig 1. Definition of polyfill according to Wikipedia
I think that a rather narrow definition, nevertheless it shows the origin of the word to be specifically Javascript and client side development.

Slowly but surely, this has become part of the PHP vernacular, everyone has heard of password_compat. A polyfill for PHP7's random_* API is also available.

I think we know what a polyfill is, or can skim the definition ... because I'm going to keep using that word.

Recently a fellow githubber opened an issue for pthreads, they are writing a static analysis suite for PHP, and are attempting to integrate pthreads into their code. First thing to say is, I don't know where that will lead him. But it does give him the problem that a lot of environments don't have pthreads available, and or they aren't using a thread safe interpreter.

In the issue, he made the suggestion that we have a compatibility layer, a polyfill. I confess, this had never occurred to me before.

Not only does it solve his problem but it actually serves as a useful tool ... I shall explain.


The Unanswerable Question


I'm often asked the question "what is a good use case for threading?". I'll stare open mouthed at the asker, or squint and tilt my head awkwardly in response. In a way it's like being asked the question "what is a good use case for objects?".

I'll go on to try to explain this is some awkward way, never really knowing if I am making sense.

I can't answer that question, it doesn't really make sense. Maybe someone can, but not me.

A question that does make sense is "what kind of code lends itself to threading?". To this we can give a pretty good answer.

First we can make the assumption that your are only considering threading because you have a lot of work to do, if that's not the case, do something else. Assuming there is a lot of work to do, then whether you have the kind of task that could gain anything by using threads depends on the nature of the work. This seems kinda obvious, but if every detail is explained, then more people will understand, I think.

If the kind of work you have to do can be broken down into units of work, each fulfilling the following requirements:

  • does not depend on other units of work
  • does not communicate with other units of work

You can be pretty sure that you have a good candidate.

These basic guidelines are extremely useful. Good multi-threaded code avoids synchronization, because there is too much margin for error and the unexpected, even with the best API in the world. Even with the best API, and the best programmers, synchronization (which must occur for units of work to communicate) diminishes performance, creates contention for locks, and is generally a bad thing.

If you are not dependant on the order of execution, you could (and at some point might have to) write your own scheduler (Pool::submit) to exploit hardware, and your software, to the fullest.

If you know enough to see the cases where those rules can be broken, then you don't need my help and can stop reading, I bid you farewell and good luck.

If you are still reading then I must be making sense, so we will now look at how you can use the polyfill as a tool.


New Rule: Training Shoe Slogans Are Always Wrong!


When it comes to researching multi threaded php, you should not "Just Do it".

In fact, there are very few occasions where such an attitude would be advisable, so, new rule.

If you think you have the kind of code that can take advantage, then you should test the waters. Before you change your PHP installation, or development environments, you should try to write your code using the polyfill.

When you start to win, and you have things the way you want them, you can load pthreads. Save for final optimization for real threads, reducing synchronization, and communication with non Threaded objects, if at this time you do not see a visible benefit, the best advice I can give is go in another direction.

Throwing threads at any task doesn't necessarily make it faster, and if at this early stage in development you are not seeing a visible benefit, then in all likelihood, there isn't any benefit to be had, simple as that.

If you do see a benefit, then you don't need to be worried about deployment problems and dependency on pthreads, if pthreads is available the units of work execute in parallel, if not, they don't. Everything works in a predictable way, everywhere.


Final Thought


My final words should pay homage to the observation that the best ideas aren't always our own, I'm really grateful when fellow programmers try to engage on github, or by any other means. They don't have to do that.

So, thank you ovrweb for taking the time.

Tuesday, 8 September 2015

Addendum: Letter from the Future

Fig 1. Some PHP7 logos
A couple of weeks ago, I wrote about my efforts to port pthreads to PHP7, to make it worthy of the shiny new platform.

Work continued on pthreads, and today I'm going to take the opportunity to update my previous blog post with some correction and extension.

With PHP7 in RC2, I'm sure everyone is a bit tired of blog posts about how quick PHP7 is and why it is so quick, so we're not going into that today. We will be looking at the performance of pthreads in particular.

Corrections

 

Last time I wrote about v3, it was still under development, and while the pthreads test suite passed, complex code of the kind you cannot include in an extension test suite didn't work as expected. I knew about it at the time but we were talking about untagged, unreleased code.

Note that we are still talking about untagged, unreleased code. However, this is only because the route to release is not very clear for PHP7 extensions yet, with no pear/pecl support.

Serialization Hack 

 

I previously wrote that you would be able to serialize Threaded objects like any other in PHP. I have to retract that statement; I overlooked the fact that a serialization hack is required to make Threaded objects behave as expected when they themselves are members of objects which are not Threaded (and so are serialized).

So, the hack got put back in, a bit tidier this time, and is used much less frequently than before, because no need for serialization of Threaded objects when they are members of other Threaded objects.

Note that, Threaded objects are still not serialized, only the serialize/unserialize handlers manipulated to pass around the address of an object, rather than a serial representation of the objects value.

Threaded Iteration

 

This has been improved yet again, we don't waste the memory to copy the set of keys as I previously said we would. Now we just iterate over the store copying keys and values as they are required for iteration, safely, obviously.

This couldn't be more efficient, nothing else to say about that.

Performance

 

It's going to be obvious that a Threaded object has quite some overhead associated with it, in order to provide implicit safety, store in a thread safe manner, and synchronize at the programmers will. What might not be obvious is just how many hoops pthreads has to jump through so that a programmer can manipulate one object in two contexts.

You cannot actually have an object in two contexts in a shared nothing environment, so that's the first thing to observe; There are actually O(n) objects where n is the number of contexts with a reference to the object.

But it gets worse, consider the following code:

<?php
class Test extends Thread {

 public function __construct(Threaded $threaded) {
  $this->member = $threaded;
 }

 public function run() {
  while (1) {
   $this->member->doStuff();
  }
 }
}
?>

Whenever $this->member is accessed in the thread, if you don't know that another context didn't change the reference, you have to undertake an enormous amount of work to provide the new context a reference to $this->member, at worst a new object is constructed every time.

In later versions of pthreads v2 there was a mechanism to reduce the number of constructions but it wasn't wholly effective, it leaked memory, with no chance to plug the leak. So this mechanism was removed from pthreads v3.

This means that not only are there O(n) objects where n is the number of contexts, but they must be constructed O(n) times where n is the number of accesses to the object in another context.

This is obviously extremely slow, and quite scary ...

For normal objects, objects that are not Threaded, we have little choice but to put up with the performance overhead of that. It should normally be the case that objects being used by Threads are Threaded, so this isn't much of a concern.

For Threaded objects though, this is just unacceptable.

Immutability to the Rescue


In pthreads v3, setting a member of a Threaded object (A) to another Threaded object (B) makes the reference that A holds to B immutable.

This means that during execution, once a member is set it cannot be unset or reset by any context, this means that the complexity for access is no longer O(n) but O(1).

Before you go batshit crazy about forcing immutability on the programmer, take a look at some numbers, and read what I have to say about it ...

Consider the following (quite normal, not super CPU intensive) code:

<?php
class My extends Threaded {
 public function method($i) {
  return 1 * $i;
 }
}

class Test extends Thread {
 public function __construct(Threaded $threaded) {
  $this->threaded = $threaded;
 }

 public function run() {
  while (@$i++<1000000) {
   $this->threaded[] = 
    $this->threaded->method($i);
  }
 }
}

$my = new My();
$test = new Test($my);
$test->start();
$test->join();
var_dump(count($my));
?>

Pretty standard stuff, and doesn't look that expensive, but because of the complexity of access in PHP5.6 and pthreads v2, measuring the user instructions and time taken to execute yields the following result:

  Performance counter stats for 'php time.php':

    14,547,244,407      instructions:u          

       2.133205136 seconds time elapsed

Note this is a late version of pthreads v2 with the aforementioned poor mechanism to reduce access complexity.

Same method, same machine, same extensions, PHP7 and pthreads v3 yields:

  Performance counter stats for 'php time.php':

     2,525,791,532      instructions:u          

       0.501464325 seconds time elapsed

Now that is more like it !!

A wise person once said "Never trust a benchmark you didn't fake yourself".

What we are looking at here is not really the time elapsed, for that will vary so much depending on so many things. We are interested in the number of user instructions executed because regardless of how long it takes, this gives you a good idea of how complex some user code is for the CPU.

Not only does immutability reduce the complexity of access considerably, it also allows us to avoid synchronization after the first access to $this->member in the new context. We can do this safely because we already have a reference to the object, constructed (synchronized) on the first access and stored locally to the thread and object, and we know that the reference is immutable.

Immutability breaks backward compatibility, but as mentioned, I don't care about that if I'm breaking something stupid or bad.

It pains me to say it, the amount of effort I put into making pthreads work is completely unreasonable, but it was both bad and stupid.

It may not seem like it initially, but immutability will become your best friend, very quickly.

 Volatility

 

This might be a new word to some PHP programmers, or one of those words that you heard but don't really know what it means, so here is the dictionary definition:

Fig 2. The definition of volatile, for reference.
An object that might change while being manipulated in many contexts is the epitome of volatility.

pthreads v3 introduces volatile objects to replace objects whose Threaded members are currently mutated by many contexts.

Volatile extends Threaded, so a Volatile object set as a member of a Threaded object still creates an immutable reference to the Volatile object, which is desirable because of access complexity, but the Volatile object itself is ... volatile.

Volatile objects are slow, with high access complexity, and should only be used when there is no other option.

The cost of all this ...

 

Nothing is without cost, it's arguable that multi-threaded programming in PHP just got harder to understand, but it is without question that it got so much faster that the set of power PHP programmers that use pthreads are not going to care.

Tuesday, 25 August 2015

A Letter from the Future

Fig 1. A sign post to the future (unverified).
The last few months have been a hectic time in the life of a PHP extension developer.: PHP7 approaches fast, with the first Release Candidate already out in the wild.

PHP7 probably feels like the future to you, but it's my here and now ... I wonder if that makes me a time traveller ... I digress ...

When it became apparent that the changes to PHP7 were rather significant for the kind of extensions I like to write, I was worried: I was worried because all the extensions I maintain, I'm able to maintain based on years of experience with PHP5, which I just didn't have for PHP7.

So I set to reading as much as I could, source code, blog posts and help from other internals contributors helped me stumble my way to familiarity, and with great pride I made an announcement on Twitter:



Outwardly I was happy to have succeeded in my task to make pthreads PHP7 compatible, however inwardly I struggled, I couldn't bring myself to tag a release, it just didn't feel right.

After a few days of reading and re-reading every line of pthreads while postponing tagging a release, I realized that I wanted to rewrite most of pthreads; Compatibility is not enough, worthiness is a better thing to strive for.

I always wanted to be the kind of person who could say "up side your head" or "he/she got game" without it being awkward for everyone present, alas, I am a programmer, with a beard. Humour me, read the next sentence in the knowledge that it fulfils a life long dream.

I think I'm justified in saying, with regard to PHP7 in particular, that she has without a shadow of a doubt, got game.

A change in attitude brought about PHP7; PHP5 matured with the attitude that if it works it's good enough. Most of the changes for PHP7 were made because of the realization that it was not good enough, and no matter what kind of disruption fixing it would bring, it would be worth it.

With my adjusted attitude, I set to work. I tore out the bad bits and rewrote or removed them until I had what we're going to call pthreads v3.

Removed Things

Before you shout about breaking code, I'm totally justified in removing some stuff because it's bad or stupid. I don't feel guilty about breaking bad or stupid code when I'm providing a superior path.

I want pthreads not only to be useful, but as far as possible I want it to be easy to write good code, some stuff just provided a direct path to crappy code.

Threaded::from

Not only were there bugs in the implementation, this was simply superseded by PHP7 support for anonymous classes, nice and simple.

Mutex and Cond

I mentioned as often as I could that these were never intended for wide use, they were present at the very beginning to help me develop and debug the extension.

Using mutex and condition variables directly in PHP is dangerous: You do not have enough control over execution to use them safely.

If you lock a mutex and then for whatever reason (perhaps an unexpected exception changes the code path, or a fatal engine error occurs) you do not unlock it, the next context to call lock will deadlock.

They were never required, there is synchronization methods built into Threaded objects.

Threaded::isWaiting

There is something seriously wrong with code designed to detect if an object is waiting for notification, any such code is written misunderstanding synchronization.

Threaded::lock and Threaded::unlock

This amounts to using mutex directly in userland, and presents the same kinds of dangers.

Synchronization of an objects properties or state should be only achieved with Threaded::synchronized.

In pthreads v2, Threaded::synchronized only synchronized state, not the properties table, so lock and unlock seemed reasonable.

Method Modifiers - Special Behaviour

In pthreads v2, a protected method could only be executed by one context at a time and a private method could only be executed inside the thread context.

That seemed useful, however, it was unreliable because of the way functions are cached in the core and called by various extensions in the wild.

Removing this special behaviour allows Zend to cache function pointers normally, making calls to Threaded methods a bit quicker and less complex.

Threaded::synchronized is now suitable for implementing exclusion reliably.

Improved Things

I've tried to look over pthreads with the same kind of critical attitude that brought PHP7 into existence. This has resulted in many improvements and much nicer code, the inner workings of pthreads are even starting to look simple.

Serialization Hack for Threaded Objects

In any version of PHP, objects cannot be shared among many contexts, normal objects are just serialized because it's the safest (and only) thing you can reasonably do.

In pthreads v2, Threaded objects were not serialized, each context with a reference to a Threaded object has a distinct physical object in it's own object store, but they share a physical thread safe property store and some other stuff (state etc). This was facilitated by a hack to the serialization handlers that passed around, I'm ashamed to say - as a string - the physical address of Threaded objects.

This is obviously crap, so I removed that completely. You can now serialize a Threaded object just like any other in pthreads v3.

Threaded Object Iteration

As mentioned, Threaded objects don't use a normal property store, so iteration needs implementing for these objects.

In pthreads v2, when you begin iterating over a Threaded object the entire custom property store is converted to a normal HashTable of zvals for Zend.

This is not so bad for tiny objects, but it is bad for complicated or big objects, or loops where you intend to break out early.

In pthreads v3, when you begin iteration over a Threaded object, just the keys are copied for the iterator and each value in the property store is converted JIT.

This keeps memory usage down and is much more suitable in the general case.

Threaded Object Monitor

I've pinched the term Monitor from Java. I'm sure you can find a detailed explanation if you're interested in the fine detail, suffice to say for now that a monitor is a mutex, condition, and state, that are used to implement critical sections - where only one thread may travel that path at a time.

In pthreads v2, there was no uniform monitor, there were separate structures, with separate locks as well as a lock on the object itself.

This was pretty terrible of me. Indefensible.

In pthreads v3 there is one monitor for each object, not only does that make the internals easier to understand and debug, it makes synchronization much more powerful and predictable in userland.

Worker and Pool

In pthreads v2, using a Worker directly was a tricky business; The programmer needs to retain a reference to any object who may be executed, if they don't, faults will follow swiftly.

This was in part solved by the provided Pool implementation which maintained references for the programmer, but because PHP (everything is a hashtable) it done so consuming a lot of memory that was difficult to keep track and control of.

The Pool::collect method allowed the programmer to forcibly free memory for a long running process, you pass Pool::collect a function that accepts a Threaded object and return true if the engine can free that object. All objects are passed to the collector regardless of if they have been executed or not.

In pthreads v3, Pool::collect has been moved to Worker::collect, and it's now Worker that maintains references to objects on the stack, this means that you no longer need to retain references to objects who may be executed.

Worker::collect is more efficient because you only traverse a list of garbage, in addition the structure is no longer a HashTable, but a custom structure, fit for purpose.

What's Next ?

As of today, I haven't tagged a release, I'm still testing all these changes with the help of a few dedicated users, consider this an invitation to join in the testing.

I'm pretty happy with the shape of things now, a release will be tagged soon, and I can move onto the next extension.

I'm going to go back to code now ...

Tuesday, 28 July 2015

The Universe is NOT Aware

Fig 1: Part of the universe

I'm very mindful of speaking clearly, when I think people might be listening. It's extremely important to communicate ideas precisely, so that they can be understood with minimal effort on the part of your audience.

In my parallel PHP podcast and talk, and a previous blog post, I gave clear explanations of asynchronous and parallel concurrency.

I'm going to assume you haven't seen any of that, and repeat the explanation, with pretty pictures and some more thoughts ...

Let's imagine we have three distinct tasks to execute, the nature of those tasks is unimportant for the explanation.

Synchronous Execution


Following is a diagram of the synchronous execution of those tasks:

Fig 2: Synchronous Execution

This is the model we are all used too; instructions are executed in a linear fashion, one after the other, task after task.

This is easiest for everyone; It's easiest for the programmer using a language, and easiest for the engineers of the language.

Asynchronous Execution


Following is a diagram of the asynchronous execution of those tasks:

Fig 3: Asynchronous Execution

We can see that the instructions for each task are interleaved with each other, because of this, the tasks can be said to run concurrently with respect to each other.

This is what asynchronous concurrency looks like. 

On the face of it, it takes the same amount of time to execute asynchronous code as it does to execute synchronous code.

Asynchronous concurrency has it's most appropriate use case in I/O bound code: Synchronous code that is I/O bound spends a considerable time waiting for hardware to become available. Using non-blocking API's, and interleaving instructions, means that you can eliminate that waiting: When synchronous blocking code would have waited, asynchronous non-blocking code is ready to execute the instructions for another task. This reduces the overall time it takes to execute your tasks.

This is considerably more messy than synchronous code, from both the perspective of programmer and language engineer; Whether it's worth chopping and dicing your instructions such that they can be interleaved is a question you should always ask.

Parallel Execution


Following is a diagram of the parallel execution of those tasks:

Fig 4: Parallel Execution

We can see that the tasks more closely resemble their synchronous counter parts, but run concurrently with respect to time

The only way to do this is by utilizing more than one thread of execution.

This is what parallel concurrency looks like.

In theory, our code is three times faster than it is when executed synchronously. In practice, given the ability to execute in parallel we invariably want our tasks to communicate with each other. This introduces overhead associated with synchronization (locking), not only costing time, but considerable cognitive overhead for any real world parallel code.

Giving a best use-case is much harder than with asynchronous concurrency, because the applicable domain of parallel concurrency is vast in comparison.

What you can say is that you should aim for that diagram as an ideal, you should design your tasks such that they are, as far as possible, isolated and so incur the minimum possible overhead from synchronization.

 

Applying Knowledge


Imagine, if you will, a scientist who says that since the universe has awareness within it, the universe itself is aware.

This is a pretty blunt example, I'm sure everyone can see the error in that logic. 

But what if the assertion that the universe is aware was accompanied by "a kind of word salad" which somehow lends superficial plausibility to the idea.

I find it hard to imagine there is anyone who cannot understand the key differences between these models. I'm sure it's crystal clear in the readers mind, the differences and properties of these models are easily understood.

What might not be so easily understood, is how to apply that knowledge to a bigger system, with more complex ideas.

How do we describe the execution of a task which was offloaded to Gearman, or some other process; Can't we describe that as asynchronous concurrency (since the operating system might interleave the tasks) ?

That's confusing the universe (system) with what is going on in the universe (system).

No matter the size nor complexity of the system, the definitions given above stand. 

If you are interleaving instructions you are achieving asynchronous concurrency, if you are executing instructions in parallel, you are achieving parallel concurrency.

It has to be that simple; When we skew the lines, we describe something parallel as asynchronous, or vice versa, it tastes like word salad, and makes it difficult to understand what is really going on.

A long time ago, I used the words parallel and asynchronous interchangeably in some example code I have distributed, and I could whip myself for doing so. I done so at a time when I just wasn't aware of the confusion surrounding these terms, and assumed, wrongly, that I would be understood.

If you have a blog, or a podcast, or someone you are educating, or any reason to talk about this stuff, I implore you to triple check your language and ideas, before communicating them, and I'll be doing the same.

Wednesday, 22 July 2015

One of Them

FIG 1: Me, and my beard, talking at a conference.
In real life, I'm a pretty awkward guy at first; I'm prone to stuttering, have no sense of direction, I forget names, the faces of people I've met, places I've been, and find it impossible to be assertive, or confident in any way.

I'm pretty much a mess.

Some of these symptoms disappear once I get to know you better, but first impressions count for a lot. My small circle of friends just accept, thankfully, that they have to help me navigate the world if they want me around, and sometimes have to wait for the end of a sentence.

I'm okay with it, I don't live in the real world, so don't have to deal with real life very much. The written word, including code, is not usually awkward for me, it flows freely, though it may not always make sense.

I know I'm not alone, I know lots of people who work in Tech are the same; They will confidently talk about the pros and cons of their favourite systems in IRC all day long, but put them in a real life situation and they fall apart, can't make decisions and don't know who or where they are.

While I am at peace with my acute awkwardness, it so happens that I hugely admire anyone who is able to get up on a stage and hold an audience. It's worth noting that if it weren't for this breed of individual, there are things I would never have understood properly.

Not so many months ago, in a burst of uncharacteristic confidence, I decided I would submit a talk to the inaugural PHP South Coast. This is as local as a conference can get for me, there would be friendly faces (I might not know their names, or recognize them at first), and I chose a subject matter I know a fair amount about, parallel PHP.

The plan was to practice at my local meetup in Hampshire, however, because of real life that never happened.

In the last couple of weeks leading up to the conference my beloved partner and I discussed how the talk should go.

I arranged to drive two friends to the conference, and we thought we could go through my talk in the car. However, it was 7am and we wanted bacon, so that didn't happen either.

So there I was, scheduled to speak after the keynote from Cal Evans, having not practised talking to anyone, not even one person. A few of us got around a table, and I quickly ran through the outline of the talk, asked if anything was missing, and we discussed, for about 180 seconds, questions that could be asked.

I lapped up the keynote, it was funny, even emotional, well produced ... I totally forgot I was up next.

I went straight into the room where I was speaking, then left, walked around to the other side of the room, entered again, then left, went to the other side of the room and finally got my shit together and approached someone that looked like staff.

We couldn't get my laptop to work, which was embarrassing. A working laptop was hooked up, I got the attention of the room and heard myself shakily enter the world of the speaker.

I eventually got control of my voice, managed to get a couple of laughs, and I think confidently answer questions at the end.

It was over, I literally ran outside to a corner and smoked by myself, caught my breath, and began to look forward to the rest of the conference.

A short while later I tweeted:


 From the comfort of my office chair, the awkwardness of the experience for me is overshadowed by the sense of pride that I done it. 

It may not have been the best talk; I don't know if I stuttered during, or missed anything out. I know that it was short and the audience was left wanting more, and I was left looking forward to having the opportunity to speak again, and improving.

Photo at the top courtesy of Rob Allen, who was there and armed with a camera all day.

Monday, 8 June 2015

20 Years of PHP


On this day, 20 years ago, PHP version 1.0 debuted to the world; It was a way of escaping the horror of writing your CGI programs in Perl, or worse, with your own bespoke set of C functions (that you wrongly referred to as a framework internally).

You probably wouldn't recognize code from that era:




  Hey, you are using Netscape!



  Sorry, that record does not exist


  Welcome !

You have  credits left in your account.


Nor would you recognize how to install or execute the interpreter.

This begs an important question ...

Will we recognize PHP twenty years hence ?

The answer depends on what you think PHP is ...

The meaning of the (b)acronym PHP has changed over time, programmers tend to over think stuff.

When Suzuki or Honda engineers come up with a racing motorcycle, they call it the GSXR or CBR, these letters don't mean anything most of the time, they just sound cool.

PHP code has also changed over time, the meaning of the letters is as unimportant as the syntax.

If PHP is a syntax to you, perhaps you will not recognize it.

PHP is the communities that surround it, it is the programmers who work whenever they are able to better the language or extensions available for it, it is the many many workshops dependant on it for an income, the would-or-will-be 13 year olds trying to figure out just how arrays work tonight.

For as long as there is a thing we recognize as the internet, there will be all the things that make up PHP, I look forward to seeing what the next 20 years brings.

Monday, 12 January 2015

Mocking PHP

Fig 1. Some kind of horrific monkey-muppet-tellytubby hybrid.
Much to the dismay of every RoR fanboy that ever lived, I'm not going to break character and start mocking PHP in the literal, playground sense.

I'm talking, of course, about mocking internal PHP functions and methods, so that we can test code that relies upon them.

I work on a vast PHP code base, it is 3M LOC of PHP alone. It's somewhere between legacy and modern, work is ongoing. I imagine this is the position lots of us find ourselves in, it's certainly not the first time I found myself here.

When I joined the current project there were many many tests, they relied upon the kind of unholy magic that runkit allows you to perform, for the most part this worked okay for a while. However, runkit inexplicably caused many of the tests to fault, either at shutdown, or at random.

I'm a very vocal, even forceful advocate of running the latest and greatest versions of PHP, as a result of that, we wanted to get to testing with OpCache. We can't very well judge whether optimizations performed by opcache are causing our considerably complicated, and legacy code to fold under lab conditions if we cannot get to the end of a test suite without crashes.

So we were in a bit of a jam, I've always found runkit to be quite awkward, and now I'm staring its source code in the face knowing it represents a road block to my goal of running the latest stable versions of PHP, with the first decent optimizer that ever existed for Zend.

I tackled the problem with code, code which I was allowed by my gracious employer to open source.

Tackling the problem with code might have been the wrong thing, but we got a cool extension out of it so read on, whatever your thoughts on that.

The Root Problem

This is likely a problem we have all come across; while writing unit tests we have to dodge code that invokes internal functionality, such as fopen or file_get_contents, or we have to, in some sense, write our code in mind of testability.

We find ourselves wrapping internal functionality in what we playfully (read:wrongly) refer to as "utility classes", so that even our production code has the overhead associated with what we require at test time. This is really a quite horrible solution in 100 LOC, in 3M LOC it isn't a solution at all.

In the same way, using namespaces to avoid the problem is a gargantuan task in a legacy application that is of any size, and is a fragile solution whatever, in my opinion.

The Obvious Solution

runkit allows you to redefine internal functions or methods, but it does it with strings that contain code, in a pretty awkward way.

As mentioned, I had hit a wall in working out what was causing runkit to fail in our particular case, however did realize that we could do-over the bits of runkit that make sense in a more modern way.

The Modern Solution

Here is a test case, that although requires the uopz extension, is a self-contained test case that invokes a built-in PHP function.
/* composer.json:
{
 "require": {
  "phpunit/phpunit": "4.6.*@dev" 
 }
} */
require_once("vendor/autoload.php");

class Test extends PHPUnit_Framework_TestCase {

 public static function setupBeforeClass() {
  $fopen = uopz_copy("fopen");
  
  uopz_function("fopen", function($file, $mode) use ($fopen)
  {
   switch ($file) {
    case "test.stream":
     return STDOUT;
    
    default:
     return $fopen($file, $mode);
   }
  });
 }

 public function testOpenTestStreamIsResource() {
  $this->assertInternalType(
   'resource', fopen("test.stream", "w"));
 }

 public function testOpenTestStreamIsSTDOUT() {
  $this->assertEquals(
   fopen("test.stream", "w"), STDOUT);
 }

 public function testOpenOtherStreamIsNotSTDOUT() {
  $this->assertNotEquals(
   fopen("php://temp", "w"), STDOUT);
 }

 public static function tearDownAfterClass() {
  uopz_restore("fopen");
 }
}

Hopefully, it is obvious from the example that you can manipulate internal functions and methods in a much more fluid way than runkit allowed. The same kind of manipulations can be performed on user code.

In addition to the useful bits of runkit, uopz reimplements the useful bits of Sebastian's test_helpers extension, and a rather cool runtime class composition function.

Sebastian has expressed the desire to deprecate test_helpers in favour of uopz.

I'm not going to bore the reader with a bunch of example code, head over to the php manual to read more about what uopz can do.