69 comments

[ 5.3 ms ] story [ 125 ms ] thread
If the goal is to save resources, maybe it's worth switching to Go entirely.

It's a shame the article does not explain what was unsatisfactory about php-pm [1], which is a native php solution that also allows the application to boot just once for all requests.

[1] https://github.com/php-pm/php-pm

They mentioned php-pm, but marked it as unsatisfactory w/o providing any rationale.
(comment deleted)
40x speedup claim with 0 evidence or reproduction scenario. It's like that meme: "source: trust me dude". The conclusionnis: they made a middleware, something that nginx's auth module does.

I want to believe this. I want to be hyped. It sounds great. But there's no reproduction scenario. Some claims are also false (php doesn't kill the process to start the processing cycle). Others seem too good to be true - like 40x speedup.

It just smells like "hey, we are cool kids too, look at us, we're advertising using the hype that other kids use!".

If I'm able to reproduce 40x speedup, I'll so gladly eat my words and flame myself.

PHP is the worst programming language ever made in current widespread use. There was never an excuse to use it, there were always other options, even many years ago.

> "To them, we say “think again.” We believe that the only limit PHP has is the limit you set."

You shouldn't be writing PHP in the first place, and should slowly work to (incrementally, slowly) shift your codebase into any other programming language in existence if it is already written in PHP.

The core language is terribly designed. PHP 7 did not fix this. Even JavaScript is miles better (PHP has a type system equally as bad, if not worse).

Of course, this sentiment is unpopular, because you're never supposed to rewrite anything even incrementally, and Popular Means Quality, and saying otherwise is heresy.

I propose the more radical solution of killing PHP entirely (again, incrementally, slowly), and replace it entirely with the language of your choosing (maybe that's Go).

> There was never an excuse to use it, there were always other options, even many years ago.

What was the alternative to using php from 1996 to 2000 if you were running a small mom and pop isp and your customer base was requesting shopping carts, photo galleries, and blog like web capabilities?

In that era, the servers were pentiums of 75MHz.

Agreed.

Back then you primarily went one of two ways, Perl & PHP. PHP was by far the lowest barrier to development. Easy to enable PHP support in webservers, easy to incrementally increase usage in your platform alongside any static HTML.

PHP + mod_php moved away from needing to know what was happening on the server side.

Perl and the other cgi-bin integrations could be complicated, involved, requiring more specific configuration on the server side. Sure, it's not _that_ hard to do, but it does present a barrier to entry that PHP / mod_php handily solved.

By 1999, Zope, C CGIs, TCL (AOLServer), ColdFusion, Delphi HTTP Server, ASP, IIS ISAPI,...

More than two possible ways.

I'm sorry, I don't see anywhere where I said there were only two ways.
That is what I take from "Back then you primarily went one of two ways, Perl & PHP.".

As if everything else wasn't worth mentioning.

Back on my little bubble, the options listed by me were much more relevant.

When I wrote "PHP is obsolete" I emphasized that it was my favorite language back in 2000. It was a decent answer to the problems of the 1990s, but it has no place in modern life. The response on Hacker News was split:

https://news.ycombinator.com/item?id=9598309

> Even JavaScript is miles better (PHP has a type system equally as bad, if not worse).

That's just not true. Just one example: PHP will throw runtime errors when (1) an argument type being passed to a function does not match its corresponding declared parameter type and (2) a value being returned from a function does not match the declared function return type. In pure Javascript you can't restrict the types of objects being passed to or returned from a function.

Every language has a purpose, even if it doesn't fit your preferences.

For people new to development especially who may have started with some simple static HTML, just being able to rename a .html file to .php on a dirt cheap web host and have it "just work" is such a low barrier to entry that it is a tremendous learning tool.

People also like to forget that PHP scales down better than any language out there, making it a no-brainer decision for cheap hosting of small and simple sites.

When you start increasing traffic and throughput or building software to run an serious business, of course there are other great options.

Just remember that every language has a purpose even if it's not yours, otherwise it wouldn't exist.

Out of curiosity - have you ever actually programmed anything? You're angry, which I can understand, and hateful but you're providing zero facts to support your opinion. You sound like a child deciding what's cool to like and what's cool to bash. Naturally, with nothing to back your opinion up. So, do you even code?
There is a reason it's still popular. PHP has some advantages:

1) Rapid iteration: Edit a file, hit refresh, see your results.

