I have recently spent quite a bit of time trying to come up with a better way to implement RESTful service that serve data in JSON. This is because most of our work these days involves writing client-side JavaScript apps that present a rich UI in the browser and then do all server-side interactions via AJAX. In pursuit of the best way to implement RESTful service on the backend, I have tried my hands at Go programming language, D programming language, Lua and of course Java and PHP. I was assuming that the Go or Lua would be much faster than PHP. Well, it turns out that at least without special optimizations, that is not the case.
I wrote the following programs to compare their performance:
<?php
header('Content-Type: application/json');
$db = new PDO('mysql:host=localhost;dbname=db;charset=utf8', 'user', 'pass');
$stmt = $db->query("SELECT * FROM node");
$result = array();
$result['list'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($result);
<?php
define('DRUPAL_ROOT', getcwd());
require_once DRUPAL_ROOT . '/includes/bootstrap.inc';
drupal_bootstrap(DRUPAL_BOOTSTRAP_DATABASE);
// drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
header('Content-Type: application/json');
$stmt = db_query("SELECT * FROM node");
$result = array();
$result['list'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($result);
json = require "cjson"
function json_result(key, data)
local result = {}
result[key] = data
ngx.say(json.encode(result))
end
function json_error(...)
local result = {}
result["message"] = string.format(...)
ngx.status = ngx.HTTP_INTERNAL_SERVER_ERROR
ngx.say(json.encode(result))
end
mysql = require "resty.mysql"
local db, err = mysql:new()
if not db then
json_error("failed to instantiate mysql: %s", err)
return
end
db:set_timeout(1000) -- 1 sec
local ok, err, errno, sqlstate = db:connect{
host = "127.0.0.1",
port = 3306,
database = "db",
user = "user",
password = "pass",
max_packet_size = 1024 * 1024
}
if not ok then
json_error("failed to connect: %s: %d %d", err, errno, sqlstate)
return
end
result, err, errno, sqlstate = db:query("SELECT * FROM node")
if not result then
json_error("failed to query: %s: %d %d", err, errno, sqlstate)
end
json_result("list", result)
The above programs simply query a table and return all rows and columns from that table as a JSON array.
And then I hit the above programs with a bit of load using 'ab' HTTP load testing command. Following are the results ...