Browse Source

Merge branch 'master' of gitlab.techempower.com:techempower/frameworkbenchmarks

Keith R. Gustafson 12 years ago
parent
commit
26633963cf
100 changed files with 1567 additions and 516 deletions
  1. 1 1
      README.md
  2. 21 3
      benchmarker.py
  3. 18 1
      config/create.js
  4. 21 0
      config/create.sql
  5. 34 0
      cowboy/README.md
  6. 24 0
      dancer/README.md
  7. 0 0
      dancer/__init__.py
  8. 32 0
      dancer/app.pl
  9. 18 0
      dancer/benchmark_config
  10. 37 0
      dancer/nginx.conf
  11. 32 0
      dancer/setup.py
  12. 33 0
      elli/README.md
  13. 24 0
      express/app.js
  14. 2 1
      express/benchmark_config
  15. 1 0
      express/package.json
  16. 20 0
      express/views/fortune.mustache
  17. 52 0
      framework_test.py
  18. 1 1
      gemini/.project
  19. 0 15
      gemini/Docroot/WEB-INF/GeminiHello-Base.conf
  20. 0 7
      gemini/Docroot/WEB-INF/GeminiHello-Dev.conf
  21. 5 3
      gemini/Docroot/WEB-INF/GeminiHello-Inverness.conf
  22. 2 16
      gemini/Docroot/WEB-INF/GeminiHello-Prod.conf
  23. 1 16
      gemini/Docroot/WEB-INF/GeminiHello.conf
  24. BIN
      gemini/Docroot/WEB-INF/lib/techempower.jar
  25. 16 0
      gemini/Docroot/WEB-INF/mustache/fortunes.mustache
  26. 9 0
      gemini/Docroot/WEB-INF/mustache/layout.mustache
  27. 0 10
      gemini/Docroot/WEB-INF/web.xml
  28. 1 1
      gemini/Source/hello/GhForm.java
  29. 1 1
      gemini/Source/hello/GhStore.java
  30. 65 0
      gemini/Source/hello/home/entity/Fortune.java
  31. 14 0
      gemini/Source/hello/home/handler/HelloHandler.java
  32. 1 0
      gemini/benchmark_config
  33. 2 2
      go/README.md
  34. 1 0
      go/benchmark_config
  35. 82 20
      go/src/hello/hello.go
  36. 14 0
      go/templates/fortune.html
  37. 9 0
      go/templates/layout.html
  38. 36 17
      installer.py
  39. 23 0
      kelp/README.md
  40. 0 0
      kelp/__init__.py
  41. 28 0
      kelp/app.pl
  42. 18 0
      kelp/benchmark_config
  43. 3 0
      kelp/conf/config.pl
  44. 37 0
      kelp/nginx.conf
  45. 32 0
      kelp/setup.py
  46. 32 0
      mojolicious/README.md
  47. 0 0
      mojolicious/__init__.py
  48. 29 0
      mojolicious/app.pl
  49. 18 0
      mojolicious/benchmark_config
  50. 37 0
      mojolicious/nginx.conf
  51. 32 0
      mojolicious/setup.py
  52. 32 21
      openresty/app.lua
  53. 2 1
      openresty/nginx.conf
  54. 2 2
      php-fuel/README.md
  55. 3 3
      php-kohana/README.md
  56. 2 2
      php-micromvc/README.md
  57. 2 2
      php-silex/README.md
  58. 3 3
      php-symfony2/README.md
  59. 4 4
      php-symfony2/app/config/config_prod.yml
  60. 3 3
      php-symfony2/web/app.php
  61. 1 0
      php/benchmark_config
  62. 51 0
      php/fortune.php
  63. 1 0
      php/setup.py
  64. 3 3
      phreeze/benchmark_config
  65. 8 13
      phreeze/deploy/nginx.conf
  66. 2 2
      phreeze/index.php
  67. 5 2
      phreeze/libs/verysimple/HTTP/RequestUtil.php
  68. 11 7
      phreeze/libs/verysimple/Phreeze/Controller.php
  69. 62 43
      phreeze/libs/verysimple/Phreeze/DataAdapter.php
  70. 14 11
      phreeze/libs/verysimple/Phreeze/GenericRouter.php
  71. 27 26
      phreeze/libs/verysimple/Phreeze/Phreezer.php
  72. 4 4
      phreeze/libs/verysimple/String/VerySimpleStringUtil.php
  73. 23 0
      plack/app.psgi
  74. 11 1
      play-scala/app/controllers/Application.scala
  75. 24 0
      play-scala/app/models/Fortune.scala
  76. 1 1
      play-scala/app/models/World.scala
  77. 18 0
      play-scala/app/views/fortune.scala.html
  78. 13 0
      play-scala/app/views/main.scala.html
  79. 1 0
      play-scala/benchmark_config
  80. 1 0
      play-scala/conf/routes
  81. 54 16
      play1/app/controllers/Application.java
  82. 3 3
      play1/benchmark_config
  83. 14 6
      play1/conf/application.conf
  84. 4 2
      play1/conf/routes
  85. 7 7
      play1/setup.py
  86. 1 1
      rack/README.md
  87. 1 1
      rails-stripped/README.md
  88. 1 1
      rails/README.md
  89. 6 0
      rails/app/controllers/hello_world_controller.rb
  90. 4 0
      rails/app/models/fortune.rb
  91. 12 0
      rails/app/views/hello_world/fortune.html.erb
  92. 1 3
      rails/app/views/layouts/application.html.erb
  93. 2 0
      rails/benchmark_config
  94. 1 0
      rails/config/routes.rb
  95. 4 4
      results/i7/20130415095717/db.csv
  96. 67 68
      results/i7/20130415095717/db/phreeze/raw
  97. 9 9
      results/i7/20130415095717/json.csv
  98. 62 64
      results/i7/20130415095717/json/phreeze/raw
  99. 4 4
      results/i7/20130415095717/query.csv
  100. 57 58
      results/i7/20130415095717/query/phreeze/raw

+ 1 - 1
README.md

@@ -2,7 +2,7 @@
 
 
 Guesses and anecdotes can dominate discussions about the performance of web application frameworks.  Here we attempt to provide some objective performance measures across a wide field of frameworks, covering several platforms: Go, Python, Java, Ruby, PHP, Clojure, Groovy, and JavaScript.  The tests exercise the frameworks' JSON seralization and object-relational model (ORM).  Future versions will exercise server-side template libraries and other computation.
 Guesses and anecdotes can dominate discussions about the performance of web application frameworks.  Here we attempt to provide some objective performance measures across a wide field of frameworks, covering several platforms: Go, Python, Java, Ruby, PHP, Clojure, Groovy, and JavaScript.  The tests exercise the frameworks' JSON seralization and object-relational model (ORM).  Future versions will exercise server-side template libraries and other computation.
 
 
-See results data we've collected from Amazon EC2 instances and our physical hardware at our blog. http://www.techempower.com/blog/2013/03/28/framework-benchmarks/
+Read more and see the results of our tests on Amazon EC2 and physical hardware at http://www.techempower.com/benchmarks/
 
 
 ## Running the test suite
 ## Running the test suite
 
 

+ 21 - 3
benchmarker.py

@@ -182,7 +182,10 @@ class Benchmarker:
     except ValueError:
     except ValueError:
       framework_id = str(framework.sort)
       framework_id = str(framework.sort)
       
       
-    
+    if test not in self.results['rawData'].keys():
+      self.results['rawData'][test] = dict()
+      self.results['weighttpData'][test] = dict()
+
     self.results['rawData'][test][framework_id] = results
     self.results['rawData'][test][framework_id] = results
     self.results['weighttpData'][test][framework_id] = dict()
     self.results['weighttpData'][test][framework_id] = dict()
     self.results['weighttpData'][test][framework_id]['latency'] = latency
     self.results['weighttpData'][test][framework_id]['latency'] = latency
@@ -301,7 +304,11 @@ class Benchmarker:
       # If the test is in the excludes list, we skip it
       # If the test is in the excludes list, we skip it
       if self.exclude != None and test.name in self.exclude:
       if self.exclude != None and test.name in self.exclude:
         continue
         continue
-
+      
+      # If the test does not contain an implementation of the current test-type, skip it
+      if self.type != 'all' and not test.contains_type(self.type):
+        continue
+      
       print textwrap.dedent("""
       print textwrap.dedent("""
       =====================================================
       =====================================================
         Beginning {name}
         Beginning {name}
@@ -421,6 +428,15 @@ class Benchmarker:
         framework = self.results['frameworks'][int(key)]
         framework = self.results['frameworks'][int(key)]
         writer.writerow([framework] + value)
         writer.writerow([framework] + value)
 
 
+    # Fortune CSV
+    with open(os.path.join(self.full_results_directory(), "fortune.csv"), 'wb') as csvfile:
+      writer = csv.writer(csvfile)
+      writer.writerow(["Framework"] + self.query_intervals)
+      if 'fortune' in self.results['rawData'].keys():
+        for key, value in self.results['rawData']['fortune'].iteritems():
+          framework = self.results['frameworks'][int(key)]
+          writer.writerow([framework] + value)
+
   ############################################################
   ############################################################
   # End __parse_results
   # End __parse_results
   ############################################################
   ############################################################
@@ -504,10 +520,12 @@ class Benchmarker:
       self.results['rawData']['json'] = dict()
       self.results['rawData']['json'] = dict()
       self.results['rawData']['db'] = dict()
       self.results['rawData']['db'] = dict()
       self.results['rawData']['query'] = dict()
       self.results['rawData']['query'] = dict()
+      self.results['rawData']['fortune'] = dict()
       self.results['weighttpData'] = dict()
       self.results['weighttpData'] = dict()
       self.results['weighttpData']['json'] = dict()
       self.results['weighttpData']['json'] = dict()
       self.results['weighttpData']['db'] = dict()
       self.results['weighttpData']['db'] = dict()
       self.results['weighttpData']['query'] = dict()
       self.results['weighttpData']['query'] = dict()
+      self.results['weighttpData']['fortune'] = dict()
     else:
     else:
       for x in self.__gather_tests():
       for x in self.__gather_tests():
         if x.name not in self.results['frameworks']:
         if x.name not in self.results['frameworks']:
@@ -526,4 +544,4 @@ class Benchmarker:
   # End __init__
   # End __init__
   ############################################################
   ############################################################
   
   
-  
+  

+ 18 - 1
config/create.js

@@ -5,4 +5,21 @@ for (var i = 1; i <= 10000; i++) {
 }
 }
 
 
 // http://docs.mongodb.org/manual/applications/optimization/
 // http://docs.mongodb.org/manual/applications/optimization/
-db.world.ensureIndex({id: 1})
+db.world.ensureIndex({id: 1})
+
+db.fortune.drop()
+
+db.fortune.save( {id: 1, message: 'fortune: No such file or directory'} );
+db.fortune.save( {id: 2, message: "A computer scientist is someone who fixes things that aren't broken."} );
+db.fortune.save( {id: 3, message: 'After enough decimal places, nobody gives a damn.'} );
+db.fortune.save( {id: 4, message: 'A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1'} );
+db.fortune.save( {id: 5, message: 'A computer program does what you tell it to do, not what you want it to do.'} );
+db.fortune.save( {id: 6, message: 'Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen'} );
+db.fortune.save( {id: 7, message: 'Any program that runs right is obsolete.'} );
+db.fortune.save( {id: 8, message: 'A list is only as strong as its weakest link. — Donald Knuth'} );
+db.fortune.save( {id: 9, message: 'Feature: A bug with seniority.'} );
+db.fortune.save( {id: 10, message: 'Computers make very fast, very accurate mistakes.'} );
+db.fortune.save( {id: 11, message: '<script>alert("This should not be displayed in a browser alert box.");</script>'} );
+db.fortune.save( {id: 12, message: 'フレームワークのベンチマーク'} );
+
+db.fortune.ensureIndex({id: 1})

+ 21 - 0
config/create.sql

@@ -35,3 +35,24 @@ END #
 DELIMITER ;
 DELIMITER ;
 
 
 CALL load_data();
 CALL load_data();
+
+DROP TABLE IF EXISTS Fortune;
+CREATE TABLE  Fortune (
+  id int(10) unsigned NOT NULL auto_increment,
+  message varchar(2048) CHARACTER SET 'utf8' NOT NULL,
+  PRIMARY KEY  (id)
+)
+ENGINE=INNODB;
+
+INSERT INTO fortune (message) VALUES ('fortune: No such file or directory');
+INSERT INTO fortune (message) VALUES ('A computer scientist is someone who fixes things that aren''t broken.');
+INSERT INTO fortune (message) VALUES ('After enough decimal places, nobody gives a damn.');
+INSERT INTO fortune (message) VALUES ('A bad random number generator: 1, 1, 1, 1, 1, 4.33e+67, 1, 1, 1');
+INSERT INTO fortune (message) VALUES ('A computer program does what you tell it to do, not what you want it to do.');
+INSERT INTO fortune (message) VALUES ('Emacs is a nice operating system, but I prefer UNIX. — Tom Christaensen');
+INSERT INTO fortune (message) VALUES ('Any program that runs right is obsolete.');
+INSERT INTO fortune (message) VALUES ('A list is only as strong as its weakest link. — Donald Knuth');
+INSERT INTO fortune (message) VALUES ('Feature: A bug with seniority.');
+INSERT INTO fortune (message) VALUES ('Computers make very fast, very accurate mistakes.');
+INSERT INTO fortune (message) VALUES ('<script>alert("This should not be displayed in a browser alert box.");</script>');
+INSERT INTO fortune (message) VALUES ('フレームワークのベンチマーク');

+ 34 - 0
cowboy/README.md

@@ -0,0 +1,34 @@
+# Cowboy Benchmarking Test
+
+This is the Cowboy portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test controller](src/json_handler.erl)
+
+
+### Data-Store/Database Mapping Test
+Uses the db abstraction class from Kohana
+
+* [DB test controller](src/db_handler.erl)
+
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Cowboy 0.8.3](https://github.com/extend/cowboy)
+* [Erlang R16B](http://www.erlang.org/)
+* [MySQL 5.5.29](https://dev.mysql.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db
+
+### Variable Query Test
+    
+http://localhost/db?queries=2

+ 24 - 0
dancer/README.md

@@ -0,0 +1,24 @@
+# Setup
+
+* Perl 5.16.3
+* MySQL 5.5
+* Wrk 2.0
+
+# Requirements
+
+* Dancer
+* Dancer::Plugin::Database
+* DBD::mysql
+* Starman (if using Starman as web server)
+* Plack (for plackup)
+* nginx (if you want to front Dancer with nginx, nginx.conf provided)
+
+# Deployment
+
+Something along the lines of
+
+    plackup -E production -s Starman --workers=2 -l /tmp/frameworks-benchmark.sock -a ./app.pl
+
+if you want to front it with nginx, otherwise
+
+    plackup -E production -s Starman --port=8080 --workers=2 -a ./app.pl

+ 0 - 0
dancer/__init__.py


+ 32 - 0
dancer/app.pl

@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use Dancer ':syntax';
+use DBI;
+
+set serializer => 'JSON';
+
+my $dsn = "dbi:mysql:database=hello_world;host=localhost;port=3306";
+my $dbh = DBI->connect( $dsn, 'benchmarkdbuser', 'benchmarkdbpass', {} );
+my $sth = $dbh->prepare("SELECT * FROM World where id = ?");
+
+get '/json' => sub {
+    { message => 'Hello, World!' }
+};
+
+get '/db' => sub {
+    my $queries = params->{queries} || 1;
+    my @response;
+    for ( 1 .. $queries ) {
+        my $id = int rand 10000 + 1;
+        $sth->execute($id);
+        if ( my $row = $sth->fetchrow_hashref ) {
+            push @response,
+              { id => $id, randomNumber => $row->{randomNumber} };
+        }
+    }
+    return \@response;
+};
+
+Dancer->dance;

+ 18 - 0
dancer/benchmark_config

@@ -0,0 +1,18 @@
+{
+  "framework": "dancer",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "port": 8080,
+      "sort": 76
+    },
+    "raw": {
+      "setup_file": "setup",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 77
+    }
+  }]
+}

+ 37 - 0
dancer/nginx.conf

@@ -0,0 +1,37 @@
+user USR;
+
+worker_processes 2;
+
+events {
+  worker_connections  1024;
+}
+
+http {
+  output_buffers   1 32k;
+  postpone_output  1460;
+
+  sendfile         on;
+  tcp_nopush       on;
+
+  tcp_nodelay      on;
+
+  upstream backendurl {
+    server unix:/home/ubuntu/FrameworkBenchmarks/dancer/frameworks-benchmark.sock;
+  }
+
+  server {
+    listen 8080;
+    server_name localhost;
+
+    location / {
+      try_files $uri @proxy;
+      access_log off;
+      expires max;
+    }
+
+    location @proxy {
+      proxy_set_header Host $http_host;
+      proxy_pass http://backendurl;
+    }
+  }
+}

+ 32 - 0
dancer/setup.py

@@ -0,0 +1,32 @@
+import subprocess
+import sys
+import setup_util
+from os.path import expanduser
+import os
+import getpass
+
+home = expanduser("~")
+
+def start(args):
+  setup_util.replace_text("dancer/app.pl", "localhost", ""+ args.database_host +"")
+  setup_util.replace_text("dancer/nginx.conf", "USR", getpass.getuser())
+  setup_util.replace_text("dancer/nginx.conf", "server unix:.*\/FrameworkBenchmarks", "server unix:" + home + "/FrameworkBenchmarks")
+
+  try:
+    subprocess.Popen("plackup -E production -s Starman --workers=" + str(args.max_threads) + " -l " + home + "/FrameworkBenchmarks/dancer/frameworks-benchmark.sock -a ./app.pl", shell=True, cwd="dancer")
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/dancer/nginx.conf", shell=True)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop():
+  try:
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
+    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+    out, err = p.communicate()
+    for line in out.splitlines():
+      if 'starman' in line:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 33 - 0
elli/README.md

@@ -0,0 +1,33 @@
+# Elli Benchmarking Test
+
+This is the Elli portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test controller](src/elli_bench_cb.erl)
+
+
+### Data-Store/Database Mapping Test
+
+* [DB test controller](src/elli_bench_cb.erl)
+
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Elli](git://github.com/knutin/elli)
+* [Erlang R16B](http://www.erlang.org/)
+* [MySQL 5.5.29](https://dev.mysql.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db
+
+### Variable Query Test
+    
+http://localhost/db?queries=2

+ 24 - 0
express/app.js

@@ -6,6 +6,7 @@
 var cluster = require('cluster')
 var cluster = require('cluster')
   , numCPUs = require('os').cpus().length
   , numCPUs = require('os').cpus().length
   , express = require('express')
   , express = require('express')
+  , mustacheExpress = require('mustache-express')
   , mongoose = require('mongoose')
   , mongoose = require('mongoose')
   , async = require('async')
   , async = require('async')
   , conn = mongoose.connect('mongodb://localhost/hello_world')
   , conn = mongoose.connect('mongodb://localhost/hello_world')
@@ -21,6 +22,11 @@ var cluster = require('cluster')
     randomNumber: Sequelize.INTEGER
     randomNumber: Sequelize.INTEGER
   }, {
   }, {
     freezeTableName: true
     freezeTableName: true
+  })
+  , Fortune      = sequelize.define('Fortune', {
+    message: Sequelize.STRING
+  }, {
+    freezeTableName: true
   });
   });
 
 
 var Schema = mongoose.Schema
 var Schema = mongoose.Schema
