Symfony2 versus Go: Round 1 – Hello world (static pages)

In my new job at Hailo we are introducing Go as the main language in the new architecture and because of that I have started playing with it. Besides that, there has been a lot of comments and opinions in both the Symfony2 and the PHP community regarding the TechEmpower framework benchmarks where Symfony2 appears at the bottom of the list for most of the tests.

Needless to say, PHP is and will always be slower than a compiled new-generation language. If it was faster… something would be absolutely wrong… but is this speed difference valuable? Most people will talk about the amount of servers you could save… and this is absolutely true. However, engineers able to develop applications in languages as Go or Scala are definitely more expensive and scarce so this is a cost and a risk to be taken into account as well.

Apart from that, comparing Symfony2 with Go is an absolute unfair and somehow even stupid comparison. Symfony2 is a full-stack PHP framework and because of that, it runs inside an existing web server as a module (being Apache, Nginx/PHP-FPM, etc) while with Go, we create a web-server within the code. So, it is comparing apples with bananas, but still, people like benchmarks, so there we go.

My whole idea for these series is to be able to somehow benchmark the difference if we decide to switch part of the application from PHP to Go (for instance, some slow API, some heavy calculation endpoint, etc…) and one of the easiest ways to do it without changing a lot of things is to use Apache mod_proxy extension to redirect some HTTP calls to a different port where Go would be listening. Of course, in a production environment, this would be done in some HTTP Load Balancer on top of our application, that might be Apache, Nginx, or other available options.

In our experiment, we will end up with these 2 urls: http://localhost/hello-php and http://localhost/hello-go. There will be Apache serving both but for the second one we will proxy the Request to another port where Go is listening. And this can be easily done with these lines in our VirtualHost configuration:

    ProxyPreserveHost on
    ProxyPass /hello-go http://localhost:8080/hello

And to build a simple hello world in Go, that listens on port 8080:

package main 
 
import (
    "net/http"
    "fmt"
)
 
func hello(w http.ResponseWriter, r *http.Request) {
      w.Header().Set("Content-Type", "text/html")
      fmt.Fprint(w, "Hello world, from Go!")
}  
 
func main() {
    http.HandleFunc("/hello", hello)
    http.ListenAndServe(":8080", nil)
}

And a Hello world in Symfony2 is something like this:

<?php
 
namespace Ricardclau\SymfonyVsGoBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Response;
 
class DefaultController extends Controller
{
    /**
     * @Route("/hello-php")
     */
    public function indexAction()
    {
        return new Response('Hello world, from PHP!');
    }
}

And if we use Apache Benchmark tool to benchmark the difference vs both calls we will get that our Symfony2 application is able to serve about 230 req/s and our Go endpoint can serve about 6300 req/s!.

So, for this particular case, without databases and not heavy business logic, Go is about 30 times faster than Symfony2. Pretty amazing, isn´t it? Let´s switch to Go? Well, let´s think about it a little bit.

If we were in a production environment, with a heavy traffic website, would we be serving static pages with PHP? Absolutely not! We would put Varnish or some other reverse proxy cache layer in front of our application! So, this difference is absolutely useless in real world applications! Of course, if you are confident with Go, you can develop your website entirely in Go and save some CPU cycles (and perhaps, even the Varnish setup) but again, if you are a CEO or the average Joe CTO who need to hire developers it is more likely that you can get 20 engineers with proper skills in PHP / Apache / Varnish than in Go.

To me, in this first experiment, the conclusion would be that for this case, switching to faster languages in absolutely worthless… but, what do you think about these numbers? In the following chapter of the series we will compare both stacks with database “select” queries and applications with intensive writing POST HTTP requests, so stay tuned for more crazy and perhaps stupid benchmarks!

You may also like...