Browse Source

Add the lapis framework to benchmarks

Tor Hveem 12 years ago
parent
commit
6066e1fa41
9 changed files with 478 additions and 0 deletions
  1. 38 0
      lapis/README.md
  2. 16 0
      lapis/benchmark_config
  3. 14 0
      lapis/config.lua
  4. 10 0
      lapis/config.moon
  5. 79 0
      lapis/mime.types
  6. 43 0
      lapis/nginx.conf
  7. 16 0
      lapis/setup.py
  8. 205 0
      lapis/web.lua
  9. 57 0
      lapis/web.moon

+ 38 - 0
lapis/README.md

@@ -0,0 +1,38 @@
+# Lapis (Nginx + Lua(jit + Lapis)  Benchmark Test
+
+The lua app is inside [web.lua](web.lua) which is compiled using [moonscript compiler](http://moonscript.org) from [web.moon](web.moon)
+The nginx conf is inside [nginx.conf](nginx.conf)
+Requires a nginx compiled with ngx_lua module, see [openresty.org](http://openresty.org), and ngxpostgres which is bundled with openresty.
+Requires [lapis framework](http://leafo.net/lapis) installed
+    
+    luarocks install lapis
+
+Requires postgresql hostname specified as IP address, if not possible then add resolver conf to nginx.conf.
+
+The lapis benchmark is using its ORM, and no raw queries.
+
+
+## Test URLs
+### JSON Encoding 
+
+http://localhost:8080/
+
+### Single Row Random Query
+
+http://localhost:8080/db
+
+### Variable Row Query Test
+
+http://localhost:8080/db?queries=2
+
+### Fortune URL
+
+http://localhost:8080/fortunes
+
+### DB Updates URL
+
+http://localhost:8080/update?queries=2
+
+### Plaintext URL
+
+http://localhost:8080/plaintext

+ 16 - 0
lapis/benchmark_config

@@ -0,0 +1,16 @@
+{
+  "framework": "lapis",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "sort": 143
+    }
+  }]
+}

+ 14 - 0
lapis/config.lua

@@ -0,0 +1,14 @@
+local config
+do
+  local _table_0 = require("lapis.config")
+  config = _table_0.config
+end
+config("development", function()
+  return postgresql_url("postgres://benchmarkdbuser:[email protected]/hello_world")
+end)
+return config("production", function()
+  port(80)
+  num_workers(4)
+  lua_code_cache("off")
+  return postgresql_url("postgres://benchmarkdbuser:[email protected]/hello_world")
+end)

+ 10 - 0
lapis/config.moon

@@ -0,0 +1,10 @@
+import config from require "lapis.config"
+
+config "development", ->
+  postgresql_url "postgres://benchmarkdbuser:[email protected]/hello_world"
+
+config "production", ->
+  port 80
+  num_workers 4
+  lua_code_cache "off"
+  postgresql_url "postgres://benchmarkdbuser:[email protected]/hello_world"

+ 79 - 0
lapis/mime.types

@@ -0,0 +1,79 @@
+types {
+    text/html                             html htm shtml;
+    text/css                              css;
+    text/xml                              xml;
+    image/gif                             gif;
+    image/jpeg                            jpeg jpg;
+    application/x-javascript              js;
+    application/atom+xml                  atom;
+    application/rss+xml                   rss;
+
+    text/mathml                           mml;
+    text/plain                            txt;
+    text/vnd.sun.j2me.app-descriptor      jad;
+    text/vnd.wap.wml                      wml;
+    text/x-component                      htc;
+
+    image/png                             png;
+    image/tiff                            tif tiff;
+    image/vnd.wap.wbmp                    wbmp;
+    image/x-icon                          ico;
+    image/x-jng                           jng;
+    image/x-ms-bmp                        bmp;
+    image/svg+xml                         svg svgz;
+    image/webp                            webp;
+
+    application/java-archive              jar war ear;
+    application/mac-binhex40              hqx;
+    application/msword                    doc;
+    application/pdf                       pdf;
+    application/postscript                ps eps ai;
+    application/rtf                       rtf;
+    application/vnd.ms-excel              xls;
+    application/vnd.ms-powerpoint         ppt;
+    application/vnd.wap.wmlc              wmlc;
+    application/vnd.google-earth.kml+xml  kml;
+    application/vnd.google-earth.kmz      kmz;
+    application/x-7z-compressed           7z;
+    application/x-cocoa                   cco;
+    application/x-java-archive-diff       jardiff;
+    application/x-java-jnlp-file          jnlp;
+    application/x-makeself                run;
+    application/x-perl                    pl pm;
+    application/x-pilot                   prc pdb;
+    application/x-rar-compressed          rar;
+    application/x-redhat-package-manager  rpm;
+    application/x-sea                     sea;
+    application/x-shockwave-flash         swf;
+    application/x-stuffit                 sit;
+    application/x-tcl                     tcl tk;
+    application/x-x509-ca-cert            der pem crt;
+    application/x-xpinstall               xpi;
+    application/xhtml+xml                 xhtml;
+    application/zip                       zip;
+
+    application/octet-stream              bin exe dll;
+    application/octet-stream              deb;
+    application/octet-stream              dmg;
+    application/octet-stream              eot;
+    application/octet-stream              iso img;
+    application/octet-stream              msi msp msm;
+
+    audio/midi                            mid midi kar;
+    audio/mpeg                            mp3;
+    audio/ogg                             ogg;
+    audio/x-m4a                           m4a;
+    audio/x-realaudio                     ra;
+
+    video/3gpp                            3gpp 3gp;
+    video/mp4                             mp4;
+    video/mpeg                            mpeg mpg;
+    video/quicktime                       mov;
+    video/webm                            webm;
+    video/x-flv                           flv;
+    video/x-m4v                           m4v;
+    video/x-mng                           mng;
+    video/x-ms-asf                        asx asf;
+    video/x-ms-wmv                        wmv;
+    video/x-msvideo                       avi;
+}