@@ -50,6 +56,10 @@ if (cluster.isMaster) {
     app.use(express.bodyParser());
     app.use(express.bodyParser());
     app.use(express.methodOverride());
     app.use(express.methodOverride());
     app.use(app.router);
     app.use(app.router);
+    app.engine('mustache', mustacheExpress());
+
+    app.set('view engine', 'mustache');
+    app.set('views', __dirname + '/views');
   });
   });
 
 
   app.configure('development', function() {
   app.configure('development', function() {
@@ -104,5 +114,19 @@ if (cluster.isMaster) {
     });
     });
   });
   });
 
 
+  app.get('/fortune', function(req, res) {
+    Fortune.findAll().success(function (fortunes) {
+      var newFortune = Fortune.build({message: "Additional fortune added at request time."});
+      fortunes.push(newFortune);
+      fortunes.sort(sortFortunes);
+
+      res.render('fortune', {fortunes: fortunes});
+    });
+  });
+
+  function sortFortunes(a, b) {
+    return (a.message < b.message) ? -1 : (a.message > b.message) ? 1 : 0;
+  }
+
   app.listen(8080);
   app.listen(8080);
 }
 }

+ 2 - 1
express/benchmark_config

@@ -18,8 +18,9 @@
       "setup_file": "setup",
       "setup_file": "setup",
       "db_url": "/sequelize",
       "db_url": "/sequelize",
       "query_url": "/sequelize?queries=",
       "query_url": "/sequelize?queries=",
+      "fortune_url": "/fortune",
       "port": 8080,
       "port": 8080,
       "sort": 6
       "sort": 6
     }
     }
   }]
   }]
-}
+}

+ 1 - 0
express/package.json

@@ -8,5 +8,6 @@
     , "async": "0.2.5"
     , "async": "0.2.5"
     , "sequelize": "1.6.0-beta4"
     , "sequelize": "1.6.0-beta4"
     , "mysql": "2.0.0-alpha7"
     , "mysql": "2.0.0-alpha7"
+    , "mustache-express": "0.2.1"
   }
   }
 }
 }

+ 20 - 0
express/views/fortune.mustache

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+{{#fortunes}}
+<tr>
+<td>{{id}}</td>
+<td>{{message}}</td>
+</tr>
+{{/fortunes}}
+</table>
+</body>
+</html>

+ 52 - 0
framework_test.py

@@ -141,10 +141,43 @@ class FrameworkTest:
       self.query_url_passed = True
       self.query_url_passed = True
     except (AttributeError, subprocess.CalledProcessError) as e:
     except (AttributeError, subprocess.CalledProcessError) as e:
       self.query_url_passed = False
       self.query_url_passed = False
+
+    # Fortune
+    try:
+      print "VERIFYING Fortune (" + self.fortune_url + ") ..."
+      url = self.benchmarker.generate_url(self.fortune_url, self.port)
+      subprocess.check_call(["curl", "-f", url])
+      print ""
+      self.fortune_url_passed = True
+    except (AttributeError, subprocess.CalledProcessError) as e:
+      self.fortune_url_passed = False
   ############################################################
   ############################################################
   # End verify_urls
   # End verify_urls
   ############################################################
   ############################################################
 
 
+  ############################################################
+  # contains_type(type)
+  # true if this test contains an implementation of the given 
+  # test type (json, db, etc.)
+  ############################################################
+  def contains_type(self, type):
+    try:
+      if type == 'json' and self.json_url != None:
+        return True
+      if type == 'db' and self.db_url != None:
+        return True
+      if type == 'query' and self.query_url != None:
+        return True
+      if type == 'fortune' and self.fortune_url != None:
+        return True
+    except AttributeError:
+      pass
+      
+    return False
+  ############################################################
+  # End stop
+  ############################################################
+
   ############################################################
   ############################################################
   # benchmark
   # benchmark
   # Runs the benchmark for each type of test that it implements
   # Runs the benchmark for each type of test that it implements
@@ -191,6 +224,19 @@ class FrameworkTest:
         print "Complete"
         print "Complete"
     except AttributeError:
     except AttributeError:
       pass
       pass
+
+    # fortune
+    try:
+      if self.fortune_url_passed and (self.benchmarker.type == "all" or self.benchmarker.type == "fortune"):
+        sys.stdout.write("BENCHMARKING Fortune ... ") 
+        remote_script = self.__generate_concurrency_script(self.fortune_url, self.port)
+        self.__run_benchmark(remote_script, self.benchmarker.output_file(self.name, 'fortune'))
+        results = self.__parse_test('fortune')
+        self.benchmarker.report_results(framework=self, test="fortune", requests=results['requests'], latency=results['latency'],
+          results=results['results'], total_time=results['total_time'], errors=results['errors'], total_requests=results['totalRequests'])
+        print "Complete"
+    except AttributeError:
+      pass
   ############################################################
   ############################################################
   # End benchmark
   # End benchmark
   ############################################################
   ############################################################
@@ -217,6 +263,12 @@ class FrameworkTest:
       results = self.__parse_test('query')
       results = self.__parse_test('query')
       self.benchmarker.report_results(framework=self, test="query", requests=results['requests'], latency=results['latency'],
       self.benchmarker.report_results(framework=self, test="query", requests=results['requests'], latency=results['latency'],
         results=results['results'], total_time=results['total_time'], errors=results['errors'], total_requests=results['totalRequests'])
         results=results['results'], total_time=results['total_time'], errors=results['errors'], total_requests=results['totalRequests'])
+
+    # Query
+    if os.path.exists(self.benchmarker.output_file(self.name, 'fortune')):
+      results = self.__parse_test('fortune')
+      self.benchmarker.report_results(framework=self, test="fortune", requests=results['requests'], latency=results['latency'],
+        results=results['results'], total_time=results['total_time'], errors=results['errors'], total_requests=results['totalRequests'])
   ############################################################
   ############################################################
   # End parse_all
   # End parse_all
   ############################################################
   ############################################################

+ 1 - 1
gemini/.project

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <projectDescription>
 <projectDescription>
-	<name>GeminiHello</name>
+	<name>FrameworkBenchmarks-Gemini</name>
 	<comment></comment>
 	<comment></comment>
 	<projects>
 	<projects>
 		<project>TechEmpower</project>
 		<project>TechEmpower</project>

+ 0 - 15
gemini/Docroot/WEB-INF/GeminiHello-Base.conf

@@ -414,21 +414,6 @@ MailServerCount = 1
 
 
 EmailerThreadsDaemon = yes
 EmailerThreadsDaemon = yes
 
 
-# StartupMailAuthor
-#   Specifies the email address to use when sending out the startup
-#   email.  This just needs to be specified so that the mail server
-#   won't reject it due to anti-spam measures.
-
-StartupMailAuthor = [email protected]
-
-# StartupMailRecipients
-#   When this Gemini application starts, Gemini will send an e-mail notice
-#   to the provided comma-separated list of recipients.  This notice can
-#   be useful for tracking when the site has been restarted.  If set to
-#   empty string, this functionality is disabled.
-
-StartupMailRecipients =
-
 # Mail Server blocks (where 'X' is a sequential ID of the mail servers
 # Mail Server blocks (where 'X' is a sequential ID of the mail servers
 # used by the application).
 # used by the application).
 #
 #

+ 0 - 7
gemini/Docroot/WEB-INF/GeminiHello-Dev.conf

@@ -10,9 +10,6 @@
 # Extend the baseline configuration.
 # Extend the baseline configuration.
 Extends = GeminiHello-Base.conf
 Extends = GeminiHello-Base.conf
 
 
-# TODO: Edit these settings according to the particulars of the
-# Development environments.
-
 DeploymentDescription = Development/${Servlet.MachineName}
 DeploymentDescription = Development/${Servlet.MachineName}
 
 
 # Database connectivity for Development.
 # Database connectivity for Development.
@@ -23,8 +20,4 @@ db.LoginPass = root
 # Disable outbound e-mail from the Development environment.
 # Disable outbound e-mail from the Development environment.
 OutboundMailEnabled = no
 OutboundMailEnabled = no
 
 
-# You may want to disable the last login update on Development.
-#BasicSecurity.UpdateLastLogin = no
-
-
 
 

+ 5 - 3
gemini/Docroot/WEB-INF/GeminiHello-Inverness.conf

@@ -9,7 +9,9 @@
 
 
 # Extend the development configuration, which in turn extends the
 # Extend the development configuration, which in turn extends the
 # baseline configuration.
 # baseline configuration.
-Extends = GeminiHello-Dev.conf
+Extends = GeminiHello-Prod.conf
+
+DeploymentDescription = Production/${Servlet.MachineName}
 
 
 # Now set any attributes that are specific to this machine.
 # Now set any attributes that are specific to this machine.
 
 
@@ -18,5 +20,5 @@ db.ConnectString = 172.16.98.98:3306/hello_world?jdbcCompliantTruncation=false&e
 Log.Console.On = yes
 Log.Console.On = yes
 Log.Console.LogDebugThreshold = 50
 Log.Console.LogDebugThreshold = 50
 
 
-#db.Driver.Pooling = 30
-#db.Driver.MaxPooling = 30
+db.Driver.Pooling = 30
+db.Driver.MaxPooling = 30

+ 2 - 16
gemini/Docroot/WEB-INF/GeminiHello-Prod.conf

@@ -10,9 +10,6 @@
 # Extend the baseline configuration.
 # Extend the baseline configuration.
 Extends = GeminiHello-Base.conf
 Extends = GeminiHello-Base.conf
 
 
-# TODO: Edit these settings according to the particulars of the
-# Production environment.
-
 DeploymentDescription = Production/${Servlet.MachineName}
 DeploymentDescription = Production/${Servlet.MachineName}
 
 
 # Database connectivity for Production.
 # Database connectivity for Production.
@@ -20,19 +17,8 @@ db.ConnectString = localhost:3306/gemini?jdbcCompliantTruncation=false&cachePrep
 db.LoginName = hello
 db.LoginName = hello
 db.LoginPass = hello
 db.LoginPass = hello
 
 
-# Mail server definition for the production environment.  TODO: Most
-# likely you shouldn't be using the TechEmpower mail server in 
-# Production, so change this.
-MailServerCount = 1
-MailServer1.ServerAddress = mail.techempower.com
-MailServer1.SmtpPort = 25
-MailServer1.PopPort = 110
-MailServer1.Username = mhixson
-MailServer1.Password = password
-MailServer1.ServerRole = Outbound
-
-# In production, we'll want to have the email exception handler enabled.
-EmailExceptionHandler.Enabled = true
+# For this application, we are not sending any outbound e-mail.
+OutboundMailEnabled = no
 
 
 # In production, refer to all the static assets via URLs with version strings to
 # In production, refer to all the static assets via URLs with version strings to
 # allow us to perform aggressive caching.
 # allow us to perform aggressive caching.

+ 1 - 16
gemini/Docroot/WEB-INF/GeminiHello.conf

@@ -76,7 +76,7 @@ ApplicationRoot = ${Servlet.ApplicationRoot}
 #   description is used to identify the installation in some system-
 #   description is used to identify the installation in some system-
 #   generated messages such as exception report e-mails.
 #   generated messages such as exception report e-mails.
 
 
-DeploymentDescription = Unspecified
+DeploymentDescription = Production
 
 
 
 
 # -----------------------------------------------------------------------
 # -----------------------------------------------------------------------
@@ -413,21 +413,6 @@ MailServerCount = 1
 
 
 EmailerThreadsDaemon = yes
 EmailerThreadsDaemon = yes
 
 
-# StartupMailAuthor
-#   Specifies the email address to use when sending out the startup
-#   email.  This just needs to be specified so that the mail server
-#   won't reject it due to anti-spam measures.
-
-StartupMailAuthor = [email protected]
-
-# StartupMailRecipients
-#   When this Gemini application starts, Gemini will send an e-mail notice
-#   to the provided comma-separated list of recipients.  This notice can
-#   be useful for tracking when the site has been restarted.  If set to
-#   empty string, this functionality is disabled.
-
-StartupMailRecipients =
-
 # Mail Server blocks (where 'X' is a sequential ID of the mail servers
 # Mail Server blocks (where 'X' is a sequential ID of the mail servers
 # used by the application).
 # used by the application).
 #
 #

BIN
gemini/Docroot/WEB-INF/lib/techempower.jar


+ 16 - 0
gemini/Docroot/WEB-INF/mustache/fortunes.mustache

@@ -0,0 +1,16 @@
+{{<layout}}
+{{$body}}
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+{{#.}}
+<tr>
+<td>{{id}}</td>
+<td>{{message}}</td>
+</tr>
+{{/.}}
+</table>
+{{/body}}
+{{/layout}}

+ 9 - 0
gemini/Docroot/WEB-INF/mustache/layout.mustache

@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+{{$body}}{{/body}}
+</body>
+</html>

+ 0 - 10
gemini/Docroot/WEB-INF/web.xml

@@ -50,14 +50,4 @@
   <!-- Use UTF-8 for everything. -->
   <!-- Use UTF-8 for everything. -->
   <character-encoding>UTF-8</character-encoding>
   <character-encoding>UTF-8</character-encoding>
 
 
-  <!-- Enable GZIP compression. -->
-  <!--
-  <filter filter-name="gzip" filter-class="com.caucho.filters.GzipFilter">
-    <init>
-      <use-vary>true</use-vary>
-    </init>
-  </filter>
-  <filter-mapping url-pattern='*' filter-name="gzip" />
-  -->
-
 </web-app>
 </web-app>

+ 1 - 1
gemini/Source/hello/GhForm.java

@@ -59,7 +59,7 @@ public class GhForm
   @Override
   @Override
   protected void onValidlySubmitted()
   protected void onValidlySubmitted()
   {
   {
-    // Does nothing.    
+    // Does nothing.
   }
   }
 
 
 }   // End GhForm.
 }   // End GhForm.

+ 1 - 1
gemini/Source/hello/GhStore.java

@@ -5,7 +5,6 @@ import hello.home.entity.*;
 import com.techempower.*;
 import com.techempower.*;
 import com.techempower.cache.*;
 import com.techempower.cache.*;
 import com.techempower.data.*;
 import com.techempower.data.*;
-import com.techempower.gemini.cluster.client.handler.*;
 import com.techempower.log.*;
 import com.techempower.log.*;
 
 
 /**
 /**
@@ -48,6 +47,7 @@ public class GhStore
     
     
     // Use EntityGroup rather than CacheGroup to ensure World entities are not cached.
     // Use EntityGroup rather than CacheGroup to ensure World entities are not cached.
     register(EntityGroup.of(World.class));
     register(EntityGroup.of(World.class));
+    register(EntityGroup.of(Fortune.class));
 
 
     // Register relationships.
     // Register relationships.
     // We have no relationships in this application.
     // We have no relationships in this application.

+ 65 - 0
gemini/Source/hello/home/entity/Fortune.java

@@ -0,0 +1,65 @@
+package hello.home.entity;
+
+import com.techempower.js.*;
+
+import hello.*;
+
+/**
+ * A fortune entity.
+ */
+public class   Fortune
+    extends    GhDataEntity
+    implements Comparable<Fortune>
+{
+
+  private String message;
+  
+  /**
+   * Default Constructor.
+   */
+  public Fortune()
+  {
+    // Does nothing.
+  }
+  
+  /**
+   * Set the message.  
+   */
+  public Fortune setMessage(String message)
+  {
+    this.message = message;
+    return this;
+  }
+  
+  /**
+   * Get the message.
+   */
+  public String getMessage()
+  {
+    return this.message;
+  }
+
+  /**
+   * A visitor factory used to map this class to JSON.
+   */
+  public static final VisitorFactory<Fortune> VISITOR_FACTORY = new VisitorFactory<Fortune>()
+  {
+    @Override
+    public Visitor visitor(Fortune fortune)
+    {
+      return Visitors.map(
+          "id", fortune.getId(),
+          "message", fortune.getMessage());
+    }
+  };
+
+  /**
+   * For our purposes, Fortunes sort by their message text. 
+   */
+  @Override
+  public int compareTo(Fortune other)
+  {
+    return getMessage().compareTo(other.getMessage());
+  }
+  
+}

+ 14 - 0
gemini/Source/hello/home/handler/HelloHandler.java

@@ -59,5 +59,19 @@ public class HelloHandler
     
     
     return json(worlds);
     return json(worlds);
   }
   }
+  
+  /**
+   * Fetch the full list of Fortunes from the database, sort them by the
+   * fortune message text, and then render the results to simple HTML using a 
+   * server-side template.
+   */
+  @PathSegment
+  public boolean fortunes()
+  {
+    final List<Fortune> fortunes = store.list(Fortune.class);
+    fortunes.add(new Fortune().setMessage("Additional fortune added at request time."));
+    Collections.sort(fortunes);
+    return mustache("fortunes", fortunes);
+  }
 
 
 }
 }

+ 1 - 0
gemini/benchmark_config

@@ -6,6 +6,7 @@
       "json_url": "/",
       "json_url": "/",
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/db?queries=",
       "query_url": "/db?queries=",
+      "fortune_url": "/fortunes",
       "port": 8080,
       "port": 8080,
       "sort": 0
       "sort": 0
     }
     }

+ 2 - 2
go/README.md

@@ -7,10 +7,10 @@ This is the go portion of a [benchmarking test suite](../) comparing a variety o
 
 
 ## Versions
 ## Versions
 
 
-* [Go 1.0.3](http://golang.org/)
+* [Go 1.1beta2](http://golang.org/)
 
 
 ## Test URLs
 ## Test URLs
 
 
 ### JSON Encoding Test
 ### JSON Encoding Test
 
 
-http://localhost:8080/json
+http://localhost:8080/json

+ 1 - 0
go/benchmark_config

@@ -6,6 +6,7 @@
       "json_url": "/json",
       "json_url": "/json",
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/db?queries=",
       "query_url": "/db?queries=",
+      "fortune_url": "/fortune",
       "port": 8080,
       "port": 8080,
       "sort": 27
       "sort": 27
     }
     }

+ 82 - 20
go/src/hello/hello.go

@@ -4,10 +4,12 @@ import (
 	"database/sql"
 	"database/sql"
 	"encoding/json"
 	"encoding/json"
 	_ "github.com/go-sql-driver/mysql"
 	_ "github.com/go-sql-driver/mysql"
+	"html/template"
 	"log"
 	"log"
 	"math/rand"
 	"math/rand"
 	"net/http"
 	"net/http"
 	"runtime"
 	"runtime"
+	"sort"
 	"strconv"
 	"strconv"
 )
 )
 
 
@@ -20,28 +22,50 @@ type World struct {
 	RandomNumber uint16 `json:"randomNumber"`
 	RandomNumber uint16 `json:"randomNumber"`
 }
 }
 
 
+type Fortune struct {
+	Id      uint16 `json:"id"`
+	Message string `json:"message"`
+}
+
 const (
 const (
-	DB_CONN_STR   = "benchmarkdbuser:benchmarkdbpass@tcp(172.16.98.98:3306)/hello_world?charset=utf8"
-	DB_SELECT_SQL = "SELECT id, randomNumber FROM World where id = ?;"
-	DB_ROWS       = 10000
+	DB_CONN_STR           = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world?charset=utf8"
+	DB_SELECT_SQL         = "SELECT id, randomNumber FROM World where id = ?"
+	DB_FORTUNE_SELECT_SQL = "SELECT id, message FROM Fortune;"
+	DB_ROWS               = 10000
+	MAX_CONN              = 80
 )
 )
 
 
 var (
 var (
-	db    *sql.DB
-	query *sql.Stmt
+	stmts        = make(chan *sql.Stmt, MAX_CONN)
+	fortuneStmts = make(chan *sql.Stmt, MAX_CONN)
+	tmpl         = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
 )
 )
 
 