2) Ease of deployment: SFTP your changes, done (obviously you wouldn't work this way for a serious project...)

3) Simple execution model: each request gets its own thread (or process), each request starts from scratch.

> PHP has a type system equally as [sic] bad, if not worse

PHP 7's type system is worse than Javascript's type system? I can't imagine any developer who has worked with both those languages agreeing with you. It sounds like you haven't done any serious PHP work for the last ten years or so, and your opinions haven't kept pace with reality.

What type system? In either case, seriously. The best thing that php has going for it is the community. No bs just make it work type of people. Everything else about php is terrifying
Ohhh is that so? Show me how you do the following in Javascript.

    try{
      $exceptionType = rand(1,10) > 5?     
        BadMethodCallException::class
        : LogicException::class;
      throw new $exceptionType("smartass");
    }
    catch(BadMethodCallException $typed_1){
      file_put_contents('php://stderr', "Bad method, ".$typed_1->getMessage());
    }
    catch(LogicException $typed_2){
      file_put_contents('php://stderr', "Bad logic, ".$typed_2->getMessage());
    }
or this:

    function lieToMe(PHPMailer\PHPMailer\PHPMailer $mailer){
      
    }
or this:

    $mailStrategy = new MailStrategy();
    $mailStrategy("email@example.com","Subject","Body");
Or any of the other actually cool things you get with PHP if you can cope with the language.

It's sad to see people who probably can't program a microwave diss an entire language they haven't ever actually used.

> we can no longer use f5-debug

Sums up what is still one of the major issue-slash-weirdness of the php dev world. For all the frameworks and language advance, despite xdebug existing for over 15 years and working great in pretty much any editor or IDE, most PHP dev including the "experienced" ones have no idea how to use a debugger, or if they do they don't apply it to PHP.

Can you imagine debugging your C/C++/Rust/Go/... programs by adding printf everywhere and re-run the whole thing ? Again and again to find which variable fail; while a simple step by step with watches would solve it in a single run, in a tenth of the time, without needing to crappify the source ? That's what 99% of PHP dev still do.

Even the javascript world have adopted proper debugger right in the browser. But in PHP it's so freaking terrible that when people need to solve a bug you don't hear "step until you spot the issue" but "var_dump all the things" or "log to the symfony debug bar !".

(comment deleted)
I still print debug quite often in Go, I don't thinks its always less efficient then a debugger, and even when it is I don't think its always 10x less efficient. I think it depends heavily on the type of software you're working on.

For webapps in particular there can be a lot of value in constantly reloading the page. For example it can allow you to more often visually inspect the page for ui/ux/performance improvements. Particularly in early stages of a user interface where you're still figuring things out.

> Can you imagine debugging your C/C++/Rust/Go/... programs by adding printf everywhere and re-run the whole thing ?

Yes, absolutely. This is my principal and nearly-exclusive method of debugging the distributed systems I work on all day.

same. i find a debugger useful for tracking down segfaults, but for debugging logic it's printf all the way.
It's true that for distributed systems, logging tends to work better/is a necessary first step. I'd still want to invest in an extensive test harness though, if you can afford that luxury. Usually this enables productive debugging for distributed systems code, which pays of quickly.
Agreed, a deterministic test harness is critical, especially when working on the inner components, like state machines.
There was one network monitoring company that used Smalltalk, and Smalltalk's ability to very rapidly save the entire memory image. Basically, for exceptions, a snapshot of the server's state could be saved off in addition to the log, then brought up later, completely live, with a debugger on that very method. (Definitely a distributed system, running on other people's hardware in other people's data centers.)

I worked at another company where we used a different kind of Smalltalk serialization to save the GUI's state in an auto-generated error email or log entry, so we could open the application in the exact same UI state when dealing with a bug.

Most people aren't working on distributed systems though, so debuggers work fine for them
well it's hard to find a race condition with a debugger. sometimes it would just work with the debugger since you slow down the program or maybe halt on the wrong places.
Sure, but I'd argue that most developers aren't working with code day in and day out where race conditions are a concern.
well it depends, I mostly try to create my code so that things can run in parallel.

I also barley use a debugger, even for code that does not run in parallel, mostly because I'm used to make logging calls at the right places so that I can find issues way faster than with a debugger (most often I'm only run into hard issues or issues where a debugger will fail, i.e. build scripts -_-)