+ 43 - 0
lapis/nginx.conf

@@ -0,0 +1,43 @@
+#worker_processes  1;
+pid        /tmp/nginx.pid;
+error_log /dev/null crit;
+#error_log /tmp/test.log error;
+env LAPIS_ENVIRONMENT;
+
+events {
+    worker_connections 16384;
+}
+
+http {
+    access_log off;
+    include mime.types;
+    lua_package_path 'CWD/lapis/?.lua;;';	
+
+    upstream database {
+        postgres_server DBHOSTNAME dbname=hello_world user=benchmarkdbuser password=benchmarkdbpass;
+    }
+    server {
+        listen 8080;
+        lua_code_cache off;
+        charset "utf-8";
+
+        location / {
+            default_type text/html;
+            set $_url "";
+            content_by_lua_file "web.lua";
+        }
+
+        location /static/ {
+            alias static/;
+        }
+
+        location /favicon.ico {
+          alias static/favicon.ico;
+        }
+        location = /query {
+            internal;
+            postgres_pass database;
+            postgres_query $echo_request_body;
+        }
+    }
+}

+ 16 - 0
lapis/setup.py

@@ -0,0 +1,16 @@
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args):
+  setup_util.replace_text("lapis/nginx.conf", "CWD", os.getcwd())
+  setup_util.replace_text("lapis/nginx.conf", "DBHOSTNAME", args.database_host)
+  subprocess.Popen('/usr/local/openresty/nginx/sbin/nginx -c `pwd`/nginx.conf -g "worker_processes ' + str((args.max_threads)) + ';"', shell=True, cwd="lapis")
+
+  return 0
+
+def stop():
+  subprocess.Popen('/usr/local/openresty/nginx/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd="lapis")
+
+  return 0

+ 205 - 0
lapis/web.lua

@@ -0,0 +1,205 @@
+local lapis = require("lapis")
+local db = require("lapis.db")
+local Model
+do
+  local _table_0 = require("lapis.db.model")
+  Model = _table_0.Model
+end
+local config
+do
+  local _table_0 = require("lapis.config")
+  config = _table_0.config
+end
+local insert = table.insert
+local sort = table.sort
+local random = math.random
+local Fortune
+do
+  local _parent_0 = Model
+  local _base_0 = { }
+  _base_0.__index = _base_0
+  if _parent_0 then
+    setmetatable(_base_0, _parent_0.__base)
+  end
+  local _class_0 = setmetatable({
+    __init = function(self, ...)
+      if _parent_0 then
+        return _parent_0.__init(self, ...)
+      end
+    end,
+    __base = _base_0,
+    __name = "Fortune",
+    __parent = _parent_0
+  }, {
+    __index = function(cls, name)
+      local val = rawget(_base_0, name)
+      if val == nil and _parent_0 then
+        return _parent_0[name]
+      else
+        return val
+      end
+    end,
+    __call = function(cls, ...)
+      local _self_0 = setmetatable({}, _base_0)
+      cls.__init(_self_0, ...)
+      return _self_0
+    end
+  })
+  _base_0.__class = _class_0
+  if _parent_0 and _parent_0.__inherited then
+    _parent_0.__inherited(_parent_0, _class_0)
+  end
+  Fortune = _class_0
+end
+local World
+do
+  local _parent_0 = Model
+  local _base_0 = { }
+  _base_0.__index = _base_0
+  if _parent_0 then
+    setmetatable(_base_0, _parent_0.__base)
+  end
+  local _class_0 = setmetatable({
+    __init = function(self, ...)
+      if _parent_0 then
+        return _parent_0.__init(self, ...)
+      end
+    end,
+    __base = _base_0,
+    __name = "World",
+    __parent = _parent_0
+  }, {
+    __index = function(cls, name)
+      local val = rawget(_base_0, name)
+      if val == nil and _parent_0 then
+        return _parent_0[name]
+      else
+        return val
+      end
+    end,
+    __call = function(cls, ...)
+      local _self_0 = setmetatable({}, _base_0)
+      cls.__init(_self_0, ...)
+      return _self_0
+    end
+  })
+  _base_0.__class = _class_0
+  if _parent_0 and _parent_0.__inherited then
+    _parent_0.__inherited(_parent_0, _class_0)
+  end
+  World = _class_0
+end
+return lapis.serve((function()
+  local Benchmark
+  do
+    local _parent_0 = lapis.Application
+    local _base_0 = {
+      ["/"] = function(self)
+        return {
+          json = {
+            message = "Hello, World!"
+          }
+        }
+      end,
+      ["/db"] = function(self)
+        local num_queries = tonumber(self.params.queries) or 1
+        local worlds = { }
+        for i = 1, num_queries do
+          insert(worlds, World:find(random(1, 10000)))
+        end
+        return {
+          json = worlds
+        }
+      end,
+      ["/fortunes"] = function(self)
+        self.fortunes = Fortune:select("")
+        insert(self.fortunes, {
+          id = 0,
+          message = "Additional fortune added at request time."
+        })
+        sort(self.fortunes, function(a, b)
+          return a.message < b.message
+        end)
+        self.title = "Fortunes"
+        return self:html(function()
+          return element("table", function()
+            tr(function()
+              th(function()
+                return text("id")
+              end)
+              return th(function()
+                return text("message")
+              end)
+            end)
+            local _list_0 = self.fortunes
+            for _index_0 = 1, #_list_0 do
+              local fortune = _list_0[_index_0]
+              tr(function()
+                td(function()
+                  return text(fortune.id)
+                end)
+                return td(function()
+                  return text(fortune.message)
+                end)
+              end)
+            end
+          end)
+        end)
+      end,
+      ["/update"] = function(self)
+        local num_queries = tonumber(self.params.queries) or 1
+        local worlds = { }
+        for i = 1, num_queries do
+          local wid = random(1, 10000)
+          local world = World:find(wid)
+          world.randomnumber = random(1, 10000)
+          world:update("randomnumber")
+          insert(worlds, world)
+        end
+        return {
+          json = worlds
+        }
+      end,
+      ["/plaintext"] = function(self)
+        return {
+          content_type = "text/plain",
+          layout = false
+        }, "Hello, World!"
+      end
+    }
+    _base_0.__index = _base_0
+    if _parent_0 then
+      setmetatable(_base_0, _parent_0.__base)
+    end
+    local _class_0 = setmetatable({
+      __init = function(self, ...)
+        if _parent_0 then
+          return _parent_0.__init(self, ...)
+        end
+      end,
+      __base = _base_0,
+      __name = "Benchmark",
+      __parent = _parent_0
+    }, {
+      __index = function(cls, name)
+        local val = rawget(_base_0, name)
+        if val == nil and _parent_0 then
+          return _parent_0[name]
+        else
+          return val
+        end
+      end,
+      __call = function(cls, ...)
+        local _self_0 = setmetatable({}, _base_0)
+        cls.__init(_self_0, ...)
+        return _self_0
+      end
+    })
+    _base_0.__class = _class_0
+    if _parent_0 and _parent_0.__inherited then
+      _parent_0.__inherited(_parent_0, _class_0)
+    end
+    Benchmark = _class_0
+    return _class_0
+  end
+end)())

+ 57 - 0
lapis/web.moon

@@ -0,0 +1,57 @@
+lapis = require "lapis"
+db = require "lapis.db"
+import Model from require "lapis.db.model"
+import config from require "lapis.config"
+import insert from table
+import sort from table
+import random from math
+
+class Fortune extends Model
+
+class World extends Model
+
+lapis.serve class Benchmark extends lapis.Application
+  "/": =>
+    json: {message: "Hello, World!"}
+
+  "/db": =>
+    num_queries = tonumber(@params.queries) or 1
+    worlds = {}
+    for i = 1, num_queries
+      insert worlds, World\find random(1, 10000)
+    json: worlds
+
+  "/fortunes": =>
+    @fortunes = Fortune\select ""
+    insert @fortunes, {id:0, message:"Additional fortune added at request time."}
+    sort @fortunes, (a, b) -> a.message < b.message
+
+    @title = "Fortunes"
+    @html ->
+      element "table", ->
+        tr ->
+          th ->
+            text "id"
+          th ->
+            text "message"
+        for fortune in *@fortunes
+          tr ->
+            td ->
+              text fortune.id
+            td ->
+              text fortune.message
+
+  "/update": =>
+    num_queries = tonumber(@params.queries) or 1
+    worlds = {}
+    for i = 1, num_queries
+      wid = random(1, 10000)
+      world = World\find wid
+      world.randomnumber = random(1, 10000)
+      world\update "randomnumber"
+      insert worlds, world
+    json: worlds
+
+  "/plaintext": =>
+    content_type:"text/plain", layout: false, "Hello, World!"
+