+func init() {
+	//setup DB connection pool to work around Go issue #4805: https://code.google.com/p/go/issues/detail?id=4805&q=sql.db&colspec=ID%20Status%20Stars%20Priority%20Owner%20Reporter%20Summary
+	for i := 0; i < MAX_CONN; i++ {
+		db, err := sql.Open("mysql", DB_CONN_STR)
+		if err != nil {
+			log.Fatalf("Error opening database: %s", err)
+		}
+		stmt, err := db.Prepare(DB_SELECT_SQL)
+		if err != nil {
+			log.Fatal(err)
+		}
+		stmts <- stmt
+		fortuneStmt, err := db.Prepare(DB_FORTUNE_SELECT_SQL)
+		if err != nil {
+			log.Fatal(err)
+		}
+		fortuneStmts <- fortuneStmt
+	}
+}
+
 func main() {
 func main() {
 	runtime.GOMAXPROCS(runtime.NumCPU())
 	runtime.GOMAXPROCS(runtime.NumCPU())
-	var err error
-	if db, err = sql.Open("mysql", DB_CONN_STR); err != nil {
-		log.Fatalf("Error opening database: %s", err)
-	}
-	if query, err = db.Prepare(DB_SELECT_SQL); err != nil {
-		log.Fatalf("Error preparing statement: %s", err)
-	}
-	http.HandleFunc("/json", jsonHandler)
 	http.HandleFunc("/db", dbHandler)
 	http.HandleFunc("/db", dbHandler)
+	http.HandleFunc("/json", jsonHandler)
+	http.HandleFunc("/fortune", fortuneHandler)
 	http.ListenAndServe(":8080", nil)
 	http.ListenAndServe(":8080", nil)
 }
 }
 
 
@@ -53,16 +77,54 @@ func jsonHandler(w http.ResponseWriter, r *http.Request) {
 }
 }
 
 
 func dbHandler(w http.ResponseWriter, r *http.Request) {
 func dbHandler(w http.ResponseWriter, r *http.Request) {
-  	qnum := 1
-	if qnumStr := r.URL.Query().Get("queries"); len(qnumStr) != 0 {
-		qnum, _ = strconv.Atoi(qnumStr)
+	n := 1
+	if nStr := r.URL.Query().Get("queries"); len(nStr) != 0 {
+		n, _ = strconv.Atoi(nStr)
 	}
 	}
-	ww := make([]World, qnum)
-	for i := 0; i < qnum; i++ {
-		query.QueryRow(rand.Intn(DB_ROWS)+1).Scan(&ww[i].Id, &ww[i].RandomNumber)
+	ww := make([]World, n)
+	stmt := <-stmts //wait for a connection
+	for i := 0; i < n; i++ {
+		stmt.QueryRow(rand.Intn(DB_ROWS)+1).Scan(&ww[i].Id, &ww[i].RandomNumber)
 	}
 	}
-	w.Header().Set("Content-Type", "application/javascript")
+	stmts <- stmt //get a connection
 	j, _ := json.Marshal(ww)
 	j, _ := json.Marshal(ww)
+	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Content-Length", strconv.Itoa(len(j)))
 	w.Header().Set("Content-Length", strconv.Itoa(len(j)))
 	w.Write(j)
 	w.Write(j)
 }
 }
+
+func fortuneHandler(w http.ResponseWriter, r *http.Request) {
+	fortunes := make([]*Fortune, 0, 16)
+	stmt := <-fortuneStmts    //wait for a connection
+	rows, err := stmt.Query() //Execute the query
+	if err != nil {
+		log.Fatalf("Error preparing statement: %s", err)
+	}
+	i := 0
+	var fortune *Fortune
+	for rows.Next() { //Fetch rows
+		fortune = new(Fortune)
+		if err = rows.Scan(&fortune.Id, &fortune.Message); err != nil {
+			panic(err)
+		}
+		fortunes = append(fortunes, fortune)
+		i++
+	}
+	fortuneStmts <- stmt //return a connection
+	fortunes = append(fortunes, &Fortune{Message: "Additional fortune added at request time."})
+
+	sort.Sort(ByMessage{fortunes})
+	w.Header().Set("Content-Type", "text/html")
+	if err := tmpl.Execute(w, map[string]interface{}{"fortunes": fortunes}); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+}
+
+type Fortunes []*Fortune
+
+func (s Fortunes) Len() int      { return len(s) }
+func (s Fortunes) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+type ByMessage struct{ Fortunes }
+
+func (s ByMessage) Less(i, j int) bool { return s.Fortunes[i].Message < s.Fortunes[j].Message }

+ 14 - 0
go/templates/fortune.html

@@ -0,0 +1,14 @@
+{{define "content"}}
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+{{range .fortunes}}
+<tr>
+<td>{{.Id}}</td>
+<td>{{.Message}}</td>
+</tr>
+{{end}}
+</table>
+{{end}}

+ 9 - 0
go/templates/layout.html

@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+{{template "content" .}}
+</body>
+</html>

+ 36 - 17
installer.py

@@ -2,7 +2,7 @@ import subprocess
 import os
 import os
 
 
 class Installer:
 class Installer:
-  
+
   ############################################################
   ############################################################
   # install_software
   # install_software
   ############################################################
   ############################################################
@@ -22,7 +22,7 @@ class Installer:
     #######################################
     #######################################
     self.__run_command("sudo apt-get update", True)
     self.__run_command("sudo apt-get update", True)
     self.__run_command("sudo apt-get upgrade", True)    
     self.__run_command("sudo apt-get upgrade", True)    
-    self.__run_command("sudo apt-get install build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev python-software-properties unzip git-core libcurl4-openssl-dev libbz2-dev libmysqlclient-dev mongodb-clients libreadline6-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgdbm-dev ncurses-dev automake libffi-dev htop libtool bison libevent-dev libgstreamer-plugins-base0.10-0 libgstreamer0.10-0 liborc-0.4-0 libwxbase2.8-0 libwxgtk2.8-0 libgnutls-dev libjson0-dev libmcrypt-dev libicu-dev", True)
+    self.__run_command("sudo apt-get install build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev python-software-properties unzip git-core libcurl4-openssl-dev libbz2-dev libmysqlclient-dev mongodb-clients libreadline6-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgdbm-dev ncurses-dev automake libffi-dev htop libtool bison libevent-dev libgstreamer-plugins-base0.10-0 libgstreamer0.10-0 liborc-0.4-0 libwxbase2.8-0 libwxgtk2.8-0 libgnutls-dev libjson0-dev libmcrypt-dev libicu-dev cmake", True)
 
 
     self.__run_command("cp ../config/benchmark_profile ../../.bash_profile")
     self.__run_command("cp ../config/benchmark_profile ../../.bash_profile")
     self.__run_command("sudo sh -c \"echo '*               soft    nofile          8192' >> /etc/security/limits.conf\"")
     self.__run_command("sudo sh -c \"echo '*               soft    nofile          8192' >> /etc/security/limits.conf\"")
@@ -38,7 +38,7 @@ class Installer:
     self.__run_command("wget -O - http://binaries.erlang-solutions.com/debian/erlang_solutions.asc | sudo apt-key add -")
     self.__run_command("wget -O - http://binaries.erlang-solutions.com/debian/erlang_solutions.asc | sudo apt-key add -")
     self.__run_command("sudo apt-get update")
     self.__run_command("sudo apt-get update")
     self.__run_command("sudo apt-get install esl-erlang", True)
     self.__run_command("sudo apt-get install esl-erlang", True)
-    
+
     #
     #
     # Python
     # Python
     #
     #
@@ -62,10 +62,10 @@ class Installer:
     #
     #
     # Java
     # Java
     #
     #
-    
+
     self.__run_command("sudo apt-get install openjdk-7-jdk", True)
     self.__run_command("sudo apt-get install openjdk-7-jdk", True)
     self.__run_command("sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless", True)
     self.__run_command("sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless", True)
-    
+
     #
     #
     # Ruby/JRuby
     # Ruby/JRuby
     #
     #
@@ -76,7 +76,7 @@ class Installer:
     subprocess.call(["bash", "-c", "source ~/.rvm/scripts/'rvm' && rvm 2.0.0-p0 do gem install bundler"])
     subprocess.call(["bash", "-c", "source ~/.rvm/scripts/'rvm' && rvm 2.0.0-p0 do gem install bundler"])
     subprocess.call(["bash", "-c", "source ~/.rvm/scripts/'rvm' && rvm install jruby-1.7.3"])
     subprocess.call(["bash", "-c", "source ~/.rvm/scripts/'rvm' && rvm install jruby-1.7.3"])
     subprocess.call(["bash", "-c", "source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do gem install bundler"])
     subprocess.call(["bash", "-c", "source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do gem install bundler"])
-    
+
     # We need a newer version of jruby-rack
     # We need a newer version of jruby-rack
     self.__run_command("git clone git://github.com/jruby/jruby-rack.git")
     self.__run_command("git clone git://github.com/jruby/jruby-rack.git")
     subprocess.call(["bash", "-c", "cd installs/jruby-rack && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do bundle install"])
     subprocess.call(["bash", "-c", "cd installs/jruby-rack && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do bundle install"])
@@ -87,7 +87,14 @@ class Installer:
     # go
     # go
     #
     #
 
 
-    self.__run_command("curl http://go.googlecode.com/files/go1.1beta1.linux-amd64.tar.gz | tar xvz")
+    self.__run_command("curl http://go.googlecode.com/files/go1.1beta2.linux-amd64.tar.gz | tar xvz")
+
+    #
+    # Perl
+    #
+
+    self.__run_command("curl -L http://cpanmin.us | perl - --sudo App::cpanminus")
+    self.__run_command("cpanm -S DBI DBD::mysql Kelp Dancer Mojolicious Kelp::Module::JSON::XS Dancer::Plugin::Database Starman Plack JSON")
 
 
     #
     #
     # php
     # php
@@ -116,6 +123,18 @@ class Installer:
 
 
     self.__run_command("sudo apt-get install ghc cabal-install", True)
     self.__run_command("sudo apt-get install ghc cabal-install", True)
 
 
+    #
+    # RingoJs
+    #
+    self.__run_command("wget http://www.ringojs.org/downloads/ringojs_0.9-1_all.deb")
+    self.__run_command("sudo apt-get install jsvc")
+    self.__run_command("sudo dpkg -i ringojs_0.9-1_all.deb")
+    self.__run_command("rm ringojs_0.9-1_all.deb")
+    self.__run_command("sudo ringo-admin install oberhamsi/sql-ringojs-client")
+    self.__run_command("sudo ringo-admin install ringo/stick")
+    self.__run_command("sudo ringo-admin install oberhamsi/reinhardt")
+    self.__run_command("sudo ringo-admin install grob/ringo-sqlstore")
+
     #######################################
     #######################################
     # Webservers
     # Webservers
     #######################################
     #######################################
@@ -130,7 +149,7 @@ class Installer:
     self.__run_command("sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.orig")
     self.__run_command("sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.orig")
     self.__run_command("sudo sh -c \"cat ../config/ports.conf > /etc/apache2/ports.conf\"")
     self.__run_command("sudo sh -c \"cat ../config/ports.conf > /etc/apache2/ports.conf\"")
     self.__run_command("sudo /etc/init.d/apache2 stop")
     self.__run_command("sudo /etc/init.d/apache2 stop")
-    
+
     #
     #
     # Nginx
     # Nginx
     #
     #
@@ -138,7 +157,7 @@ class Installer:
     self.__run_command("./configure", cwd="nginx-1.2.7")
     self.__run_command("./configure", cwd="nginx-1.2.7")
     self.__run_command("make", cwd="nginx-1.2.7")
     self.__run_command("make", cwd="nginx-1.2.7")
     self.__run_command("sudo make install", cwd="nginx-1.2.7")
     self.__run_command("sudo make install", cwd="nginx-1.2.7")
-    
+
     #
     #
     # Openresty (nginx with openresty stuff)
     # Openresty (nginx with openresty stuff)
     #
     #
@@ -146,7 +165,7 @@ class Installer:
     self.__run_command("./configure --with-luajit", cwd="ngx_openresty-1.2.7.5")
     self.__run_command("./configure --with-luajit", cwd="ngx_openresty-1.2.7.5")
     self.__run_command("make", cwd="ngx_openresty-1.2.7.5")
     self.__run_command("make", cwd="ngx_openresty-1.2.7.5")
     self.__run_command("sudo make install", cwd="ngx_openresty-1.2.7.5")
     self.__run_command("sudo make install", cwd="ngx_openresty-1.2.7.5")
-    
+
     #
     #
     # Gunicorn
     # Gunicorn
     #
     #
@@ -224,7 +243,7 @@ class Installer:
     self.__run_command("wget http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.1.1.zip")
     self.__run_command("wget http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.1.1.zip")
     self.__run_command("unzip -o grails-2.1.1.zip")
     self.__run_command("unzip -o grails-2.1.1.zip")
     self.__run_command("rm grails-2.1.1.zip")
     self.__run_command("rm grails-2.1.1.zip")
-    
+
 
 
     ##############################
     ##############################
     # Flask
     # Flask
@@ -237,7 +256,7 @@ class Installer:
     self.__run_command("wget http://downloads.typesafe.com/play/2.1.1/play-2.1.1.zip")
     self.__run_command("wget http://downloads.typesafe.com/play/2.1.1/play-2.1.1.zip")
     self.__run_command("unzip -o play-2.1.1.zip")
     self.__run_command("unzip -o play-2.1.1.zip")
     self.__run_command("rm play-2.1.1.zip")
     self.__run_command("rm play-2.1.1.zip")
-    
+
     ##############################
     ##############################
     # Play 1
     # Play 1
     ##############################
     ##############################
@@ -245,7 +264,7 @@ class Installer:
     self.__run_command("unzip -o play-1.2.5.zip")
     self.__run_command("unzip -o play-1.2.5.zip")
     self.__run_command("rm play-1.2.5.zip")
     self.__run_command("rm play-1.2.5.zip")
     self.__run_command("mv play-1.2.5/play play-1.2.5/play1")
     self.__run_command("mv play-1.2.5/play play-1.2.5/play1")
-    
+
     # siena
     # siena
     self.__run_command("play-1.2.5/play1 install siena", send_yes=True)
     self.__run_command("play-1.2.5/play1 install siena", send_yes=True)
 
 
@@ -323,7 +342,7 @@ class Installer:
     ./waf build
     ./waf build
     sudo ./waf install
     sudo ./waf install
     cd ~
     cd ~
-    
+
     ##############################
     ##############################
     # wrk
     # wrk
     ##############################
     ##############################
@@ -339,16 +358,16 @@ class Installer:
     ##############################
     ##############################
     sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
     sudo apt-key adv --keyserver keyserver.ubuntu.com --recv 7F0CEB10
     sudo cp 10gen.list /etc/apt/sources.list.d/10gen.list
     sudo cp 10gen.list /etc/apt/sources.list.d/10gen.list
-    sudo apt-get update 
+    sudo apt-get update
     yes | sudo apt-get install mongodb-10gen
     yes | sudo apt-get install mongodb-10gen
-    
+
     sudo mv /etc/mongodb.conf /etc/mongodb.conf.orig
     sudo mv /etc/mongodb.conf /etc/mongodb.conf.orig
     sudo mv mongodb.conf /etc/mongodb.conf
     sudo mv mongodb.conf /etc/mongodb.conf
     sudo restart mongodb
     sudo restart mongodb
     """
     """
     p = subprocess.Popen(self.benchmarker.ssh_string.split(" "), stdin=subprocess.PIPE)
     p = subprocess.Popen(self.benchmarker.ssh_string.split(" "), stdin=subprocess.PIPE)
     p.communicate(remote_script)
     p.communicate(remote_script)
-    
+
   ############################################################
   ############################################################
   # End __parse_results
   # End __parse_results
   ############################################################
   ############################################################

+ 23 - 0
kelp/README.md

@@ -0,0 +1,23 @@
+# Setup
+
+* Perl 5.10+
+* MySQL 5.5
+* Wrk 2.0
+
+# Requirements
+
+* Kelp
+* DBD::mysql
+* Starman (if using Starman as web server)
+* Plack (for plackup)
+* nginx (if you want to front Dancer with nginx, nginx.conf provided)
+
+# Deployment
+
+Something along the lines of
+
+    plackup -E production -s Starman --workers=2 -l /tmp/frameworks-benchmark.sock -a ./app.pl
+
+if you want to front it with nginx, otherwise
+
+    plackup -E production -s Starman --port=8080 --workers=2 -a ./app.pl

+ 0 - 0
kelp/__init__.py


+ 28 - 0
kelp/app.pl

@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+use Kelp::Less;
+use DBI;
+
+my $dsn = "dbi:mysql:database=hello_world;host=localhost;port=3306";
+my $dbh = DBI->connect( $dsn, 'benchmarkdbuser', 'benchmarkdbpass', {} );
+my $sth = $dbh->prepare("SELECT * FROM World where id = ?");
+
+get '/json' => sub {
+    { message => 'Hello, World!' }
+};
+
+get '/db' => sub {
+    my $self = shift;
+    my $queries = $self->param('queries') || 1;
+    my @response;
+    for ( 1 .. $queries ) {
+        my $id = int rand 10000 + 1;
+        $sth->execute($id);
+        if ( my $row = $sth->fetchrow_hashref ) {
+            push @response,
+              { id => $id, randomNumber => $row->{randomNumber} };
+        }
+    }
+    return \@response;
+};
+
+run;

+ 18 - 0
kelp/benchmark_config

@@ -0,0 +1,18 @@
+{
+  "framework": "kelp",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "port": 8080,
+      "sort": 78
+    },
+    "raw": {
+      "setup_file": "setup",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 79
+    }
+  }]
+}

+ 3 - 0
kelp/conf/config.pl

@@ -0,0 +1,3 @@
+{
+    modules => ['JSON::XS']
+}

+ 37 - 0
kelp/nginx.conf

@@ -0,0 +1,37 @@
+user USR;
+
+worker_processes 2;
+
+events {
+  worker_connections  1024;
+}
+
+http {
+  output_buffers   1 32k;
+  postpone_output  1460;
+
+  sendfile         on;
+  tcp_nopush       on;
+
+  tcp_nodelay      on;
+
+  upstream backendurl {
+    server unix:/home/ubuntu/FrameworkBenchmarks/kelp/frameworks-benchmark.sock;
+  }
+
+  server {
+    listen 8080;
+    server_name localhost;
+
+    location / {
+      try_files $uri @proxy;
+      access_log off;
+      expires max;
+    }
+
+    location @proxy {
+      proxy_set_header Host $http_host;
+      proxy_pass http://backendurl;
+    }
+  }
+}

+ 32 - 0
kelp/setup.py