The point is that the debugger is an essential tool for debugging because in most cases it will do what you want and is faster. Most coding errors are not race conditions. I don't know why everyone must pipe in with the edge cases where a debugger might not work. In 99% of scenarios where you want to test some code in a development environment, setting breakpoint is the quickest way to see what is wrong. Log output is useful too, and you will probably use both. But, if you are a developer and don't have the ability to step through your code in a debugger, many problems will take much longer to fix.
It depends what the issue is. I work on dys. systems almost exclusively and if you can reproduce locally, I can almost always run the project using multiple procs with a debugger attached to each one of them
It's often much faster to just print or dump some data to screen just to see where your assumptions have gone wrong. There's a point at which some bugs become more complex, or just aren't easily figured out from this method, but it's surprisingly quick and powerful when used in conjunction with a language in which doing so is quick and easy. Doing it in a project that requires a few minutes or more just to build can quickly change this equation, but this is my go-to initial method for debugging problems.

Then again, it's generally pretty easy for me since I develop with liberal use of debug messages and dumping of data structures at multiple locations depending on the value of the DEBUG environment variable. In production I just run without a DEBUG environment prefix and nobody is bothered by the verboseness, but if there's a problem, step one is generally just doing a test run with DEBUG=3 or something prefixing the command. It's a bit different for web-based scripts like in PHP, but not much so (just make it a param), as long as STDERR goes to a log file.

The php dev landscape is pretty wide. On the one hand there's wordpress developers that can only use "f5-debug", on the other hand there's software developers that use TDD with PHPUnit and Behat.
The thing I find most hard about WP development is that there isn't much else you can do. It's like one bootstrap file bootstrapping another, with hooks peppered throughout. The majority of your problems will lie in the integration of a handful of plugins. Otherwise, you're better off doing something else. It plays like a out of tune orchestra. Sure I could hook up xdebug. In fact I have in the past. I profiled the beast. The call graph made mu forehead feel like a lead weight.

But if I'm working on a project with components of my choosing, I'm free to make liberal use of PHPUnit, both for unit testing and heavier tests that involve the whole stack. Debugging isn't as smooth as debugging JS or typescript so I lean more on logs and object dumps. Might be different if I used PHPStorm but that feels sluggish to use - says something when I use Emacs with tonnes of packages.

It is possible to do higher quality programming in PHP but WP isn't a friendly environment for that. And environment goes a long way.

Is there empirical evidence to support the idea that PHP developers do not use xdebug? If not, perhaps you can explain why you think this?

I have largely stopped coding in PHP, but I did use xdebug when necessary. I have very little idea of other developers' workflows, but I am very skeptical of this claim.

I consulted with ~12 teams of PHP (not WordPress) developers between 2004 and 2016. Some were in the US, some in Europe.

Zero of them used xdebug until I forced them to.

Interesting. Which framework(s) were these teams using? How large were they?

xdebug is not always the most straightforward thing to set up. I don't tend to bother with it unless I am doing a lot of PHP development (which fortunately has not been the case recently). I've also had less cause to use it since the introduction of the Psy shell. It's still something that I would consider an essential tool, and I do wonder at the circumstances which allowed these teams to be able to get by without it, but the experience could maybe be a bit smoother. I did not think that the ST2/ST3 or Atom integration was that great; the best experience I had was with NetBeans, but NetBeans is otherwise pretty clunky. Presumably your mileage varies somewhat.

Frameworks varied, but included Laravel, Symfony, and Cake. Some code bases were spaghetti.

I agree that xdebug is hard to set up. I only had reproducible success with it after Vagrant became mainstream. Otherwise we had to share a dev server with all the team members in their own directories, and getting xdebug running on the dev server was a trial-and-error headache.

Debugging is one of the reasons I can’t recommend PHP to anyone for any purpose anymore.

I've been a PHP developer for a long time at many companies and I've always been the only one using xDebug.

People generally find setting it up confusing (which it can be).

Also xDebug can't discriminate if you have multiple projects running in one fpm etc which can be irritating if your request hit many of them (ie calls that can't be mapped in your debugging session).

> Can you imagine debugging your C/C++/Rust/Go/... programs by adding printf everywhere and re-run the whole thing ?

I'd say 90%-95% of the time that's entirely sufficient.

"The most effective debugging tool is still careful thought, coupled with judiciously placed print statements." - Brian Wilson Kernighan

That's really missing the best part of drop-in debugging, which is taking advantage of the REPL. You see what's wrong, and then can fiddle with code to see the exact lines of code to put in place to resolve the issue. REPL-driven development is pushed hard in e.g. Clojure land, but it's an insanely productive workflow in a ton of different languages
The only time I've found debuggers useful (vs. logs/prints) is when I inherit a pile of spaghetti code and want to see poke around at things. Other than that debuggers are much slower than running the code with a flag that enables the debug logging.

IMO the ability to easily diagnose and debug issues is a feature of the code/application and should be taken into account when writing it. Having to fall back on a debugger means your dealing with something not written with maintenance in mind.

I'm not sure what you're missing about using debuggers, but it's something. Breakpoints and stepping are massive time savers.

You can easily replace dozens of runs of a buggy program with a single debugging session. It's genuinely shocking that anyone would argue that debug mode is better.

You also need dozens of stepping and breakpoints with a debugger. A dozen of runs with printf doesn't take more time than a dozen of stepping within a debugger.

Reminds me of the classic old debate of command line vs GUI app. GUI might be easier to run, but command line apps are easier to automated, and overall better suited for power users.

Setting a breakpoint takes less time (and shows drastically more of the current state) than printf. Some breakpoints are automated, like breaking on exceptions.

There's also the problem that printf affects output for web programs and therefore isn't feasible if you want to eventually see what the output is.

It's like you have a sick patient and want to see how they're doing by cutting them in half. X-rays and scans make far more sense.

I think there is kind of a big difference though in that you don't have to compile php to execute scripts vs the languages you named. It's often just a lot faster to add a single loc to dump output to the page and immediately rerun the script and get immediate output. Debuggers are great, but not needed for the more simple bugs, which tend to be most common. If php devs had to wait a few minutes (or longer) to compile first, just dumping the output wouldn't be an efficient option. Not all bugs need tracing and stepping, but when they do it's great to be able to use the actual debugger.
I've found that it's only when I use a framework that I absolutely need X-Debug. Otherwise it's a nice-to-have but not a requirement.
php script life time is usually about 1 ms. dont you think attatching a debugger to that is a bit overkill !?
C/C++/Rust/Go: Compiled language Stockholm syndrome.

Time difference between printf() & F5 vs. setting up breakpoints and watch variables in a debugger is going to be negligible in something like Ruby/Python/PHP.

Also, everything is so damn framework-heavy these days that stepping until you strike gold can take a very long time. Super-verbose logging would probably be more effective.

Printf debugging works everywhere though. Debuggers are cool, but mostly what happens when I attach a debugger is I get to see all the things that timeout when I step through the code. Not to mention all the fun of trying to get remote debugging to work consistently... var_dump into a log file gives me what I need most of the time in seconds.
You want both methods, of course, but if I were forced to pick just one it would be printf-based.
I'm also one of those who switched from PHP to Go and now I have quite a bit of legacy PHP code that just works and don't have time to rewrite.

My solution:

Use a Go FastCGI client library to call PHP by talking directly to php-fpm. It saves on the HTTP request overhead and no need to run a web server. Actually, php-fpm is a decent application server itself.

Edit: Here's a link to example code: https://github.com/tomasen/fcgi_client

Without wanting to sound critical of this, they seem to have reinvented long-lived PHP servers. Gearman has allowed you to do this with PHP for almost ten years now, and it was even the case that you could plug it directly into mongrel2 with 0mq.

Fundamentally, it's an idea that works incredibly well - it's amazing that more people don't make use of it....

(comment deleted)
I had a similar idea a while back. The implementation I came up with (but never implemented) was to create a PHP extension that would link to a statically compiled GO module. Basically it would instantiate a network server on the GO side, and marshal the HTTP request/response data structures back and forth between PHP and Go. I imagined I would probably utilize a pthreads extension or one of the event loop extensions to handle each incoming request:

http://php.net/pthreads

http://php.net/manual/en/book.event.php

Can anyone dumb this down for me?

I don't really understand this use case - is this for PHP developers to eke out some more performance for their web apps?