@@ -0,0 +1,32 @@
+import subprocess
+import sys
+import setup_util
+from os.path import expanduser
+import os
+import getpass
+
+home = expanduser("~")
+
+def start(args):
+  setup_util.replace_text("kelp/app.pl", "localhost", ""+ args.database_host +"")
+  setup_util.replace_text("kelp/nginx.conf", "USR", getpass.getuser())
+  setup_util.replace_text("kelp/nginx.conf", "server unix:.*\/FrameworkBenchmarks", "server unix:" + home + "/FrameworkBenchmarks")
+
+  try:
+    subprocess.Popen("plackup -E production -s Starman --workers=" + str(args.max_threads) + " -l " + home + "/FrameworkBenchmarks/kelp/frameworks-benchmark.sock -a ./app.pl", shell=True, cwd="kelp")
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/kelp/nginx.conf", shell=True)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop():
+  try:
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
+    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+    out, err = p.communicate()
+    for line in out.splitlines():
+      if 'starman' in line:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 32 - 0
mojolicious/README.md

@@ -0,0 +1,32 @@
+# Setup
+
+* Perl 5.16.3
+* MySQL 5.5
+* Wrk 2.0
+
+# Requirements
+
+* Mojolicious
+* Mojolicious::Plugin::Database
+* DBD::mysql
+* Starman (if using Starman as web server)
+* Plack (for plackup)
+* nginx (if you want to front Mojolicious
+with nginx, nginx.conf provided)
+* Morbo and Hypnotoad provided by Mojolicious
+
+# Deployment
+
+Set production mode:
+
+    export MOJO_MODE=production
+
+Something along the lines of
+
+    plackup -s Starman --workers=2 -l /tmp/frameworks-benchmark.sock -a ./app.pl
+
+if you want to front it with nginx, otherwise
+
+    plackup -s Starman --port 8080 --workers=2 -a ./app.pl
+
+or the equivalent Morbo or Hypnotoad commands.

+ 0 - 0
mojolicious/__init__.py


+ 29 - 0
mojolicious/app.pl

@@ -0,0 +1,29 @@
+#!/usr/bin/env perl
+use Mojolicious::Lite;
+use DBI;
+
+my $dsn = "dbi:mysql:database=hello_world;host=localhost;port=3306";
+my $dbh = DBI->connect( $dsn, 'benchmarkdbuser', 'benchmarkdbpass', {} );
+my $sth = $dbh->prepare("SELECT * FROM World where id = ?");
+
+get '/json' => sub {
+    my $self = shift;
+    $self->render( json => { message => 'Hello, world!' } );
+};
+
+get '/db' => sub {
+    my $self = shift;
+    my $queries = $self->param('queries') || 1;
+    my @response;
+    for ( 1 .. $queries ) {
+        my $id = int rand 10000 + 1;
+        $sth->execute($id);
+        if ( my $row = $sth->fetchrow_hashref ) {
+            push @response,
+              { id => $id, randomNumber => $row->{randomNumber} };
+        }
+    }
+    $self->render( json => \@response );
+};
+
+app->start;

+ 18 - 0
mojolicious/benchmark_config

@@ -0,0 +1,18 @@
+{
+  "framework": "mojolicious",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "port": 8080,
+      "sort": 80
+    },
+    "raw": {
+      "setup_file": "setup",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 81
+    }
+  }]
+}

+ 37 - 0
mojolicious/nginx.conf

@@ -0,0 +1,37 @@
+user USR;
+
+worker_processes 2;
+
+events {
+  worker_connections  1024;
+}
+
+http {
+  output_buffers   1 32k;
+  postpone_output  1460;
+
+  sendfile         on;
+  tcp_nopush       on;
+
+  tcp_nodelay      on;
+
+  upstream backendurl {
+    server unix:/home/ubuntu/FrameworkBenchmarks/mojolicious/frameworks-benchmark.sock;
+  }
+
+  server {
+    listen 8080;
+    server_name localhost;
+
+    location / {
+      try_files $uri @proxy;
+      access_log off;
+      expires max;
+    }
+
+    location @proxy {
+      proxy_set_header Host $http_host;
+      proxy_pass http://backendurl;
+    }
+  }
+}

+ 32 - 0
mojolicious/setup.py

@@ -0,0 +1,32 @@
+import subprocess
+import sys
+import setup_util
+from os.path import expanduser
+import os
+import getpass
+
+home = expanduser("~")
+
+def start(args):
+  setup_util.replace_text("mojolicious/app.pl", "localhost", ""+ args.database_host +"")
+  setup_util.replace_text("mojolicious/nginx.conf", "USR", getpass.getuser())
+  setup_util.replace_text("mojolicious/nginx.conf", "server unix:.*\/FrameworkBenchmarks", "server unix:" + home + "/FrameworkBenchmarks")
+
+  try:
+    subprocess.Popen("plackup -E production -s Starman --workers=" + str(args.max_threads) + " -l " + home + "/FrameworkBenchmarks/mojolicious/frameworks-benchmark.sock -a ./app.pl", shell=True, cwd="mojolicious")
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/mojolicious/nginx.conf", shell=True)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop():
+  try:
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
+    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+    out, err = p.communicate()
+    for line in out.splitlines():
+      if 'starman' in line:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 32 - 21
openresty/app.lua

@@ -1,30 +1,41 @@
+local _M = {}
+
 local cjson = require "cjson"
 local cjson = require "cjson"
 local mysql = require "resty.mysql"
 local mysql = require "resty.mysql"
 local math = require "math"
 local math = require "math"
 
 
-local mysqlconn = {
-    host = "DBHOSTNAME",
-    port = 3306,
-    database = "hello_world",
-    user = "benchmarkdbuser",
-    password = "benchmarkdbpass"
-}
+local encode = cjson.encode
+local random = math.random
+local insert = table.insert
+
 
 
-ngx.header.content_type = 'application/json'
+function _M.handler(ngx)
+    ngx.header.content_type = 'application/json'
+    
+    if ngx.var.uri == '/json' then
+        local resp = {message = "Hello, World!"}
+        ngx.print( encode(resp) )
+    elseif ngx.var.uri == '/db' then
 
 
-if ngx.var.uri == '/json' then
-    local resp = {message = "Hello, World!"}
-    ngx.print( cjson.encode(resp) )
+        local mysqlconn = {
+            host = "DBHOSTNAME",
+            port = 3306,
+            database = "hello_world",
+            user = "benchmarkdbuser",
+            password = "benchmarkdbpass"
+        }
 
 
-elseif ngx.var.uri == '/db' then
-    local db, err = mysql:new()
-    local ok, err = db:connect(mysqlconn)
-    local num_queries = tonumber(ngx.req.get_uri_args()["queries"]) or 1
-    local worlds = {}
-    for i=1, num_queries do
-        local wid = math.random(1, 10000)
-        table.insert(worlds, db:query('SELECT * FROM World WHERE id = '..wid)[1])
+        local db, err = mysql:new()
+        local ok, err = db:connect(mysqlconn)
+        local num_queries = tonumber(ngx.var.arg_queries) or 1
+        local worlds = {}
+        for i=1, num_queries do
+            local wid = random(1, 10000)
+            insert(worlds, db:query('SELECT * FROM World WHERE id = '..wid)[1])
+        end
+        ngx.print( encode(worlds) )
+        local ok, err = db:set_keepalive(0, 256)
     end
     end
-    ngx.print( cjson.encode(worlds) )
-    local ok, err = db:set_keepalive(0, 256)
 end
 end
+
+return _M

+ 2 - 1
openresty/nginx.conf