The goridge library (https://github.com/spiral/goridge) makes a little more sense to me; it's a bridge between golang and PHP via RPC.

I went through the code (https://github.com/spiral/roadrunner) but it doesn't seem like something you can swap into an existing PHP project. Can anyone explain what use case this might be for?

In typical PHP applications, the entire application is bootstraped, executed and teared down for every request.

RoadRunner lets you run "workers" (php processes) that perform all the bootstrapping just once, and then receive-process-reply to requests. The use case is to avoid the (possibly expensive, especially with modern frameworks) bootstrapping for every request.

Check the symfony integration example for instance [1]. Everything that's outside of the

  while ($req = $psr7->acceptRequest()) {
  ...
  }
is usually run for every request in traditional PHP, whereas here it is only run once when initializing the worker and then that while block reads/executes/replies to each specific request.

The problem with this approach is that you now need to be careful not to leave unwanted stuff behind (open files / db connections, static $properties, etc.) that may interfere with future requests, whereas this just isn't possible in "normal" PHP. I would argue that this is one of the features that makes PHP so beginner-friendly.

[1] https://github.com/spiral/roadrunner/wiki/Symfony-Framework

am i missing something ? php-fpm can keep the process running as long as you want (pm.max_requests=0)
What you are missing is that, in php-fpm, while the interpreter process itself is not destroyed after every request, it does cleanup everything on the php-side (ie, it closes all open descriptors, it unloads all php code, etc.).

This is awesome ergonomically (because a past request cannot affect a future one in any way), but has terrible performance because all of the PHP code has to be re-bootstrapped for every request (think: read config files, open db connection, setup the injection-container, etc.).

Thus, this thing is like php-fpm but letting you bootstrap once and then just reply to requests within that php-space.

Aside from the "now you have an extra gun to shoot your foot with" issue, the other major difference is that php-fpm can execute any php file, whereas this approach requires a different process for each entry point (aka "front controller" in modern frameworks, aka "index.php").

This probably works ok, but it's doubling down on the terrible that is modern php. PHP has this wonderful conceptual model of get a request, return a response, and throw everything away. The logical consequence is that everything you built up in objects or variables along the way of making your response is garbage (because you're throwing it away when you're done).

Since you're just making garbage, it doesn't need to be pretty, it just needs to be fast.

Since you're making garbage, it doesn't need to be future proof, it will only be alive for 10ms.

You can make some really fast pages with PHP if you try, but modern frameworks are going to take longer to load than a fast page will take to be finished.

I think the standard PHP model (one process per request), while still popular, is being replaced with fairly robust event loops. I've been using Swoole (https://github.com/swoole/swoole-src) in my company for about a year now, and it has matured into quite a stable code base, even if the documentation is lacking at times. The performance is pretty phenomenal and it has useful async coroutines for interacting with redis/MySQL/PgSQL. I saw some benchmarks in their GitHub issues list where it outperformed Node and Go (taken with a pinch of salt obviously).

If you're afraid of something as experimental as Swoole, more stable options do exist, such as ReactPHP. Not quite as performant apparently, but seem to be popular.

In general, I find that the PHP ecosystem is still thriving. It's definitely one of the easier languages to get up and running with, and now thanks to the community, it's imbibing some of the more advanced features found in more modern languages.

I still love PHP, as much as the 10 year old me did when I started using it 20 years ago. It just gets the job done, even if it is a bit ugly at times!

Thank you for sharing your experience with swoole. I didn't know about swoole and will definately play with it to add to my options on future PHP projects.
FYI, the learning curve is a little steep due to lack of docs, but a friend of mine has started to put together https://swoole.co.uk, which tries to bridge the gaps.

Also, I believe swoole is used extensively by tencent/wechat, so we're in reasonable company!

Did they just reinvent FastCGI?
Usual question for this. How you handle sessions? The php built in is very bad if you recycle the main process.
Classic ASP is a similar framework to PHP. In Classic ASP there are a Session and a Application object. The Session object can store variables that will be available during the user session (using session cookie). And the Application object can store variables that will be available to all other scripts. So when the server starts, you put everything in the Application object, so when you get a new request, you load the data from the Application object instead of re-creating everything, doing database lookups etc on every request. This makes Classic ASP very performant with sub-millisecond requests. I used Classic ASP until recently and have now switched to Node.JS which uses an event loop. Per-request as in ASP and PHP is much easier then a event loop. In Node.JS for example, it's very common to pull in a framework like Express to do the routing, while PHP and ASP already do that job for you. One problem with ASP and PHP however - they're not optimal for real time stuff like chats or progress-bars.