@@ -8,10 +8,11 @@ events {
 
 
 http {
 http {
     access_log off;
     access_log off;
+    lua_package_path 'CWD/openresty/?.lua;;';	
     server {
     server {
         listen       8080;
         listen       8080;
         location / {
         location / {
-            content_by_lua_file 'CWD/openresty/app.lua';
+            content_by_lua 'require("app").handler(ngx)';
         }
         }
     }
     }
 }
 }

+ 2 - 2
php-fuel/README.md

@@ -5,13 +5,13 @@ This is the FuelPHP portion of a [benchmarking test suite](../) comparing a vari
 ### JSON Encoding Test
 ### JSON Encoding Test
 Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
 Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
 
 
-* [JSON test controller](fuel/app/classes/controllers/bench.php)
+* [JSON test controller](fuel/app/classes/controller/bench.php)
 
 
 
 
 ### Data-Store/Database Mapping Test
 ### Data-Store/Database Mapping Test
 Uses the Fuel ORM
 Uses the Fuel ORM
 
 
-* [DB test controller](fuel/app/classes/controllers/bench.php)
+* [DB test controller](fuel/app/classes/controller/bench.php)
 
 
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions

+ 3 - 3
php-kohana/README.md

@@ -5,19 +5,19 @@ This is the Kohana PHP portion of a [benchmarking test suite](../) comparing a v
 ### JSON Encoding Test
 ### JSON Encoding Test
 Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
 Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
 
 
-* [JSON test controller](application/classes/controllers/Bench.php)
+* [JSON test controller](application/classes/Controller/Bench.php)
 
 
 
 
 ### Data-Store/Database Mapping Test
 ### Data-Store/Database Mapping Test
 Uses the db abstraction class from Kohana
 Uses the db abstraction class from Kohana
 
 
-* [DB test controller](application/classes/controllers/Bench.php)
+* [DB test controller](application/classes/Controller/Bench.php)
 
 
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
 The tests were run with:
 The tests were run with:
 
 
-* [Codeigniter Version 2.1.3](http://kohanaframework.org/)
+* [Kohana Version 3.3.0](http://kohanaframework.org/)
 * [PHP Version 5.4.13](http://www.php.net/) with FPM and APC
 * [PHP Version 5.4.13](http://www.php.net/) with FPM and APC
 * [nginx 1.2.7](http://nginx.org/)
 * [nginx 1.2.7](http://nginx.org/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)

+ 2 - 2
php-micromvc/README.md

@@ -5,13 +5,13 @@ This is the Micromvc portion of a [benchmarking test suite](../) comparing a var
 ### JSON Encoding Test
 ### JSON Encoding Test
 Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
 Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
 
 
-* [JSON test controller](index.php)
+* [JSON test controller](Class/Controller/Benchmark/Json.php)
 
 
 
 
 ### Data-Store/Database Mapping Test
 ### Data-Store/Database Mapping Test
 Uses the built-in ORM of micromvc
 Uses the built-in ORM of micromvc
 
 
-* [DB test controller](index.php)
+* [DB test controller](Class/Controller/Benchmark/Db.php)
 
 
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions

+ 2 - 2
php-silex/README.md

@@ -1,4 +1,4 @@
-# Cake PHP Benchmarking Test
+# Silex Benchmarking Test
 
 
 This is the Silex PHP portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 This is the Silex PHP portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 
 
@@ -17,7 +17,7 @@ Uses the Doctrine DBAL functionality.
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
 The tests were run with:
 The tests were run with:
 
 
-* [Symfony Version 2.2.1](http://silex.sensiolabs.org/)
+* [Silex Version 1.0](http://silex.sensiolabs.org/)
 * [PHP Version 5.4.13](http://www.php.net/) with FPM and APC
 * [PHP Version 5.4.13](http://www.php.net/) with FPM and APC
 * [nginx 1.2.7](http://nginx.org/)
 * [nginx 1.2.7](http://nginx.org/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)

+ 3 - 3
php-symfony2/README.md

@@ -1,4 +1,4 @@
-# Cake PHP Benchmarking Test
+# Symfony 2 Benchmarking Test
 
 
 This is the Symfony 2 PHP portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 This is the Symfony 2 PHP portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 
 
@@ -11,8 +11,8 @@ Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-
 ### Data-Store/Database Mapping Test
 ### Data-Store/Database Mapping Test
 Uses the Symfony 2/Doctrine 2 Entity functionality.
 Uses the Symfony 2/Doctrine 2 Entity functionality.
 
 
-* [DB test controller](src/Skamander/BenchmarkBundle/BenchController.php)
-* [DB test model](src/Skamander/BenchmarkBundle/World.php)
+* [DB test controller](src/Skamander/BenchmarkBundle/Controller/BenchController.php)
+* [DB test model](src/Skamander/BenchmarkBundle/Entity/World.php)
 
 
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions

+ 4 - 4
php-symfony2/app/config/config_prod.yml

@@ -11,11 +11,11 @@ framework:
     #validation:
     #validation:
     #    cache: apc
     #    cache: apc
 
 
-#doctrine:
-#    orm:
-#        metadata_cache_driver: apc
+doctrine:
+    orm:
+        metadata_cache_driver: apc
 #        result_cache_driver: apc
 #        result_cache_driver: apc
-#        query_cache_driver: apc
+        query_cache_driver: apc
 
 
 monolog:
 monolog:
     handlers:
     handlers:

+ 3 - 3
php-symfony2/web/app.php

@@ -8,10 +8,10 @@ $loader = require_once __DIR__.'/../app/bootstrap.php.cache';
 // Use APC for autoloading to improve performance.
 // Use APC for autoloading to improve performance.
 // Change 'sf2' to a unique prefix in order to prevent cache key conflicts
 // Change 'sf2' to a unique prefix in order to prevent cache key conflicts
 // with other applications also using APC.
 // with other applications also using APC.
-/*
-$loader = new ApcClassLoader('sf2', $loader);
+
+$loader = new ApcClassLoader('symfony2Benchmark', $loader);
 $loader->register(true);
 $loader->register(true);
-*/
+
 
 
 require_once __DIR__.'/../app/AppKernel.php';
 require_once __DIR__.'/../app/AppKernel.php';
 //require_once __DIR__.'/../app/AppCache.php';
 //require_once __DIR__.'/../app/AppCache.php';

+ 1 - 0
php/benchmark_config

@@ -13,6 +13,7 @@
       "setup_file": "setup",
       "setup_file": "setup",
       "db_url": "/dbraw.php",
       "db_url": "/dbraw.php",
       "query_url": "/dbraw.php?queries=",
       "query_url": "/dbraw.php?queries=",
+      "fortune_url": "/fortune.php"
       "port": 8080,
       "port": 8080,
       "sort": 12
       "sort": 12
     }
     }

+ 51 - 0
php/fortune.php

@@ -0,0 +1,51 @@
+<?php
+//
+// Database Test
+//
+
+// Database connection
+// http://www.php.net/manual/en/ref.pdo-mysql.php
+$pdo = new PDO('mysql:host=localhost;dbname=hello_world;charset=utf8', 'benchmarkdbuser', 'benchmarkdbpass', array(
+    PDO::ATTR_PERSISTENT => true
+));
+
+// Define query
+$statement = $pdo->prepare('SELECT * FROM Fortune');
+$statement->execute();
+  
+// Store result in array.
+$arr = $statement->fetchAll();
+$arr[] = array('id' => 0, 'message' => 'Additional fortune added at request time.');
+
+function cmp($a, $b) {
+  if ($a['message'] == $b['message']) {
+    return 0;
+  }
+  
+  return ($a['message'] < $b['message']) ? -1 : 1;
+}
+
+uasort($arr, 'cmp');
+?>
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+<?php
+foreach ($arr as &$value) {
+?>
+<tr>
+<td><?php echo htmlspecialchars($value['id'], ENT_QUOTES, 'UTF-8'); ?></td>  
+<td><?php echo htmlspecialchars($value['message'], ENT_QUOTES, 'UTF-8'); ?></td>
+</tr>
+<?php } ?>
+</table>
+</body>
+</html>

+ 1 - 0
php/setup.py

@@ -10,6 +10,7 @@ home = expanduser("~")
 def start(args):
 def start(args):
   setup_util.replace_text("php/dborm.php", "@.*\/hello_world", "@" + args.database_host + "/hello_world")
   setup_util.replace_text("php/dborm.php", "@.*\/hello_world", "@" + args.database_host + "/hello_world")
   setup_util.replace_text("php/dbraw.php", "host=.*;", "host=" + args.database_host + ";")
   setup_util.replace_text("php/dbraw.php", "host=.*;", "host=" + args.database_host + ";")
+  setup_util.replace_text("php/fortune.php", "host=.*;dbname", "host=" + args.database_host + ";dbname")
   setup_util.replace_text("php/deploy/php", "\".*\/FrameworkBenchmarks", "\"" + home + "/FrameworkBenchmarks")
   setup_util.replace_text("php/deploy/php", "\".*\/FrameworkBenchmarks", "\"" + home + "/FrameworkBenchmarks")
   setup_util.replace_text("php/deploy/php", "Directory .*\/FrameworkBenchmarks", "Directory " + home + "/FrameworkBenchmarks")
   setup_util.replace_text("php/deploy/php", "Directory .*\/FrameworkBenchmarks", "Directory " + home + "/FrameworkBenchmarks")
   setup_util.replace_text("php/deploy/nginx.conf", "root .*\/FrameworkBenchmarks", "root " + home + "/FrameworkBenchmarks")
   setup_util.replace_text("php/deploy/nginx.conf", "root .*\/FrameworkBenchmarks", "root " + home + "/FrameworkBenchmarks")

+ 3 - 3
phreeze/benchmark_config

@@ -3,9 +3,9 @@
   "tests": [{
   "tests": [{
     "default": {
     "default": {
       "setup_file": "setup",
       "setup_file": "setup",
-      "json_url": "/phreeze/json",
-      "db_url": "/phreeze/db",
-      "query_url": "/phreeze/db?queries=",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
       "port": 8080,
       "port": 8080,
       "sort": 49
       "sort": 49
     }
     }

+ 8 - 13
phreeze/deploy/nginx.conf

@@ -58,29 +58,24 @@ http {
         #location ~ \.php$ {
         #location ~ \.php$ {
         #    proxy_pass   http://127.0.0.1;
         #    proxy_pass   http://127.0.0.1;
         #}
         #}
+        
+        root /home/ubuntu/FrameworkBenchmarks/;
+        index  index.php;
+        
+        location /phreeze/ {
+            try_files $uri $uri/ /phreeze/index.php?_REWRITE_COMMAND=$uri&$args;
+        }
 
 
         # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
         # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
         #
         #
         location ~ \.php$ {
         location ~ \.php$ {
-            root /home/ubuntu/FrameworkBenchmarks;
+            try_files $uri =404;
             fastcgi_pass   127.0.0.1:9001;
             fastcgi_pass   127.0.0.1:9001;
             fastcgi_index  index.php;
             fastcgi_index  index.php;
 #            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
 #            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
             fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
             fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
             include        /usr/local/nginx/conf/fastcgi_params;
             include        /usr/local/nginx/conf/fastcgi_params;
         }
         }
-
-	    # url rewriting for a Phreeze application called "example" 
-	    #
-	    location ~ ^/phreeze/(.*) {
-	        try_files /phreeze/$1 /phreeze/$1/ /phreeze/index.php?_REWRITE_COMMAND=$1&args;
-	    }
-	    
-	    # url rewriting for phreeze app that is installed in the htdocs root
-	    #
-	    #location ~ ^/(.*) {
-	    #    try_files /$1 /$1/ /index.php?_REWRITE_COMMAND=$1&args;
-	    #}
     
     
         # deny access to .htaccess files, if Apache's document root
         # deny access to .htaccess files, if Apache's document root
         # concurs with nginx's one
         # concurs with nginx's one

+ 2 - 2
phreeze/index.php

@@ -10,7 +10,7 @@ require_once 'verysimple/Phreeze/GenericRouter.php';
 require_once 'verysimple/Phreeze/Phreezer.php';
 require_once 'verysimple/Phreeze/Phreezer.php';
 
 
 $cs = new ConnectionSetting();
 $cs = new ConnectionSetting();
-$cs->ConnectionString = "localhost:3306";
+$cs->ConnectionString = "172.16.98.98:3306";
 $cs->DBName = "hello_world";
 $cs->DBName = "hello_world";
 $cs->Username = "benchmarkdbuser";
 $cs->Username = "benchmarkdbuser";
 $cs->Password = "benchmarkdbpass";
 $cs->Password = "benchmarkdbpass";
@@ -24,7 +24,7 @@ $route_map = array(
 		'GET:db' => array('route' => 'Test.DB')
 		'GET:db' => array('route' => 'Test.DB')
 );
 );
 
 
-$router = new GenericRouter('./','Test.JSON',$route_map);
+$router = new GenericRouter('/','Test.JSON',$route_map);
 
 
 Dispatcher::Dispatch(
 Dispatcher::Dispatch(
 	$phreezer,
 	$phreezer,

+ 5 - 2
phreeze/libs/verysimple/HTTP/RequestUtil.php

@@ -2,8 +2,6 @@
 /** @package	verysimple::HTTP */
 /** @package	verysimple::HTTP */
 
 
 /** import supporting libraries */
 /** import supporting libraries */
-require_once("FileUpload.php");
-require_once("verysimple/String/VerySimpleStringUtil.php");
 
 
 /**
 /**
  * Static utility class for processing form post/request data
  * Static utility class for processing form post/request data
@@ -366,6 +364,7 @@ class RequestUtil
 		$tmp_path = $upload['tmp_name'];
 		$tmp_path = $upload['tmp_name'];
 		$info = pathinfo($upload['name']);
 		$info = pathinfo($upload['name']);
 
 
+		require_once("FileUpload.php");
 		$fupload = new FileUpload();
 		$fupload = new FileUpload();
 		$fupload->Name = $info['basename'];
 		$fupload->Name = $info['basename'];
 		$fupload->Size = $upload['size'];
 		$fupload->Size = $upload['size'];
@@ -455,6 +454,8 @@ class RequestUtil
 
 
 		if (self::$ENCODE_NON_ASCII)
 		if (self::$ENCODE_NON_ASCII)
 		{
 		{
+			require_once("verysimple/String/VerySimpleStringUtil.php");
+			
 			if (is_array($val))
 			if (is_array($val))
 			{
 			{
 				foreach ($val as $k=>$v)
 				foreach ($val as $k=>$v)
@@ -478,6 +479,8 @@ class RequestUtil
 	 */
 	 */
 	public static function HasNonAsciiChars($fieldname)
 	public static function HasNonAsciiChars($fieldname)
 	{
 	{
+		require_once("verysimple/String/VerySimpleStringUtil.php");
+		
 		$val = isset($_REQUEST[$fieldname]) ? $_REQUEST[$fieldname] : '';
 		$val = isset($_REQUEST[$fieldname]) ? $_REQUEST[$fieldname] : '';
 		return VerySimpleStringUtil::EncodeToHTML($val) != $val;
 		return VerySimpleStringUtil::EncodeToHTML($val) != $val;
 	}
 	}

+ 11 - 7
phreeze/libs/verysimple/Phreeze/Controller.php

@@ -4,16 +4,11 @@
 /** import supporting libraries */
 /** import supporting libraries */
 require_once("verysimple/HTTP/RequestUtil.php");
 require_once("verysimple/HTTP/RequestUtil.php");
 require_once("verysimple/HTTP/Context.php");
 require_once("verysimple/HTTP/Context.php");
-require_once("verysimple/HTTP/BrowserDevice.php");
-require_once("verysimple/Authentication/Authenticator.php");
-require_once("verysimple/Authentication/Auth401.php");
-require_once("verysimple/Authentication/IAuthenticatable.php");
-require_once("verysimple/String/VerySimpleStringUtil.php");
-require_once("DataPage.php");
 require_once("Phreezer.php");
 require_once("Phreezer.php");
 require_once("Criteria.php");
 require_once("Criteria.php");
 require_once("IRouter.php");
 require_once("IRouter.php");
 require_once("GenericRouter.php");
 require_once("GenericRouter.php");
+require_once("verysimple/Authentication/IAuthenticatable.php");
 
 
 /**
 /**
  * Controller is a base controller object used for an MVC pattern
  * Controller is a base controller object used for an MVC pattern
@@ -151,6 +146,8 @@ abstract class Controller
 	 */
 	 */
 	protected function Require401Authentication(IAuthenticatable $authenticatable, $realm = "Login Required", $qs_username_field = "", $qs_password_field = "")
 	protected function Require401Authentication(IAuthenticatable $authenticatable, $realm = "Login Required", $qs_username_field = "", $qs_password_field = "")
 	{
 	{
+		require_once("verysimple/Authentication/Auth401.php");
+		
 		$user = $this->Get401Authentication($authenticatable,$qs_username_field, $qs_password_field);
 		$user = $this->Get401Authentication($authenticatable,$qs_username_field, $qs_password_field);
 
 
 		// we only want to output 401 headers if the user is not already authenticated
 		// we only want to output 401 headers if the user is not already authenticated
@@ -290,6 +287,7 @@ abstract class Controller
 	 */
 	 */
 	public function GetDevice()
 	public function GetDevice()
 	{
 	{
+		require_once("verysimple/HTTP/BrowserDevice.php");
 		return BrowserDevice::GetInstance();
 		return BrowserDevice::GetInstance();
 	}
 	}
 
 
@@ -345,8 +343,10 @@ abstract class Controller
 	 * @param Array $supressProps (In the format Array("PropName1","PropName2")
 	 * @param Array $supressProps (In the format Array("PropName1","PropName2")
 	 * @param bool noMap set to true to render this DataPage regardless of whether there is a FieldMap
 	 * @param bool noMap set to true to render this DataPage regardless of whether there is a FieldMap
 	 */
 	 */
-	protected function RenderXML(DataPage $page,$additionalProps = null, $supressProps = null, $noMap = false)
+	protected function RenderXML($page,$additionalProps = null, $supressProps = null, $noMap = false)
 	{
 	{
+		require_once("verysimple/String/VerySimpleStringUtil.php");
+		
 		if (!is_array($supressProps)) $supressProps = array();
 		if (!is_array($supressProps)) $supressProps = array();
 
 
 		// never include these props
 		// never include these props
@@ -620,6 +620,8 @@ abstract class Controller
 	 */
 	 */
 	public function ClearCurrentUser()
 	public function ClearCurrentUser()
 	{
 	{
+		require_once("verysimple/Authentication/Authenticator.php");
+		
 		$this->_cu = null;
 		$this->_cu = null;
 		Authenticator::ClearAuthentication($this->GUID);
 		Authenticator::ClearAuthentication($this->GUID);
 	}
 	}
@@ -647,6 +649,8 @@ abstract class Controller
 	{
 	{
 		if (!$this->_cu)
 		if (!$this->_cu)
 		{
 		{
+			require_once("verysimple/Authentication/Authenticator.php");
+			
 			$this->Phreezer->Observe("Loading CurrentUser from Session");
 			$this->Phreezer->Observe("Loading CurrentUser from Session");
 			$this->_cu = Authenticator::GetCurrentUser($this->GUID);
 			$this->_cu = Authenticator::GetCurrentUser($this->GUID);
 
 

+ 62 - 43
phreeze/libs/verysimple/Phreeze/DataAdapter.php

@@ -4,11 +4,7 @@
 /** import supporting libraries */
 /** import supporting libraries */
 require_once("IObservable.php");
 require_once("IObservable.php");
 require_once("ConnectionSetting.php");
 require_once("ConnectionSetting.php");
-require_once("DataPage.php");
-require_once("DataSet.php");
-require_once("QueryBuilder.php");
 require_once("verysimple/DB/DataDriver/IDataDriver.php");
 require_once("verysimple/DB/DataDriver/IDataDriver.php");
-require_once("verysimple/IO/Includer.php");
 
 
 /**
 /**
  * DataAdapter abstracts and provides access to the data store
  * DataAdapter abstracts and provides access to the data store
@@ -17,7 +13,7 @@ require_once("verysimple/IO/Includer.php");
  * @author     VerySimple Inc. <[email protected]>
  * @author     VerySimple Inc. <[email protected]>
  * @copyright  1997-2005 VerySimple Inc.
  * @copyright  1997-2005 VerySimple Inc.
  * @license    http://www.gnu.org/licenses/lgpl.html  LGPL
  * @license    http://www.gnu.org/licenses/lgpl.html  LGPL
- * @version    2.0
+ * @version    2.1
  */
  */
 class DataAdapter implements IObservable
 class DataAdapter implements IObservable
 {
 {
@@ -35,6 +31,9 @@ class DataAdapter implements IObservable
 	/** @var used internally to keep track of communication error re-tries */
 	/** @var used internally to keep track of communication error re-tries */
 	private $_num_retries = 0;
 	private $_num_retries = 0;
 	
 	
+	/** @var static singleton instance of the data adapter */
+	static $ADAPTER_INSTANCE = null;
+	
 	/** @var instance of the driver class, used for escaping */
 	/** @var instance of the driver class, used for escaping */
 	static $DRIVER_INSTANCE = null;
 	static $DRIVER_INSTANCE = null;
 	
 	
@@ -52,47 +51,15 @@ class DataAdapter implements IObservable
     function __construct($csetting, $listener = null, IDataDriver $driver = null)
     function __construct($csetting, $listener = null, IDataDriver $driver = null)
     {
     {
     	$this->_driver = $driver;
     	$this->_driver = $driver;
-    	
-    	
-    	if ($this->_driver == null) 
-    	{
-    		// the driver was not explicitly provided so we will try to create one from 
-    		// the connection setting based on the database types that we do know about
-    		switch($csetting->Type)
-    		{
-    			case "mysql":
-					include_once("verysimple/DB/DataDriver/MySQL.php");
-    				$this->_driver  = new DataDriverMySQL();
-    				break;
-    			case "mysqli":
-					include_once("verysimple/DB/DataDriver/MySQLi.php");
-    				$this->_driver  = new DataDriverMySQLi();
-    				break;
-    			case "sqlite":
-					include_once("verysimple/DB/DataDriver/SQLite.php");
-    				$this->_driver  = new DataDriverSQLite();
-    				break;
-    			default:
-    				try
-    				{
-    					Includer::IncludeFile("verysimple/DB/DataDriver/".$csetting->Type.".php");
-						$classname = "DataDriver" . $csetting->Type;
-    					$this->_driver  = new $classname();
-    				}
-    				catch (IncludeException $ex)
-		    		{
-		    			throw new Exception('Unknown DataDriver "' . $csetting->Type . '" specified in connection settings');
-		    		}
-    				break;
-    		}
+    	if ($this->_driver) DataAdapter::$DRIVER_INSTANCE = $this->_driver;
 
 
-    	}
-    	
-    	DataAdapter::$DRIVER_INSTANCE = $this->_driver;
-    	
-		$this->AttachObserver($listener);
 		$this->ConnectionSetting =& $csetting;
 		$this->ConnectionSetting =& $csetting;
+
+		if ($listener) $this->AttachObserver($listener);
 		$this->Observe("DataAdapter Instantiated", OBSERVE_DEBUG);
 		$this->Observe("DataAdapter Instantiated", OBSERVE_DEBUG);
+		
+		// set the singleton reference
+		DataAdapter::$ADAPTER_INSTANCE = $this;
 	}
 	}
 	
 	
 	
 	
@@ -107,6 +74,52 @@ class DataAdapter implements IObservable
 		$this->Close();
 		$this->Close();
 	}
 	}
 	
 	
+	/**
+	 * Load the data driver
+	 * @throws Exception
+	 */
+	public function LoadDriver()
+	{
+
+		if ($this->_driver == null)
+		{
+			require_once("verysimple/IO/Includer.php");
+			
+			// the driver was not explicitly provided so we will try to create one from
+			// the connection setting based on the database types that we do know about
+			switch($this->ConnectionSetting->Type)
+			{
+				case "mysql":
+					include_once("verysimple/DB/DataDriver/MySQL.php");
+					$this->_driver  = new DataDriverMySQL();
+					break;
+				case "mysqli":
+					include_once("verysimple/DB/DataDriver/MySQLi.php");
+					$this->_driver  = new DataDriverMySQLi();
+					break;
+				case "sqlite":
+					include_once("verysimple/DB/DataDriver/SQLite.php");
+					$this->_driver  = new DataDriverSQLite();
+					break;
+				default:
+					try
+					{
+						Includer::IncludeFile("verysimple/DB/DataDriver/".$this->ConnectionSetting->Type.".php");
+						$classname = "DataDriver" . $this->ConnectionSetting->Type;
+						$this->_driver  = new $classname();
+					}
+					catch (IncludeException $ex)
+					{
+						throw new Exception('Unknown DataDriver "' . $this->ConnectionSetting->Type . '" specified in connection settings');
+					}
+					break;
+			}
+		
+			DataAdapter::$DRIVER_INSTANCE = $this->_driver;
+		
+		}
+	}
+	
     /**
     /**
 	 * Returns name of the DB currently in use
 	 * Returns name of the DB currently in use
 	 *
 	 *
@@ -133,6 +146,8 @@ class DataAdapter implements IObservable
 		}
 		}
 		else
 		else
 		{
 		{
+			if (!$this->_driver) $this->LoadDriver();
+			
 			try
 			try
 			{
 			{
 				$this->_dbconn = $this->_driver->Open(
 				$this->_dbconn = $this->_driver->Open(
@@ -382,6 +397,8 @@ class DataAdapter implements IObservable
 	 */	
 	 */	
     public static function Escape($val)
     public static function Escape($val)
     {
     {
+    	if (DataAdapter::$ADAPTER_INSTANCE) DataAdapter::$ADAPTER_INSTANCE->LoadDriver();
+
 		// this is an unfortunate leftover from poor design of making this function static
 		// this is an unfortunate leftover from poor design of making this function static
 		// we cannon use the driver's escape method without a static reference
 		// we cannon use the driver's escape method without a static reference
 		if (!DataAdapter::$DRIVER_INSTANCE) throw new Exception("DataAdapter must be instantiated before Escape can be called");
 		if (!DataAdapter::$DRIVER_INSTANCE) throw new Exception("DataAdapter must be instantiated before Escape can be called");
@@ -402,6 +419,8 @@ class DataAdapter implements IObservable
 	 */
 	 */
 	public static function GetQuotedSql($val)
 	public static function GetQuotedSql($val)
 	{
 	{
+		if (DataAdapter::$ADAPTER_INSTANCE) DataAdapter::$ADAPTER_INSTANCE->LoadDriver();
+		
 		// this is an unfortunate leftover from poor design of making this function static
 		// this is an unfortunate leftover from poor design of making this function static
 		// we cannon use the driver's escape method without a static reference
 		// we cannon use the driver's escape method without a static reference
 		if (!DataAdapter::$DRIVER_INSTANCE) throw new Exception("DataAdapter must be instantiated before Escape can be called");
 		if (!DataAdapter::$DRIVER_INSTANCE) throw new Exception("DataAdapter must be instantiated before Escape can be called");

+ 14 - 11
phreeze/libs/verysimple/Phreeze/GenericRouter.php

@@ -3,16 +3,17 @@
 
 
 /** import supporting libraries */
 /** import supporting libraries */
 require_once('IRouter.php');
 require_once('IRouter.php');
+require_once('verysimple/HTTP/RequestUtil.php');
 
 
-/**
+/**
  * Generic Router is an implementation of IRouter that uses patterns to connect
  * Generic Router is an implementation of IRouter that uses patterns to connect
- * routes to a Controller/Method
- *
- * @package    verysimple::Phreeze
- * @author     VerySimple Inc.
- * @copyright  1997-2012 VerySimple, Inc.
- * @license    http://www.gnu.org/licenses/lgpl.html  LGPL
- * @version    1.0
+ * routes to a Controller/Method
+ *
+ * @package    verysimple::Phreeze
+ * @author     VerySimple Inc.
+ * @copyright  1997-2013 VerySimple, Inc.
+ * @license    http://www.gnu.org/licenses/lgpl.html  LGPL
+ * @version    1.1
  */
  */
 class GenericRouter implements IRouter
 class GenericRouter implements IRouter
 {
 {
@@ -24,6 +25,8 @@ class GenericRouter implements IRouter
 
 
 	// cached route from last run:
 	// cached route from last run:
 	private $cachedRoute;
 	private $cachedRoute;
+	
+	public static $ROUTE_NOT_FOUND = "Default.Error404";
 
 
 	/**
 	/**
 	 * Instantiate the GenericRouter
 	 * Instantiate the GenericRouter
@@ -117,7 +120,7 @@ class GenericRouter implements IRouter
 		}
 		}
 
 
 		// if we haven't returned by now, we've found no match:
 		// if we haven't returned by now, we've found no match:
-		return array("Default","Error404");
+		return explode('.', self::$ROUTE_NOT_FOUND,2);
 	}
 	}
 
 
 	/**
 	/**
@@ -132,8 +135,8 @@ class GenericRouter implements IRouter
 			// if a root folder was provided, then we need to strip that out as well
 			// if a root folder was provided, then we need to strip that out as well
 			if ($this->appRootUrl)
 			if ($this->appRootUrl)
 			{
 			{
-				$prefix = $this->appRootUrl.'/';
-				while (substr($this->uri,0,strlen($prefix)) == $prefix)
+				$prefix = str_replace(RequestUtil::GetServerRootUrl(),'/',$this->appRootUrl);
+				if (substr($this->uri,0,strlen($prefix)) == $prefix)
 				{
 				{
 					$this->uri = substr($this->uri,strlen($prefix));
 					$this->uri = substr($this->uri,strlen($prefix));
 				}
 				}

+ 27 - 26
phreeze/libs/verysimple/Phreeze/Phreezer.php

@@ -4,10 +4,7 @@
 /** import supporting libraries */
 /** import supporting libraries */
 require_once("Observable.php");
 require_once("Observable.php");
 require_once("Criteria.php");
 require_once("Criteria.php");
-require_once("KeyMap.php");
-require_once("FieldMap.php");
 require_once("DataAdapter.php");
 require_once("DataAdapter.php");
-require_once("NotFoundException.php");
 require_once("CacheRam.php");
 require_once("CacheRam.php");
 require_once("CacheNoCache.php");
 require_once("CacheNoCache.php");
 require_once("verysimple/IO/Includer.php");
 require_once("verysimple/IO/Includer.php");
@@ -21,7 +18,7 @@ require_once("verysimple/IO/Includer.php");
  * @author     VerySimple Inc.
  * @author     VerySimple Inc.
  * @copyright  1997-2008 VerySimple, Inc.
  * @copyright  1997-2008 VerySimple, Inc.
  * @license    http://www.gnu.org/licenses/lgpl.html  LGPL
  * @license    http://www.gnu.org/licenses/lgpl.html  LGPL
- * @version    3.3.3
+ * @version    3.3.4
  */
  */
 class Phreezer extends Observable
 class Phreezer extends Observable
 {
 {
@@ -33,7 +30,7 @@ class Phreezer extends Observable
 	 */
 	 */
 	public $RenderEngine;
 	public $RenderEngine;
 
 
-	public static $Version = '3.3.3 HEAD';
+	public static $Version = '3.3.4 HEAD';
 
 
 	/**
 	/**
 	 * @var int expiration time for query & value cache (in seconds) default = 5
 	 * @var int expiration time for query & value cache (in seconds) default = 5
@@ -103,7 +100,7 @@ class Phreezer extends Observable
 		$this->_level1Cache = new CacheRam();
 		$this->_level1Cache = new CacheRam();
 		$this->_level2Cache = new CacheNoCache();
 		$this->_level2Cache = new CacheNoCache();
 
 
-		parent::AttachObserver($observer);
+		if ($observer) parent::AttachObserver($observer);
 		$this->Observe("Phreeze Instantiated", OBSERVE_DEBUG);
 		$this->Observe("Phreeze Instantiated", OBSERVE_DEBUG);
 
 
 		$this->DataAdapter = new DataAdapter($csetting, $observer);
 		$this->DataAdapter = new DataAdapter($csetting, $observer);
@@ -316,6 +313,7 @@ class Phreezer extends Observable
 
 
 		if (!$obj = $ds->Next())
 		if (!$obj = $ds->Next())
 		{
 		{
+			require_once("NotFoundException.php");
 			throw new NotFoundException("$objectclass with specified criteria not found");
 			throw new NotFoundException("$objectclass with specified criteria not found");
 		}
 		}
 
 
@@ -371,6 +369,7 @@ class Phreezer extends Observable
 			$fms = $this->GetFieldMaps($objectclass);
 			$fms = $this->GetFieldMaps($objectclass);
 
 
 			// the query builder will handle creating the SQL for us
 			// the query builder will handle creating the SQL for us
+			require_once("QueryBuilder.php");
 			$builder = new QueryBuilder($this);
 			$builder = new QueryBuilder($this);
 			$builder->RecurseFieldMaps($objectclass, $fms);
 			$builder->RecurseFieldMaps($objectclass, $fms);
 
 
@@ -379,6 +378,7 @@ class Phreezer extends Observable
 			$count_sql = $builder->GetCountSQL($criteria);
 			$count_sql = $builder->GetCountSQL($criteria);
 		}
 		}
 
 
+		require_once("DataSet.php");
 		$ds = new DataSet($this, $objectclass, $sql, $cache_timeout);
 		$ds = new DataSet($this, $objectclass, $sql, $cache_timeout);
 		$ds->CountSQL = $count_sql;
 		$ds->CountSQL = $count_sql;
 
 
@@ -390,7 +390,7 @@ class Phreezer extends Observable
     * Get one instance of an object based on it's primary key value
     * Get one instance of an object based on it's primary key value
     *
     *
     * @access public
     * @access public
-    * @param string $objectclass the type of object that your DataSet will contain
+    * @param string $objectclass to query
     * @param variant $id the value of the primary key
     * @param variant $id the value of the primary key
     * @param int cache timeout (in seconds).  Default is Phreezer->ObjectCacheTimeout.  Set to 0 for no cache
     * @param int cache timeout (in seconds).  Default is Phreezer->ObjectCacheTimeout.  Set to 0 for no cache
     * @return Phreezable
     * @return Phreezable
@@ -422,11 +422,12 @@ class Phreezer extends Observable
 
 
 		$ds = $this->Query($objectclass, $criteria);
 		$ds = $this->Query($objectclass, $criteria);
 
 
-		// tell the dataset that we will be able to cache this query
+		// this is cacheable
 		$ds->UnableToCache = false;
 		$ds->UnableToCache = false;
 
 
 		if (!$obj = $ds->Next())
 		if (!$obj = $ds->Next())
 		{
 		{
+			require_once("NotFoundException.php");
 			throw new NotFoundException("$objectclass with primary key of $id not found");
 			throw new NotFoundException("$objectclass with primary key of $id not found");
 		}
 		}
 
 
@@ -488,15 +489,15 @@ class Phreezer extends Observable
 				{
 				{
 					$prop = $fm->PropertyName;
 					$prop = $fm->PropertyName;
 					$val = $obj->$prop;
 					$val = $obj->$prop;
-
-					try
-					{
-						$sql .= $delim . "`" . $fm->ColumnName . "` = " . $this->GetQuotedSql($val);
-					}
-					catch (Exception $ex)
-					{
-						throw new Exception("Error escaping property '$prop'. value could not be converted to string");
-					}
+
+					try
+					{
+						$sql .= $delim . "`" . $fm->ColumnName . "` = " . $this->GetQuotedSql($val);
+					}
+					catch (Exception $ex)
+					{
+						throw new Exception("Error escaping property '$prop'. value could not be converted to string");
+					}
 
 
 					$delim = ", ";
 					$delim = ", ";
 				}
 				}
@@ -539,15 +540,15 @@ class Phreezer extends Observable
 					if ($fm->FieldType != FM_CALCULATION)
 					if ($fm->FieldType != FM_CALCULATION)
 					{
 					{
 						$prop = $fm->PropertyName;
 						$prop = $fm->PropertyName;
-						$val = $obj->$prop;
-
-						try
-						{
-							$sql .= $delim . ' ' . $this->GetQuotedSql($val);
-						}
-						catch (Exception $ex)
-						{
-							throw new Exception("Error escaping property '$prop'. value could not be converted to string");
+						$val = $obj->$prop;
+
+						try
+						{
+							$sql .= $delim . ' ' . $this->GetQuotedSql($val);
+						}
+						catch (Exception $ex)
+						{
+							throw new Exception("Error escaping property '$prop'. value could not be converted to string");
 						}
 						}
 
 
 						$delim = ", ";
 						$delim = ", ";

+ 4 - 4
phreeze/libs/verysimple/String/VerySimpleStringUtil.php

@@ -59,10 +59,10 @@ class VerySimpleStringUtil
 
 
 		self::$SMART_QUOTE_CHARS =
 		self::$SMART_QUOTE_CHARS =
 			array(
 			array(
-				"Ô" => "'",
-				"Õ" => "'",
-				"Ò" => "\"",
-				"Ó" => "\"",
+				"�" => "'",
+				"�" => "'",
+				"�" => "\"",
+				"�" => "\"",
 				chr(145) => "'",
 				chr(145) => "'",
 				chr(146) => "'",
 				chr(146) => "'",
 				chr(147) => "\"",
 				chr(147) => "\"",

+ 23 - 0
plack/app.psgi

@@ -0,0 +1,23 @@
+# plackup -s Starman --workers N -E deployment app.psgi
+# -or-
+# plackup -s Twiggy::Prefork --max_workers N -E deployment app.psgi
+use v5.16;
+use Plack::Builder;
+use Plack::Request;
+use JSON::XS 'encode_json';
+use DBI;
+
+my $dbh = DBI->connect('dbi:mysql:dbname=test', 'root') || die $!;
+my $sth = $dbh->prepare('SELECT randomnumber FROM world WHERE id = ?');
+my $header = ['Content-Type' => 'application/json'];
+
+builder {
+    mount '/json' => sub { [ 200, $header, [ encode_json({ message => 'Hello, World!' })] ] },
+    mount '/dbi' => sub { [ 200, $header, [ encode_json([
+        map { id => $_->[0] + 0, randomnumber => $_->[1] },
+        grep exists $_->[1],
+        map [$_, $sth->execute($_) && $sth->fetchrow_array],
+        map int rand 10000 + 1,
+        1..Plack::Request->new(shift)->param('queries')//1
+    ]) ] ] }
+};

+ 11 - 1
play-scala/app/controllers/Application.scala

@@ -5,7 +5,7 @@ import play.api.mvc._
 import play.api.libs.json.Json
 import play.api.libs.json.Json
 import java.util.concurrent._
 import java.util.concurrent._
 import scala.concurrent._
 import scala.concurrent._
-import models._
+import models.{World, Fortune}
 import utils._
 import utils._
 import scala.concurrent.Future
 import scala.concurrent.Future
 
 
@@ -58,4 +58,14 @@ object Application extends Controller {
     }
     }
   }
   }
 
 
+  def fortunes() = PredicatedAction(isDbAvailable, ServiceUnavailable) {
+    Action {
+      Async {
+        Future(Fortune.getAll())(dbEc).map { fs =>
+          val fortunes =  fs :+ Fortune(anorm.NotAssigned, "Additional fortune added at request time.")
+          Ok(views.html.fortune(fortunes))
+        }
+      }
+    }
+  }
 }
 }

+ 24 - 0
play-scala/app/models/Fortune.scala

@@ -0,0 +1,24 @@
+package models
+
+import play.api.db._
+import play.api.Play.current
+import anorm._
+import anorm.SqlParser._
+
+case class Fortune(id: Pk[Long], message: String)
+
+object Fortune {
+
+  val simpleRowParser = {
+    get[Pk[Long]]("fortune.id") ~
+    get[String]("fortune.message") map {
+      case id~message => Fortune(id, message)
+    }
+  }
+
+  def getAll(): List[Fortune] = {
+    DB.withConnection { implicit connection =>
+      SQL("SELECT * FROM Fortune").as(Fortune.simpleRowParser *)
+    }
+  }
+}

+ 1 - 1
play-scala/app/models/World.scala

@@ -37,7 +37,7 @@ object World {
    */
    */
     def findById(id: Long): World = {
     def findById(id: Long): World = {
         DB.withConnection { implicit connection =>
         DB.withConnection { implicit connection =>
-            SQL("SELECT * FROM world WHERE id = {id}").on(
+            SQL("SELECT * FROM World WHERE id = {id}").on(
                 "id" -> id
                 "id" -> id
             ).as(World.simpleRowParser.single)
             ).as(World.simpleRowParser.single)
         }
         }

+ 18 - 0
play-scala/app/views/fortune.scala.html

@@ -0,0 +1,18 @@
+@(fortunes: List[Fortune])
+
+@main("Testcase 4 :: Fortune :: FrameworkBenchmark") {
+    <table>
+        <tr>
+            <th>id</th>
+            <th>message</th>
+        </tr>
+
+        @fortunes.sortBy(_.message).map { case Fortune(id, message) =>
+            <tr>
+                <td>@id</td>
+                <td>@message</td>
+            </tr>
+        }
+
+    </table>
+}

+ 13 - 0
play-scala/app/views/main.scala.html

@@ -0,0 +1,13 @@
+@(title: String)(content: Html)
+
+<!DOCTYPE html>
+
+<html>
+<head>
+    <title>@title</title>
+    <meta charset=utf-8>
+</head>
+<body>
+    @content
+</body>
+</html>

+ 1 - 0
play-scala/benchmark_config

@@ -6,6 +6,7 @@
       "json_url": "/json",
       "json_url": "/json",
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/db?queries=",
       "query_url": "/db?queries=",
+      "fortune_url": "/fortunes",
       "port": 9000,
       "port": 9000,
       "sort": 32
       "sort": 32
     }
     }

+ 1 - 0
play-scala/conf/routes

@@ -5,6 +5,7 @@
 # Home page
 # Home page
 GET     /json                           controllers.Application.json
 GET     /json                           controllers.Application.json
 GET     /db                             controllers.Application.db(queries: Int ?= 1)
 GET     /db                             controllers.Application.db(queries: Int ?= 1)
+GET     /fortunes                       controllers.Application.fortunes
 
 
 # Map static resources from the /public folder to the /assets URL path
 # Map static resources from the /public folder to the /assets URL path
 GET     /assets/*file                   controllers.Assets.at(path="/public", file)
 GET     /assets/*file                   controllers.Assets.at(path="/public", file)

+ 54 - 16
play1/app/controllers/Application.java

@@ -10,6 +10,7 @@ import java.util.concurrent.ExecutionException;
 import models.World;
 import models.World;
 import play.db.jpa.JPAPlugin;
 import play.db.jpa.JPAPlugin;
 import play.jobs.Job;
 import play.jobs.Job;
+import play.libs.F.Promise;
 import play.mvc.Controller;
 import play.mvc.Controller;
 
 
 public class Application extends Controller {
 public class Application extends Controller {
@@ -23,17 +24,38 @@ public class Application extends Controller {
 		render();
 		render();
 	}
 	}
 
 
+	public static void hello() {
+		renderText("hello world");
+	}
+
 	public static void json() {
 	public static void json() {
 		Map<String, String> result = new HashMap<String, String>();
 		Map<String, String> result = new HashMap<String, String>();
 		result.put("message", "Hello World!");
 		result.put("message", "Hello World!");
 		renderJSON(result);
 		renderJSON(result);
 	}
 	}
 
 
+	/**
+	 * this version is used in the tests. it is the simplest and fastest.
+	 * 
+	 * @param queries
+	 */
+	public static void dbSync(int queries) {
+		if (queries == 0)
+			queries = 1;
+		final List<World> worlds = new ArrayList<World>();
+		for (int i = 0; i < queries; ++i) {
+			Long id = Long.valueOf(random.nextInt(TEST_DATABASE_ROWS) + 1);
+			World result = World.findById(id);
+			worlds.add(result);
+		}
+		renderJSON(worlds);
+	}
+
 	@play.db.jpa.NoTransaction
 	@play.db.jpa.NoTransaction
 	public static void setup() {
 	public static void setup() {
 		JPAPlugin plugin = play.Play.plugin(JPAPlugin.class);
 		JPAPlugin plugin = play.Play.plugin(JPAPlugin.class);
 		plugin.startTx(true);
 		plugin.startTx(true);
-		
+
 		// clean out the old
 		// clean out the old
 		World.deleteAll();
 		World.deleteAll();
 		System.out.println("DELETED");
 		System.out.println("DELETED");
@@ -42,19 +64,46 @@ public class Application extends Controller {
 			int randomNumber = random.nextInt(TEST_DATABASE_ROWS) + 1;
 			int randomNumber = random.nextInt(TEST_DATABASE_ROWS) + 1;
 			new World(i, randomNumber).save();
 			new World(i, randomNumber).save();
 			if (i % 100 == 0) {
 			if (i % 100 == 0) {
-				
+
 				World.em().flush();
 				World.em().flush();
 				World.em().clear();
 				World.em().clear();
 				System.out.println("FLUSHED : " + i + "/" + TEST_DATABASE_ROWS);
 				System.out.println("FLUSHED : " + i + "/" + TEST_DATABASE_ROWS);
-				
+
 			}
 			}
 		}
 		}
 		System.out.println("ADDED");
 		System.out.println("ADDED");
 		plugin.closeTx(false);
 		plugin.closeTx(false);
 	}
 	}
 
 
-	public static void db(int queries) throws InterruptedException,
-			ExecutionException {
+	/**
+	 * note this is method is much slower than the synchronous version
+	 */
+	public static void dbAsyncEachQuery(int queries)
+			throws InterruptedException, ExecutionException {
+		if (queries == 0)
+			queries = 1;
+		final int queryCount = queries;
+		List<Promise<World>> promises = new ArrayList<Promise<World>>();
+		for (int i = 0; i < queryCount; ++i) {
+			final Long id = Long
+					.valueOf(random.nextInt(TEST_DATABASE_ROWS) + 1);
+			Job<World> job = new Job<World>() {
+				public World doJobWithResult() throws Exception {
+					World result = World.findById(id);
+					return result;
+				};
+			};
+			promises.add(job.now());
+		}
+		List<World> result = await(Promise.waitAll(promises));
+		renderJSON(result);
+	}
+
+	/**
+	 * note this is method is a bit slower than the synchronous version
+	 */
+	public static void dbAsyncAllQueries(int queries)
+			throws InterruptedException, ExecutionException {
 		if (queries == 0)
 		if (queries == 0)
 			queries = 1;
 			queries = 1;
 		final int queryCount = queries;
 		final int queryCount = queries;
@@ -74,15 +123,4 @@ public class Application extends Controller {
 		renderJSON(result);
 		renderJSON(result);
 	}
 	}
 
 
-	public static void dbSync(int queries) {
-		if (queries == 0)
-			queries = 1;
-		final List<World> worlds = new ArrayList<World>();
-		for (int i = 0; i < queries; ++i) {
-			Long id = Long.valueOf(random.nextInt(TEST_DATABASE_ROWS) + 1);
-			World result = World.findById(id);
-			worlds.add(result);
-		}
-		renderJSON(worlds);
-	}
 }
 }

+ 3 - 3
play1/benchmark_config

@@ -3,9 +3,9 @@
   "tests": [{
   "tests": [{
     "default": {
     "default": {
       "setup_file": "setup",
       "setup_file": "setup",
-      "json_url": "/play1/json",
-      "db_url": "/play1/db",
-      "query_url": "/play1/db?queries=",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
       "port": 8080,
       "port": 8080,
       "sort": 65
       "sort": 65
     }
     }

+ 14 - 6
play1/conf/application.conf

@@ -30,6 +30,10 @@ date.format=yyyy-MM-dd
 # ~~~~~
 # ~~~~~
 # If you need to change the HTTP port, uncomment this (default is set to 9000)
 # If you need to change the HTTP port, uncomment this (default is set to 9000)
 # http.port=9000
 # http.port=9000
+
+#modified to match previous port on test 
+http.port=8080
+
 #
 #
 # By default the server listen for HTTP on the wilcard address.
 # By default the server listen for HTTP on the wilcard address.
 # You can restrict this.
 # You can restrict this.
@@ -100,6 +104,8 @@ date.format=yyyy-MM-dd
 db.pool.timeout=1000
 db.pool.timeout=1000
 db.pool.maxSize=30
 db.pool.maxSize=30
 db.pool.minSize=10
 db.pool.minSize=10
+
+
 #
 #
 # If you want to reuse an existing Datasource from your application server, use:
 # If you want to reuse an existing Datasource from your application server, use:
 # db=java:/comp/env/jdbc/myDatasource
 # db=java:/comp/env/jdbc/myDatasource
@@ -110,15 +116,16 @@ db.pool.minSize=10
 # db.destroyMethod=close
 # db.destroyMethod=close
 db.driver= com.mysql.jdbc.Driver
 db.driver= com.mysql.jdbc.Driver
 db.url=jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true
 db.url=jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true
+#db.url=jdbc:mysql://localhost:3306/hello_world
 db.user=benchmarkdbuser
 db.user=benchmarkdbuser
 db.pass=benchmarkdbpass
 db.pass=benchmarkdbpass
-db.jndiName=DefaultDS
+#db.jndiName=DefaultDS
 
 
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url=jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true
-db.default.user=benchmarkdbuser
-db.default.pass=benchmarkdbpass
-db.default.jndiName=DefaultDS
+#db.default.driver= com.mysql.jdbc.Driver
+#db.default.url=jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true
+#db.default.user=benchmarkdbuser
+#db.default.pass=benchmarkdbpass
+#db.default.jndiName=DefaultDS
 
 
 
 
 # JPA Configuration (Hibernate)
 # JPA Configuration (Hibernate)
@@ -205,6 +212,7 @@ mail.smtp=mock
 # Size of the Jobs pool
 # Size of the Jobs pool
 # play.jobs.pool=10
 # play.jobs.pool=10
 
 
+
 # Execution pool
 # Execution pool
 # ~~~~~
 # ~~~~~
 # Default to 1 thread in DEV mode or (nb processors + 1) threads in PROD mode.
 # Default to 1 thread in DEV mode or (nb processors + 1) threads in PROD mode.

+ 4 - 2
play1/conf/routes

@@ -5,8 +5,10 @@
 
 
 # Home page
 # Home page
 GET     /json                           Application.json
 GET     /json                           Application.json
-GET     /db                             Application.db
-GET     /db_sync                        Application.dbSync
+GET     /db                             Application.dbSync
+GET     /db2                            Application.dbAsyncAllQueries
+GET     /db3                            Application.dbAsyncEachQuery
 GET     /setup                          Application.setup
 GET     /setup                          Application.setup
 GET     /                               Application.index
 GET     /                               Application.index
+GET     /hello                          Application.hello
 
 

+ 7 - 7
play1/setup.py

@@ -4,16 +4,16 @@ import setup_util
 
 
 def start(args):
 def start(args):
   setup_util.replace_text("play1/conf/application.conf", "jdbc:mysql:\/\/.*:3306", "jdbc:mysql://" + args.database_host + ":3306")
   setup_util.replace_text("play1/conf/application.conf", "jdbc:mysql:\/\/.*:3306", "jdbc:mysql://" + args.database_host + ":3306")
-  
-  subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
-  subprocess.check_call("play1 war -o $RESIN_HOME/webapps/play1 --exclude benchmark_config", shell=True, cwd="play1")
-  subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True)
-
+  subprocess.check_call("play1 start --%prod", shell=True, cwd="play1")
+#  subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
+#  subprocess.check_call("play1 war -o $RESIN_HOME/webapps/play1 --exclude benchmark_config", shell=True, cwd="play1")
+#  subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True)
   return 0
   return 0
 def stop():
 def stop():
   try:
   try:
-    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
-    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
+    subprocess.check_call("play1 stop", shell=True, cwd="play1")
+#    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
+#    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
     return 0
     return 0
   except subprocess.CalledProcessError:
   except subprocess.CalledProcessError:
     return 1 
     return 1 

+ 1 - 1
rack/README.md

@@ -12,7 +12,7 @@ The tests were run with:
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [JRuby 1.7.3](http://jruby.org/)
 * [JRuby 1.7.3](http://jruby.org/)
 * [Rack 1.5.1](http://rack.github.com/)
 * [Rack 1.5.1](http://rack.github.com/)
-* [Passenger 3.9.5-rc3](https://www.phusionpassenger.com/)
+* [Unicorn 4.6.2](http://unicorn.bogomips.org/)
 * [Resin 4.0.34](http://www.caucho.com/)
 * [Resin 4.0.34](http://www.caucho.com/)
 
 
 ## References
 ## References

+ 1 - 1
rails-stripped/README.md

@@ -15,7 +15,7 @@ The tests were run with:
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [JRuby 1.7.3](http://jruby.org/)
 * [JRuby 1.7.3](http://jruby.org/)
 * [Rails 3.2.11](http://rubyonrails.org/)
 * [Rails 3.2.11](http://rubyonrails.org/)
-* [Passenger 3.9.5-rc3](https://www.phusionpassenger.com/)
+* [Unicorn 4.6.2](http://unicorn.bogomips.org/)
 * [Resin 4.0.34](http://www.caucho.com/)
 * [Resin 4.0.34](http://www.caucho.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 

+ 1 - 1
rails/README.md

@@ -15,7 +15,7 @@ The tests were run with:
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [JRuby 1.7.3](http://jruby.org/)
 * [JRuby 1.7.3](http://jruby.org/)
 * [Rails 3.2.11](http://rubyonrails.org/)
 * [Rails 3.2.11](http://rubyonrails.org/)
-* [Passenger 3.9.5-rc3](https://www.phusionpassenger.com/)
+* [Unicorn 4.6.2](http://unicorn.bogomips.org/)
 * [Resin 4.0.34](http://www.caucho.com/)
 * [Resin 4.0.34](http://www.caucho.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 

+ 6 - 0
rails/app/controllers/hello_world_controller.rb

@@ -14,4 +14,10 @@ class HelloWorldController < ApplicationController
     end
     end
     render :json => results
     render :json => results
   end
   end
+  
+  def fortune
+    @fortunes = Fortune.all
+    @fortunes << Fortune.new(:message => "Additional fortune added at request time.")
+    @fortunes = @fortunes.sort { |x, y| x.message <=> y.message }
+  end
 end
 end

+ 4 - 0
rails/app/models/fortune.rb

@@ -0,0 +1,4 @@
+class Fortune < ActiveRecord::Base
+  self.table_name = "Fortune"
+  attr_accessible :message
+end

+ 12 - 0
rails/app/views/hello_world/fortune.html.erb

@@ -0,0 +1,12 @@
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+<% @fortunes.each do |fortune| %>
+<tr>
+<td><%= fortune.id %></td>
+<td><%= fortune.message %></td>
+</tr>
+<% end %>
+</table>

+ 1 - 3
rails/app/views/layouts/application.html.erb

@@ -1,11 +1,9 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html>
 <html>
 <head>
 <head>
-  <title>Hello World</title>
+<title>Fortunes</title>
 </head>
 </head>
 <body>
 <body>
-
 <%= yield %>
 <%= yield %>
-
 </body>
 </body>
 </html>
 </html>

+ 2 - 0
rails/benchmark_config

@@ -6,6 +6,7 @@
       "json_url": "/hello_world/json",
       "json_url": "/hello_world/json",
       "db_url": "/hello_world/db",
       "db_url": "/hello_world/db",
       "query_url": "/hello_world/db?queries=",
       "query_url": "/hello_world/db?queries=",
+      "fortune_url": "/fortune",
       "port": 8080,
       "port": 8080,
       "sort": 16
       "sort": 16
     },
     },
@@ -14,6 +15,7 @@
       "json_url": "/rails/hello_world/json",
       "json_url": "/rails/hello_world/json",
       "db_url": "/rails/hello_world/db",
       "db_url": "/rails/hello_world/db",
       "query_url": "/rails/hello_world/db?queries=",
       "query_url": "/rails/hello_world/db?queries=",
+      "fortune_url": "/fortune",
       "port": 8080,
       "port": 8080,
       "sort": 17
       "sort": 17
     }
     }

+ 1 - 0
rails/config/routes.rb

@@ -1,6 +1,7 @@
 Hello::Application.routes.draw do
 Hello::Application.routes.draw do
   get "hello_world/json"
   get "hello_world/json"
   get "hello_world/db"
   get "hello_world/db"
+  get "fortune" => "hello_world#fortune"
 
 
 
 
   # The priority is based upon order of creation:
   # The priority is based upon order of creation:

+ 4 - 4
results/i7/20130415095717/db.csv

@@ -1,5 +1,4 @@
 Framework,8,16,32,64,128,256
 Framework,8,16,32,64,128,256
-spring,14963,29144,35921,36269,36157,34814
 openresty,17115,42955,66599,87400,94888,96122
 openresty,17115,42955,66599,87400,94888,96122
 kohana-raw,1763,2076,2194,2198,2183,2187
 kohana-raw,1763,2076,2194,2198,2183,2187
 laravel-raw,1461,1653,1698,1685,1638,1576
 laravel-raw,1461,1653,1698,1685,1638,1576
@@ -9,12 +8,13 @@ play1,5523,6072,591,46,105,220
 play1siena,9832,9716,9056,9031,9073,9027
 play1siena,9832,9716,9056,9031,9073,9027
 fuel,1216,1394,1448,1453,1451,1438
 fuel,1216,1394,1448,1453,1451,1438
 slim,2741,3285,3501,3528,3518,3524
 slim,2741,3285,3501,3528,3518,3524
+play-scala,9453,15886,19469,21606,22590,22655
 vertx,12570,22012,22568,22965,23408,24015
 vertx,12570,22012,22568,22965,23408,24015
 wicket,15118,32929,41589,43369,42698,41321
 wicket,15118,32929,41589,43369,42698,41321
 go,3351,3267,3209,3095,2819,2652
 go,3351,3267,3209,3095,2819,2652
 sinatra-ruby,4162,4431,4418,4413,4406,4377
 sinatra-ruby,4162,4431,4418,4413,4406,4377
 sinatra-jruby,511,499,482,477,460,428
 sinatra-jruby,511,499,482,477,460,428
-unfiltered,10405,24366,30278,30260,30203,30208
+spring,14963,29144,35921,36269,36157,34814
 tapestry,8865,19104,28602,32149,32146,30793
 tapestry,8865,19104,28602,32149,32146,30793
 finagle-future-pool,7333,12179,12720,12947,13120,13098
 finagle-future-pool,7333,12179,12720,12947,13120,13098
 nodejs-mongodb-raw,12501,21658,25102,27613,28323,28924
 nodejs-mongodb-raw,12501,21658,25102,27613,28323,28924
@@ -44,11 +44,11 @@ rails-ruby,2782,2962,2924,2863,2807,2766
 servlet-raw,17629,42148,63857,76231,80733,79605
 servlet-raw,17629,42148,63857,76231,80733,79605
 symfony2,520,573,573,572,569,562
 symfony2,520,573,573,572,569,562
 flask,2885,3372,3387,3346,3327,3320
 flask,2885,3372,3387,3346,3327,3320
-phreeze,4,8,13,22,26,44
+phreeze,253,885,716,549,778,782
 yesod,10266,23221,31060,33099,33022,31921
 yesod,10266,23221,31060,33099,33022,31921
 http-kit,14985,39232,56631,56581,56499,56319
 http-kit,14985,39232,56631,56581,56499,56319
 rails-stripped-jruby,3444,3497,3372,3174,2826,2257
 rails-stripped-jruby,3444,3497,3372,3174,2826,2257
 rails-stripped-ruby,3120,3311,3306,3307,3300,3299
 rails-stripped-ruby,3120,3311,3306,3307,3300,3299
 django-stripped,2327,2839,2767,2970,2964,2959
 django-stripped,2327,2839,2767,2970,2964,2959
-play-scala,9453,15886,19469,21606,22590,22655
+unfiltered,10405,24366,30278,30260,30203,30208
 silex-raw,1490,1731,1752,1751,1748,1739
 silex-raw,1490,1731,1752,1751,1748,1739

+ 67 - 68
results/i7/20130415095717/db/phreeze/raw

@@ -2,141 +2,140 @@ Welcome to Ubuntu 12.04.1 LTS (GNU/Linux 3.2.0-23-generic x86_64)
 
 
  * Documentation:  https://help.ubuntu.com/
  * Documentation:  https://help.ubuntu.com/
 
 
-  System information as of Tue Apr 16 00:46:03 PDT 2013
+  System information as of Thu Apr 18 14:13:07 PDT 2013
 
 
-  System load:  0.13                Processes:           114
-  Usage of /:   10.0% of 131.63GB   Users logged in:     1
-  Memory usage: 13%                 IP address for eth1: 172.16.98.98
+  System load:  0.14                Processes:           114
+  Usage of /:   10.1% of 131.63GB   Users logged in:     1
+  Memory usage: 14%                 IP address for eth1: 172.16.98.98
   Swap usage:   0%
   Swap usage:   0%
 
 
   Graph this data and manage this system at https://landscape.canonical.com/
   Graph this data and manage this system at https://landscape.canonical.com/
 
 
-113 packages can be updated.
-51 updates are security updates.
+116 packages can be updated.
+58 updates are security updates.
 
 
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Running Primer phreeze
  Running Primer phreeze
- wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 5s test @ http://172.16.98.122:8080/phreeze/db
+Running 5s test @ http://172.16.98.122:8080/db
   8 threads and 8 connections
   8 threads and 8 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     0.00us    0.00us   0.00us  100.00%
+    Latency    91.65ms  183.15ms 554.30ms   81.50%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  0 requests in 6.00s, 0.00B read
-  Socket errors: connect 0, read 0, write 0, timeout 23
-Requests/sec:      0.00
-Transfer/sec:       0.00B
+  423 requests in 6.00s, 177.51KB read
+  Socket errors: connect 0, read 0, write 0, timeout 9
+Requests/sec:     70.49
+Transfer/sec:     29.58KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Running Warmup phreeze
  Running Warmup phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db
+Running 1m test @ http://172.16.98.122:8080/db
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   239.25ms    1.24s   17.52s    99.13%
+    Latency   213.97ms  649.28ms   7.69s    97.95%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  4296 requests in 1.00m, 1.76MB read
-  Socket errors: connect 0, read 0, write 0, timeout 6126
-  Non-2xx or 3xx responses: 2
-Requests/sec:     71.59
-Transfer/sec:     30.04KB
+  55564 requests in 1.00m, 22.77MB read
+  Socket errors: connect 0, read 0, write 0, timeout 2652
+  Non-2xx or 3xx responses: 8
+Requests/sec:    925.99
+Transfer/sec:    388.59KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 8 for phreeze
  Concurrency: 8 for phreeze
- wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db
+Running 1m test @ http://172.16.98.122:8080/db
   8 threads and 8 connections
   8 threads and 8 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency    38.30ms  524.33ms  16.56s    99.81%
+    Latency    66.64ms  228.27ms   3.16s    90.76%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  269 requests in 1.00m, 112.90KB read
-  Socket errors: connect 0, read 0, write 0, timeout 201
-Requests/sec:      4.48
-Transfer/sec:      1.88KB
+  15221 requests in 1.00m, 6.24MB read
+  Socket errors: connect 0, read 0, write 0, timeout 51
+Requests/sec:    253.67
+Transfer/sec:    106.46KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 16 for phreeze
  Concurrency: 16 for phreeze
- wrk -d 60 -c 16 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 16 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db
+Running 1m test @ http://172.16.98.122:8080/db
   8 threads and 16 connections
   8 threads and 16 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency    48.48ms  622.29ms  16.29s    99.78%
+    Latency    13.70ms  166.24ms   7.76s    99.75%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  494 requests in 1.00m, 207.23KB read
-  Socket errors: connect 0, read 0, write 0, timeout 416
-  Non-2xx or 3xx responses: 1
-Requests/sec:      8.23
-Transfer/sec:      3.45KB
+  53133 requests in 1.00m, 21.78MB read
+  Socket errors: connect 0, read 0, write 0, timeout 189
+Requests/sec:    885.48
+Transfer/sec:    371.60KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 32 for phreeze
  Concurrency: 32 for phreeze
- wrk -d 60 -c 32 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 32 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db
+Running 1m test @ http://172.16.98.122:8080/db
   8 threads and 32 connections
   8 threads and 32 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency    73.92ms  809.63ms  15.90s    99.72%
+    Latency    17.65ms  130.33ms   7.12s    99.44%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  826 requests in 1.00m, 346.48KB read
-  Socket errors: connect 0, read 0, write 0, timeout 779
-  Non-2xx or 3xx responses: 2
-Requests/sec:     13.77
-Transfer/sec:      5.77KB
+  43006 requests in 1.00m, 17.62MB read
+  Socket errors: connect 0, read 0, write 0, timeout 526
+  Non-2xx or 3xx responses: 1
+Requests/sec:    716.72
+Transfer/sec:    300.78KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 64 for phreeze
  Concurrency: 64 for phreeze
- wrk -d 60 -c 64 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 64 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db
+Running 1m test @ http://172.16.98.122:8080/db
   8 threads and 64 connections
   8 threads and 64 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   176.47ms    1.57s   19.55s    99.19%
+    Latency    33.99ms  260.28ms   8.01s    99.88%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  1345 requests in 1.00m, 564.31KB read
-  Socket errors: connect 0, read 0, write 0, timeout 1626
-  Non-2xx or 3xx responses: 2
-Requests/sec:     22.41
-Transfer/sec:      9.40KB
+  32952 requests in 1.00m, 13.50MB read
+  Socket errors: connect 0, read 0, write 0, timeout 1215
+  Non-2xx or 3xx responses: 6
+Requests/sec:    549.17
+Transfer/sec:    230.46KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 128 for phreeze
  Concurrency: 128 for phreeze
- wrk -d 60 -c 128 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 128 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db
+Running 1m test @ http://172.16.98.122:8080/db
   8 threads and 128 connections
   8 threads and 128 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   113.34ms    1.01s   16.43s    99.59%
+    Latency    79.38ms  442.03ms  10.06s    99.60%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  1604 requests in 1.00m, 673.00KB read
-  Socket errors: connect 0, read 0, write 0, timeout 3344
-  Non-2xx or 3xx responses: 2
-Requests/sec:     26.73
-Transfer/sec:     11.22KB
+  46704 requests in 1.00m, 19.14MB read
+  Socket errors: connect 0, read 0, write 0, timeout 2012
+  Non-2xx or 3xx responses: 3
+Requests/sec:    778.36
+Transfer/sec:    326.64KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 256 for phreeze
  Concurrency: 256 for phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db
+Running 1m test @ http://172.16.98.122:8080/db
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     3.01s     6.24s   17.14s    82.33%
+    Latency   251.65ms  727.23ms  12.25s    92.21%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2646 requests in 1.00m, 1.08MB read
-  Socket errors: connect 0, read 0, write 0, timeout 6658
-  Non-2xx or 3xx responses: 5
-Requests/sec:     44.10
-Transfer/sec:     18.50KB
+  46931 requests in 1.00m, 19.23MB read
+  Socket errors: connect 0, read 0, write 0, timeout 3426
+  Non-2xx or 3xx responses: 3
+Requests/sec:    782.09
+Transfer/sec:    328.21KB

+ 9 - 9
results/i7/20130415095717/json.csv

@@ -1,6 +1,6 @@
 Framework,8,16,32,64,128,256
 Framework,8,16,32,64,128,256
-netty,56687,109567,204456,215293,217780,219279
-openresty,57913,112535,188421,204562,203967,204314
+codeigniter,3479,4004,4220,4211,4179,4141
+lithium,2406,2578,2610,2598,2591,2574
 laravel,2110,2227,2209,2171,2113,2041
 laravel,2110,2227,2209,2171,2113,2041
 kohana,3399,3688,3762,3737,3744,3734
 kohana,3399,3688,3762,3737,3744,3734
 play1,12341,12117,11970,11044,10725,10021
 play1,12341,12117,11970,11044,10725,10021
@@ -14,8 +14,8 @@ wicket,52493,78227,78425,77455,77536,77415
 go,45441,95830,175456,192524,195422,200188
 go,45441,95830,175456,192524,195422,200188
 sinatra-ruby,1017,1224,1207,1188,1183,1183
 sinatra-ruby,1017,1224,1207,1188,1183,1183
 sinatra-jruby,3330,3142,3099,3043,2854,2710
 sinatra-jruby,3330,3142,3099,3043,2854,2710
-spring,47328,74165,88262,93550,91618,86437
-phreeze,13,17,44,31,48,77
+unfiltered,40077,74963,93852,118658,145211,169802
+phreeze,618,1279,1009,906,1315,1367
 tapestry,47660,80454,107905,110565,110350,102604
 tapestry,47660,80454,107905,110565,110350,102604
 finagle,52695,108815,188561,226801,231782,233415
 finagle,52695,108815,188561,226801,231782,233415
 lift-stateless,19142,27470,33251,35512,38006,39523
 lift-stateless,19142,27470,33251,35512,38006,39523
@@ -30,25 +30,25 @@ compojure,33242,64695,106710,113120,109387,100206
 express,32610,41852,43662,45435,45858,45416
 express,32610,41852,43662,45435,45858,45416
 grails,23918,31431,32522,32598,32389,32482
 grails,23918,31431,32522,32598,32389,32482
 nodejs,43912,57605,70232,70362,72077,72436
 nodejs,43912,57605,70232,70362,72077,72436
-servlet,66165,123830,204308,209285,218160,212575
 elli,33704,93617,145380,156459,155684,156080
 elli,33704,93617,145380,156459,155684,156080
 play-scala,21643,38539,43690,43355,43671,43361
 play-scala,21643,38539,43690,43355,43671,43361
-lithium,2406,2578,2610,2598,2591,2574
+rack-ruby,31658,44682,51018,54247,55920,56987
 php,26070,35128,38937,38557,38137,39006
 php,26070,35128,38937,38557,38137,39006
 play,18254,26140,26161,26396,25997,25631
 play,18254,26140,26161,26396,25997,25631
 grizzly-jersey,38394,92946,123041,135405,142143,148086
 grizzly-jersey,38394,92946,123041,135405,142143,148086
 rack-jruby,22964,28625,29853,29713,29593,27885
 rack-jruby,22964,28625,29853,29713,29593,27885
-rack-ruby,31658,44682,51018,54247,55920,56987
+spring,47328,74165,88262,93550,91618,86437
 rails-jruby,4183,3986,3879,3631,3172,2381
 rails-jruby,4183,3986,3879,3631,3172,2381
 rails-ruby,4206,4602,4596,4590,4590,4568
 rails-ruby,4206,4602,4596,4590,4590,4568
 django-stripped,13825,13851,13852,13617,13532,13476
 django-stripped,13825,13851,13852,13617,13532,13476
 symfony2,845,898,896,895,892,889
 symfony2,845,898,896,895,892,889
 flask,13000,12905,12822,12642,12494,12385
 flask,13000,12905,12822,12642,12494,12385
-codeigniter,3479,4004,4220,4211,4179,4141
+netty,56687,109567,204456,215293,217780,219279
 yesod,44411,89560,92003,98586,92182,98557
 yesod,44411,89560,92003,98586,92182,98557
 http-kit,36071,56354,83018,103193,122511,135394
 http-kit,36071,56354,83018,103193,122511,135394
 rails-stripped-jruby,5282,5116,4948,4606,3976,2854
 rails-stripped-jruby,5282,5116,4948,4606,3976,2854
 rails-stripped-ruby,5522,6093,6068,6073,6051,6026
 rails-stripped-ruby,5522,6093,6068,6073,6051,6026
 silex,2373,2562,2585,2573,2581,2562
 silex,2373,2562,2585,2573,2581,2562
-unfiltered,40077,74963,93852,118658,145211,169802
+servlet,66165,123830,204308,209285,218160,212575
 scalatra,47591,74552,89605,92407,93047,88730
 scalatra,47591,74552,89605,92407,93047,88730
+openresty,57913,112535,188421,204562,203967,204314

+ 62 - 64
results/i7/20130415095717/json/phreeze/raw

@@ -2,136 +2,134 @@ Welcome to Ubuntu 12.04.1 LTS (GNU/Linux 3.2.0-23-generic x86_64)
 
 
  * Documentation:  https://help.ubuntu.com/
  * Documentation:  https://help.ubuntu.com/
 
 
-  System information as of Tue Apr 16 00:38:36 PDT 2013
+  System information as of Thu Apr 18 14:05:37 PDT 2013
 
 
-  System load:  0.36                Processes:           114
-  Usage of /:   10.0% of 131.63GB   Users logged in:     1
-  Memory usage: 13%                 IP address for eth1: 172.16.98.98
+  System load:  0.23                Processes:           114
+  Usage of /:   10.1% of 131.63GB   Users logged in:     1
+  Memory usage: 14%                 IP address for eth1: 172.16.98.98
   Swap usage:   0%
   Swap usage:   0%
 
 
   Graph this data and manage this system at https://landscape.canonical.com/
   Graph this data and manage this system at https://landscape.canonical.com/
 
 
-113 packages can be updated.
-51 updates are security updates.
+116 packages can be updated.
+58 updates are security updates.
 
 
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Running Primer phreeze
  Running Primer phreeze
- wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 5s test @ http://172.16.98.122:8080/phreeze/json
+Running 5s test @ http://172.16.98.122:8080/json
   8 threads and 8 connections
   8 threads and 8 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency    28.65ms   14.13ms 155.53ms   92.54%
+    Latency     1.82ms    1.26ms  15.86ms   88.59%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  1441 requests in 5.03s, 591.00KB read
-Requests/sec:    286.67
-Transfer/sec:    117.57KB
+  11665 requests in 6.00s, 4.67MB read
+Requests/sec:   1944.17
+Transfer/sec:    797.32KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Running Warmup phreeze
  Running Warmup phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/json
+Running 1m test @ http://172.16.98.122:8080/json
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   926.12ms  565.30ms   3.35s    79.60%
+    Latency   180.10ms  600.29ms   4.86s    93.92%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  17684 requests in 1.00m, 7.08MB read
-  Socket errors: connect 0, read 0, write 0, timeout 456
-Requests/sec:    294.71
-Transfer/sec:    120.88KB
+  104674 requests in 1.00m, 41.92MB read
+  Socket errors: connect 0, read 0, write 0, timeout 2895
+Requests/sec:   1744.41
+Transfer/sec:    715.41KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 8 for phreeze
  Concurrency: 8 for phreeze
- wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 8 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/json
+Running 1m test @ http://172.16.98.122:8080/json
   8 threads and 8 connections
   8 threads and 8 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency    75.33ms  579.37ms  19.38s    99.60%
+    Latency    29.03ms  141.71ms   1.65s    95.67%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  833 requests in 1.00m, 341.63KB read
-  Socket errors: connect 0, read 0, write 0, timeout 196
-Requests/sec:     13.88
-Transfer/sec:      5.69KB
+  37119 requests in 1.00m, 14.87MB read
+  Socket errors: connect 0, read 0, write 0, timeout 68
+Requests/sec:    618.61
+Transfer/sec:    253.70KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 16 for phreeze
  Concurrency: 16 for phreeze
- wrk -d 60 -c 16 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 16 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/json
+Running 1m test @ http://172.16.98.122:8080/json
   8 threads and 16 connections
   8 threads and 16 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   141.54ms    1.20s   16.65s    99.47%
+    Latency    14.54ms  262.58ms   8.39s    99.81%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  1040 requests in 1.00m, 426.47KB read
-  Socket errors: connect 0, read 0, write 0, timeout 373
-  Non-2xx or 3xx responses: 1
-Requests/sec:     17.33
-Transfer/sec:      7.11KB
+  76792 requests in 1.00m, 30.75MB read
+  Socket errors: connect 0, read 0, write 0, timeout 197
+Requests/sec:   1279.75
+Transfer/sec:    524.84KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 32 for phreeze
  Concurrency: 32 for phreeze
- wrk -d 60 -c 32 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 32 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/json
+Running 1m test @ http://172.16.98.122:8080/json
   8 threads and 32 connections
   8 threads and 32 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   187.82ms  837.56ms  15.07s    99.19%
+    Latency    22.36ms  261.06ms  14.41s    99.06%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2655 requests in 1.00m, 1.06MB read
-  Socket errors: connect 0, read 0, write 0, timeout 571
-Requests/sec:     44.25
-Transfer/sec:     18.15KB
+  60600 requests in 1.00m, 24.27MB read
+  Socket errors: connect 0, read 0, write 0, timeout 458
+Requests/sec:   1009.94
+Transfer/sec:    414.19KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 64 for phreeze
  Concurrency: 64 for phreeze
- wrk -d 60 -c 64 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 64 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/json
+Running 1m test @ http://172.16.98.122:8080/json
   8 threads and 64 connections
   8 threads and 64 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   144.89ms    1.27s   25.92s    99.63%
-    Req/Sec     0.00      0.00     0.00    100.00%
-  1868 requests in 1.00m, 766.17KB read
-  Socket errors: connect 0, read 0, write 0, timeout 1665
-Requests/sec:     31.13
-Transfer/sec:     12.77KB
+    Latency    21.36ms  120.08ms   5.62s    98.08%
+    Req/Sec     0.31     17.62     1.00k    99.97%
+  54386 requests in 1.00m, 21.78MB read
+  Socket errors: connect 0, read 0, write 0, timeout 1209
+Requests/sec:    906.37
+Transfer/sec:    371.71KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 128 for phreeze
  Concurrency: 128 for phreeze
- wrk -d 60 -c 128 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 128 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/json
+Running 1m test @ http://172.16.98.122:8080/json
   8 threads and 128 connections
   8 threads and 128 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   355.24ms    1.78s   16.51s    98.63%
+    Latency    84.11ms  645.80ms   8.44s    98.60%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2904 requests in 1.00m, 1.16MB read
-  Socket errors: connect 0, read 0, write 0, timeout 3116
-Requests/sec:     48.39
-Transfer/sec:     19.85KB
+  78926 requests in 1.00m, 31.61MB read
+  Socket errors: connect 0, read 0, write 0, timeout 2195
+Requests/sec:   1315.33
+Transfer/sec:    539.43KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Concurrency: 256 for phreeze
  Concurrency: 256 for phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/json
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/json
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/json
+Running 1m test @ http://172.16.98.122:8080/json
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   568.21ms    1.95s   16.32s    98.25%
+    Latency   176.07ms  592.30ms   6.41s    94.81%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  4651 requests in 1.00m, 1.86MB read
-  Socket errors: connect 0, read 0, write 0, timeout 6155
-  Non-2xx or 3xx responses: 6
-Requests/sec:     77.51
-Transfer/sec:     31.78KB
+  82083 requests in 1.00m, 32.87MB read
+  Socket errors: connect 0, read 0, write 0, timeout 2569
+Requests/sec:   1367.92
+Transfer/sec:    561.00KB

+ 4 - 4
results/i7/20130415095717/query.csv

@@ -1,5 +1,4 @@
 Framework,1,5,10,15,20
 Framework,1,5,10,15,20
-spring,34315,13848,7919,5553,4283
 openresty,95922,22190,11791,8065,6116
 openresty,95922,22190,11791,8065,6116
 kohana-raw,2179,1903,1662,1479,1332
 kohana-raw,2179,1903,1662,1479,1332
 laravel-raw,1576,1318,1103,948,834
 laravel-raw,1576,1318,1103,948,834
@@ -9,12 +8,13 @@ play1,186,4,0,0,0
 play1siena,7908,5541,2769,1886,1438
 play1siena,7908,5541,2769,1886,1438
 fuel,1433,1118,881,727,623
 fuel,1433,1118,881,727,623
 slim,3486,2562,1951,1577,1331
 slim,3486,2562,1951,1577,1331
+play-scala,22611,6195,3337,2252,1690
 vertx,23997,3963,2014,1380,1052
 vertx,23997,3963,2014,1380,1052
 wicket,40931,15030,8398,5807,4442
 wicket,40931,15030,8398,5807,4442
 go,2606,517,247,163,123
 go,2606,517,247,163,123
 sinatra-ruby,3828,1644,958,675,523
 sinatra-ruby,3828,1644,958,675,523
 sinatra-jruby,426,330,318,341,320
 sinatra-jruby,426,330,318,341,320
-unfiltered,29474,6494,3283,2195,1652
+spring,34315,13848,7919,5553,4283
 tapestry,30540,14483,8652,6176,4828
 tapestry,30540,14483,8652,6176,4828
 finagle-future-pool,13012,2879,1473,988,743
 finagle-future-pool,13012,2879,1473,988,743
 nodejs-mongodb-raw,27426,11632,6860,4873,3774
 nodejs-mongodb-raw,27426,11632,6860,4873,3774
@@ -44,11 +44,11 @@ rails-ruby,2613,1323,831,607,480
 servlet-raw,82987,22506,11881,8093,6131
 servlet-raw,82987,22506,11881,8093,6131
 symfony2,560,524,486,455,426
 symfony2,560,524,486,455,426
 flask,3316,1365,792,563,434
 flask,3316,1365,792,563,434
-phreeze,43,34,33,33,37
+phreeze,344,249,267,193,207
 yesod,31053,10488,5635,3851,2913
 yesod,31053,10488,5635,3851,2913
 http-kit,56199,11598,5590,3739,2808
 http-kit,56199,11598,5590,3739,2808
 rails-stripped-jruby,2237,1265,837,625,496
 rails-stripped-jruby,2237,1265,837,625,496
 rails-stripped-ruby,3173,1463,890,641,502
 rails-stripped-ruby,3173,1463,890,641,502
 django-stripped,2928,1133,645,452,348
 django-stripped,2928,1133,645,452,348
-play-scala,22611,6195,3337,2252,1690
+unfiltered,29474,6494,3283,2195,1652
 silex-raw,1737,1623,1502,1405,1322
 silex-raw,1737,1623,1502,1405,1322

+ 57 - 58
results/i7/20130415095717/query/phreeze/raw

@@ -2,123 +2,122 @@ Welcome to Ubuntu 12.04.1 LTS (GNU/Linux 3.2.0-23-generic x86_64)
 
 
  * Documentation:  https://help.ubuntu.com/
  * Documentation:  https://help.ubuntu.com/
 
 
-  System information as of Tue Apr 16 00:53:36 PDT 2013
+  System information as of Thu Apr 18 14:20:35 PDT 2013
 
 
-  System load:  0.31                Processes:           114
-  Usage of /:   10.0% of 131.63GB   Users logged in:     1
-  Memory usage: 13%                 IP address for eth1: 172.16.98.98
+  System load:  0.25                Processes:           114
+  Usage of /:   10.1% of 131.63GB   Users logged in:     1
+  Memory usage: 14%                 IP address for eth1: 172.16.98.98
   Swap usage:   0%
   Swap usage:   0%
 
 
   Graph this data and manage this system at https://landscape.canonical.com/
   Graph this data and manage this system at https://landscape.canonical.com/
 
 
-113 packages can be updated.
-51 updates are security updates.
+116 packages can be updated.
+58 updates are security updates.
 
 
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Running Primer phreeze
  Running Primer phreeze
- wrk -d 5 -c 8 -t 8 http://172.16.98.122:8080/phreeze/db?queries=2
+ wrk -d 5 -c 8 -t 8 http://172.16.98.122:8080/db?queries=2
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 5s test @ http://172.16.98.122:8080/phreeze/db?queries=2
+Running 5s test @ http://172.16.98.122:8080/db?queries=2
   8 threads and 8 connections
   8 threads and 8 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     0.00us    0.00us   0.00us  100.00%
+    Latency    50.31ms  109.14ms 502.51ms   84.81%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  0 requests in 6.00s, 0.00B read
-  Socket errors: connect 0, read 0, write 0, timeout 17
-Requests/sec:      0.00
-Transfer/sec:       0.00B
+  868 requests in 5.25s, 394.62KB read
+Requests/sec:    165.24
+Transfer/sec:     75.12KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Running Warmup phreeze
  Running Warmup phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db?queries=2
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db?queries=2
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db?queries=2
+Running 1m test @ http://172.16.98.122:8080/db?queries=2
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency   661.32ms    2.17s   16.80s    97.42%
+    Latency   233.21ms  864.81ms  12.89s    97.68%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  4155 requests in 1.00m, 1.70MB read
-  Socket errors: connect 0, read 0, write 0, timeout 6012
-  Non-2xx or 3xx responses: 1
-Requests/sec:     69.24
-Transfer/sec:     29.06KB
+  37726 requests in 1.00m, 16.75MB read
+  Socket errors: connect 0, read 0, write 0, timeout 3693
+  Non-2xx or 3xx responses: 3
+Requests/sec:    628.74
+Transfer/sec:    285.83KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Queries: 1 for phreeze
  Queries: 1 for phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db?queries=1
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db?queries=1
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db?queries=1
+Running 1m test @ http://172.16.98.122:8080/db?queries=1
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     3.00s     5.04s   18.30s    81.91%
+    Latency   280.51ms    1.36s   15.17s    98.19%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2606 requests in 1.00m, 1.07MB read
-  Socket errors: connect 0, read 0, write 0, timeout 6354
-Requests/sec:     43.43
-Transfer/sec:     18.23KB
+  20673 requests in 1.00m, 8.47MB read
+  Socket errors: connect 0, read 0, write 0, timeout 5336
+  Non-2xx or 3xx responses: 8
+Requests/sec:    344.54
+Transfer/sec:    144.59KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Queries: 5 for phreeze
  Queries: 5 for phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db?queries=5
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db?queries=5
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db?queries=5
+Running 1m test @ http://172.16.98.122:8080/db?queries=5
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     3.76s     6.57s   16.20s    75.62%
+    Latency   634.96ms    1.78s   14.52s    96.26%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2040 requests in 1.00m, 856.12KB read
-  Socket errors: connect 0, read 0, write 0, timeout 6651
-  Non-2xx or 3xx responses: 1
-Requests/sec:     34.00
-Transfer/sec:     14.27KB
+  14943 requests in 1.00m, 8.16MB read
+  Socket errors: connect 0, read 0, write 0, timeout 3953
+  Non-2xx or 3xx responses: 3
+Requests/sec:    249.02
+Transfer/sec:    139.30KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Queries: 10 for phreeze
  Queries: 10 for phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db?queries=10
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db?queries=10
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db?queries=10
+Running 1m test @ http://172.16.98.122:8080/db?queries=10
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     2.68s     6.11s   32.46s    83.90%
+    Latency   805.09ms  952.09ms   4.40s    84.14%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2037 requests in 1.00m, 854.82KB read
-  Socket errors: connect 0, read 0, write 0, timeout 6667
-  Non-2xx or 3xx responses: 1
-Requests/sec:     33.95
-Transfer/sec:     14.25KB
+  16060 requests in 1.00m, 11.53MB read
+  Socket errors: connect 0, read 0, write 0, timeout 1442
+Requests/sec:    267.64
+Transfer/sec:    196.75KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Queries: 15 for phreeze
  Queries: 15 for phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db?queries=15
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db?queries=15
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db?queries=15
+Running 1m test @ http://172.16.98.122:8080/db?queries=15
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     5.19s     9.21s   32.62s    77.13%
+    Latency     1.08s     1.30s    5.74s    87.20%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2033 requests in 1.00m, 853.24KB read
-  Socket errors: connect 0, read 0, write 0, timeout 6700
-Requests/sec:     33.88
-Transfer/sec:     14.22KB
+  11589 requests in 1.00m, 10.30MB read
+  Socket errors: connect 0, read 0, write 0, timeout 2594
+Requests/sec:    193.13
+Transfer/sec:    175.72KB
 
 
 ---------------------------------------------------------
 ---------------------------------------------------------
  Queries: 20 for phreeze
  Queries: 20 for phreeze
- wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/phreeze/db?queries=20
+ wrk -d 60 -c 256 -t 8 http://172.16.98.122:8080/db?queries=20
 ---------------------------------------------------------
 ---------------------------------------------------------
 
 
-Running 1m test @ http://172.16.98.122:8080/phreeze/db?queries=20
+Running 1m test @ http://172.16.98.122:8080/db?queries=20
   8 threads and 256 connections
   8 threads and 256 connections
   Thread Stats   Avg      Stdev     Max   +/- Stdev
   Thread Stats   Avg      Stdev     Max   +/- Stdev
-    Latency     3.91s     7.27s   32.25s    80.70%
+    Latency   769.77ms    1.51s   12.31s    92.11%
     Req/Sec     0.00      0.00     0.00    100.00%
     Req/Sec     0.00      0.00     0.00    100.00%
-  2253 requests in 1.00m, 0.92MB read
-  Socket errors: connect 0, read 0, write 0, timeout 6659
-Requests/sec:     37.55
-Transfer/sec:     15.76KB
+  12426 requests in 1.00m, 13.16MB read
+  Socket errors: connect 0, read 0, write 0, timeout 3917
+Requests/sec:    207.08
+Transfer/sec:    224.58KB

Some files were not shown because too many files changed in this diff