Browse Source

Merge branch 'master' into ninja

Kpacha 11 years ago
parent
commit
d4dd10d606
100 changed files with 1371 additions and 441 deletions
  1. 39 17
      .gitignore
  2. 4 4
      HttpListener/setup.py
  3. 19 9
      README.md
  4. 4 4
      aspnet-stripped/setup_iis.py
  5. 4 4
      aspnet/setup_iis.py
  6. 10 10
      aspnet/setup_nginx.py
  7. 6 6
      aspnet/setup_xsp.py
  8. 8 8
      beego/setup.py
  9. 1 1
      beego/src/hello/hello.go
  10. 31 0
      benchmark.cfg.example
  11. 3 3
      bottle/setup.py
  12. 6 6
      bottle/setup_nginxuwsgi.py
  13. 3 3
      bottle/setup_py3.py
  14. 3 3
      bottle/setup_pypy.py
  15. 11 11
      cake/setup.py
  16. 7 7
      compojure/setup.py
  17. 1 1
      config/benchmark_profile
  18. 5 5
      cowboy/setup_erlang.py
  19. 4 4
      cpoll_cppsp/setup.py
  20. 4 4
      dancer/setup.py
  21. 6 6
      dart-start/setup.py
  22. 10 10
      dart-stream/server.dart
  23. 6 6
      dart-stream/setup.py
  24. 6 6
      dart/setup.py
  25. 3 3
      django/setup.py
  26. 3 3
      django/setup_pg.py
  27. 3 3
      django/setup_py3.py
  28. 4 4
      dropwizard/setup.py
  29. 6 6
      elli/setup_erlang.py
  30. 8 0
      evhttp-sharp/.gitignore
  31. 24 0
      evhttp-sharp/benchmark_config
  32. 28 0
      evhttp-sharp/setup.py
  33. 69 0
      evhttp-sharp/src/EvHttpSharpBenchmark.csproj
  34. 20 0
      evhttp-sharp/src/EvHttpSharpBenchmark.sln
  35. 37 0
      evhttp-sharp/src/Program.cs
  36. 36 0
      evhttp-sharp/src/Properties/AssemblyInfo.cs
  37. BIN
      evhttp-sharp/src/lib/EvHttpSharp.dll
  38. BIN
      evhttp-sharp/src/lib/Newtonsoft.Json.dll
  39. BIN
      evhttp-sharp/src/lib/libevent_core-2-0-5.dll
  40. BIN
      evhttp-sharp/src/lib/libevent_extra-2-0-5.dll
  41. BIN
      evhttp-sharp/src/libevent_core-2-0-5.dll
  42. BIN
      evhttp-sharp/src/libevent_extra-2-0-5.dll
  43. 12 12
      express/setup.py
  44. 3 3
      falcon/setup.py
  45. 3 3
      falcon/setup_py3.py
  46. 3 3
      falcon/setup_pypy.py
  47. 9 9
      falcore/setup.py
  48. 1 3
      falcore/src/framework_benchmarks/falcore.go
  49. 7 7
      finagle/setup.py
  50. 65 35
      finagle/src/main/scala/com/falmarri/finagle/Finagle.scala
  51. 3 3
      flask/setup.py
  52. 6 6
      flask/setup_nginxuwsgi.py
  53. 3 3
      flask/setup_py3.py
  54. 3 3
      flask/setup_pypy.py
  55. 7 6
      gemini/setup.py
  56. 8 8
      go/setup.py
  57. 1 3
      go/src/hello/hello.go
  58. 21 4
      grails/README.md
  59. 5 3
      grails/benchmark_config
  60. 15 13
      grails/hello/.classpath
  61. 17 0
      grails/hello/.gitignore
  62. 7 1
      grails/hello/.project
  63. 2 2
      grails/hello/application.properties
  64. 32 5
      grails/hello/grails-app/conf/BuildConfig.groovy
  65. 49 42
      grails/hello/grails-app/conf/Config.groovy
  66. 31 3
      grails/hello/grails-app/conf/DataSource.groovy
  67. 18 0
      grails/hello/grails-app/conf/JsonBootStrap.groovy
  68. 19 0
      grails/hello/grails-app/conf/JsonWorkaroundBootStrap.groovy
  69. 1 1
      grails/hello/grails-app/conf/UrlMappings.groovy
  70. 60 0
      grails/hello/grails-app/conf/mysql-connection.properties
  71. 85 16
      grails/hello/grails-app/controllers/hello/HelloController.groovy
  72. 14 0
      grails/hello/grails-app/domain/hello/Fortune.groovy
  73. 2 0
      grails/hello/grails-app/domain/hello/World.groovy
  74. 12 5
      grails/hello/grails-app/views/error.gsp
  75. 10 0
      grails/hello/grails-app/views/hello/fortunes.gsp
  76. 3 3
      grails/hello/grails-app/views/index.gsp
  77. 85 0
      grails/hello/src/groovy/org/codehaus/groovy/grails/plugins/codecs/JSONEncoder.java
  78. 8 0
      grails/hello/web-app/WEB-INF/sitemesh-excludes.xml
  79. 2 1
      grails/hello/web-app/WEB-INF/sitemesh.xml
  80. 10 10
      grails/setup.py
  81. 3 3
      grizzly-bm/benchmark_config
  82. 4 4
      grizzly-bm/setup.py
  83. 14 16
      grizzly-bm/src/main/java/org/glassfish/grizzly/bm/JsonHttpHandler.java
  84. 1 1
      grizzly-jersey/benchmark_config
  85. 4 4
      grizzly-jersey/setup.py
  86. 12 12
      hapi/setup.py
  87. 6 6
      http-kit/setup.py
  88. 6 6
      jester/setup.py
  89. 15 0
      jetty-servlet/README.md
  90. 0 0
      jetty-servlet/__init__.py
  91. 24 0
      jetty-servlet/benchmark_config
  92. 64 0
      jetty-servlet/pom.xml
  93. 19 0
      jetty-servlet/setup.py
  94. 4 0
      jetty-servlet/source_code
  95. 36 0
      jetty-servlet/src/main/java/hello/HelloWebServer.java
  96. 31 0
      jetty-servlet/src/main/java/hello/JsonServlet.java
  97. 28 0
      jetty-servlet/src/main/java/hello/PlaintextServlet.java
  98. 5 5
      kelp/setup.py
  99. 4 4
      lapis/setup.py
  100. 7 7
      lift-stateless/setup.py

+ 39 - 17
.gitignore

@@ -1,20 +1,42 @@
-.DS_Store
-*.pyc
-installs/
-*.log
-*.lock
-node_modules/
-*.war
+# eclipse
+.classpath
+.project
+.settings
+
+# maven
 target/
-*.out
-*.class
-mods/
-/.settings
-/.buildpath
-/.project
+*/src/main/java/META-INF/
+*.versionsBackup
+bin/
+
+# common junk
+*.log
+*.swp
+*.diff
+*.patch
+
+# intellij
 *.iml
+*.ipr
+*.iws
 .idea/
-.hsenv/
-azure.err
-php-kohana/application/logs/
-php-fuel/fuel/app/logs/
+
+# Mac filesystem dust
+.DS_Store
+
+# pmd
+.pmdruleset
+.pmd
+
+# netbeans
+/nbproject
+
+# vim
+.*.sw[a-p]
+
+# merge tooling
+*.orig
+
+#maven
+*.versionsBackup
+*.releaseBackup

+ 4 - 4
HttpListener/setup.py

@@ -3,20 +3,20 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name != 'nt':
     return 1
   
   try:
     setup_util.replace_text("HttpListener/HttpListener/App.config", "localhost", args.database_host)
-    subprocess.check_call("powershell -Command .\\setup.ps1 start", cwd="HttpListener")
+    subprocess.check_call("powershell -Command .\\setup.ps1 start", cwd="HttpListener", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name != 'nt':
     return 0
   
-  subprocess.check_call("powershell -Command .\\setup.ps1 stop", cwd="HttpListener")
+  subprocess.check_call("powershell -Command .\\setup.ps1 stop", cwd="HttpListener", stderr=errfile, stdout=logfile)
   return 0

+ 19 - 9
README.md

@@ -122,6 +122,16 @@ Here is the basic structure of benchmark_config, using the Compojure framework a
   * display_name (metadata): How to render this test permutation's name in the results web site.  Some permutation names can be really long, so the display_name is provided in order to provide something more succinct.
   * versus (optional): The name of another test (elsewhere in this project) that is a subset of this framework.  This allows for the generation of the framework efficiency chart in the results web site.  For example, Compojure is compared to "servlet" since Compojure is built on the Servlets platform.
 
+### Testing on both Windows and Linux
+
+If your framework and platform can execute on both Windows and Linux, we encourage you to specify tests for both operating systems.  This increases the amount of testing you should do before submitting your pull-request, however, so we understand if you start with just one of the two.
+
+The steps involved are:
+
+* Assuming you have implemeneted the Linux test already, add a new test permutation to your `benchmark_config` file for the Windows test (or vice-versa).  When the benchmark script runs on Linux, it skips tests where the Application Operating System (`os` in the file) is specified as Linux.  When running on Windows, it skips tests where the `os` field is Linux.
+* Add the necessary tweaks to your [setup file](#setup-files) to start and stop on the new operating system.  See, for example, [the script for Go](https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/go/setup.py).
+* Test on Windows and Linux to make sure everything works as expected.
+
 ## Setup Files
 
 The setup file is responsible for starting and stopping the test. This script is responsible for (among other things):
@@ -154,12 +164,12 @@ Here is an example of Wicket's setup file.
 	import setup_util
 
 	##################################################
-	# start(args)
+	# start(args, logfile, errfile)
 	#
 	# Starts the server for Wicket
 	# returns 0 if everything completes, 1 otherwise
 	##################################################
-	def start(args):
+	def start(args, logfile, errfile):
 
     # setting the database url
     setup_util.replace_text("wicket/src/main/webapp/WEB-INF/resin-web.xml", "mysql:\/\/.*:3306", "mysql://" + args.database_host + ":3306")
@@ -169,23 +179,23 @@ Here is an example of Wicket's setup file.
     # 3. Copy package to Resin's webapp directory
     # 4. Start resin
     try:
-      subprocess.check_call("mvn clean compile war:war", shell=True, cwd="wicket")
-      subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
-      subprocess.check_call("cp wicket/target/hellowicket-1.0-SNAPSHOT.war $RESIN_HOME/webapps/wicket.war", shell=True)
-      subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True)
+      subprocess.check_call("mvn clean compile war:war", shell=True, cwd="wicket", stderr=errfile, stdout=logfile)
+      subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call("cp wicket/target/hellowicket-1.0-SNAPSHOT.war $RESIN_HOME/webapps/wicket.war", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True, stderr=errfile, stdout=logfile)
       return 0
     except subprocess.CalledProcessError:
       return 1
 
 	##################################################
-	# stop()
+	# stop(logfile, errfile)
 	#
 	# Stops the server for Wicket
 	# returns 0 if everything completes, 1 otherwise
 	##################################################
-	def stop():
+	def stop(logfile):
     try:
-      subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
+      subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True, stderr=errfile, stdout=logfile)
       return 0
     except subprocess.CalledProcessError:
       return 1

+ 4 - 4
aspnet-stripped/setup_iis.py

@@ -3,20 +3,20 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name != 'nt':
     return 1
   
   try:
     setup_util.replace_text("aspnet-stripped/src/Web.config", "localhost", args.database_host)
-    subprocess.check_call("powershell -Command .\\setup_iis.ps1 start", cwd="aspnet-stripped")
+    subprocess.check_call("powershell -Command .\\setup_iis.ps1 start", cwd="aspnet-stripped", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name != 'nt':
     return 0
   
-  subprocess.check_call("powershell -Command .\\setup_iis.ps1 stop", cwd="aspnet-stripped")
+  subprocess.check_call("powershell -Command .\\setup_iis.ps1 stop", cwd="aspnet-stripped", stderr=errfile, stdout=logfile)
   return 0

+ 4 - 4
aspnet/setup_iis.py

@@ -3,20 +3,20 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name != 'nt':
     return 1
   
   try:
     setup_util.replace_text("aspnet/src/Web.config", "localhost", args.database_host)
-    subprocess.check_call("powershell -Command .\\setup_iis.ps1 start", cwd="aspnet")
+    subprocess.check_call("powershell -Command .\\setup_iis.ps1 start", cwd="aspnet", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name != 'nt':
     return 0
   
-  subprocess.check_call("powershell -Command .\\setup_iis.ps1 stop", cwd="aspnet")
+  subprocess.check_call("powershell -Command .\\setup_iis.ps1 stop", cwd="aspnet", stderr=errfile, stdout=logfile)
   return 0

+ 10 - 10
aspnet/setup_nginx.py

@@ -6,7 +6,7 @@ import os
 root = os.getcwd() + "/aspnet"
 app = root + "/src"
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name == 'nt':
     return 1
   
@@ -14,28 +14,28 @@ def start(args):
 
   try:
     # build
-    subprocess.check_call("rm -rf bin obj", shell=True, cwd=app)
-    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd=app)
-    subprocess.check_call("sudo chown -R $USER:$USER /usr/local/etc/mono", shell=True)
+    subprocess.check_call("rm -rf bin obj", shell=True, cwd=app, stderr=errfile, stdout=logfile)
+    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd=app, stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo chown -R $USER:$USER /usr/local/etc/mono", shell=True, stderr=errfile, stdout=logfile)
     
     # nginx
     workers = 'worker_processes ' + str(args.max_threads) + ';'
-    subprocess.check_call('echo "upstream mono {\n' + ';\n'.join('\tserver 127.0.0.1:' + str(port) for port in range(9001, 9001 + args.max_threads)) + ';\n}" > ' + root + '/nginx.upstream.conf', shell=True);
-    subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' + root + '/nginx.conf -g "' + workers + '"', shell=True)
+    subprocess.check_call('echo "upstream mono {\n' + ';\n'.join('\tserver 127.0.0.1:' + str(port) for port in range(9001, 9001 + args.max_threads)) + ';\n}" > ' + root + '/nginx.upstream.conf', shell=True, stderr=errfile, stdout=logfile);
+    subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' + root + '/nginx.conf -g "' + workers + '"', shell=True, stderr=errfile, stdout=logfile)
     
     # fastcgi
     for port in range(9001, 9001 + args.max_threads):
-      subprocess.Popen("MONO_OPTIONS=--gc=sgen fastcgi-mono-server4 /applications=/:. /socket=tcp:127.0.0.1:" + str(port) + " &", shell=True, cwd=app)
+      subprocess.Popen("MONO_OPTIONS=--gc=sgen fastcgi-mono-server4 /applications=/:. /socket=tcp:127.0.0.1:" + str(port) + " &", shell=True, cwd=app, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
     return 0
   
-  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + root + "/nginx.conf -s stop", shell=True)
-  subprocess.check_call("rm -f " + root + "/nginx.upstream.conf", shell=True)
+  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + root + "/nginx.conf -s stop", shell=True, stderr=errfile, stdout=logfile)
+  subprocess.check_call("rm -f " + root + "/nginx.upstream.conf", shell=True, stderr=errfile, stdout=logfile)
   #
   # stop mono
   #

+ 6 - 6
aspnet/setup_xsp.py

@@ -3,22 +3,22 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name == 'nt':
     return 1
   
   setup_util.replace_text("aspnet/src/Web.config", "localhost", args.database_host)
 
   try:
-    subprocess.check_call("rm -rf bin obj", shell=True, cwd="aspnet/src")
-    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd="aspnet/src")
-    subprocess.check_call("sudo chown -R ubuntu:ubuntu /usr/local/etc/mono", shell=True)
-    subprocess.Popen("MONO_OPTIONS=--gc=sgen xsp4 --nonstop", shell=True, cwd="aspnet/src")
+    subprocess.check_call("rm -rf bin obj", shell=True, cwd="aspnet/src", stderr=errfile, stdout=logfile)
+    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd="aspnet/src", stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo chown -R ubuntu:ubuntu /usr/local/etc/mono", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.Popen("MONO_OPTIONS=--gc=sgen xsp4 --nonstop", shell=True, cwd="aspnet/src", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
     return 0
   

+ 8 - 8
beego/setup.py

@@ -3,18 +3,18 @@ import subprocess
 import sys
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   if os.name == 'nt':
-    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\beego&&go get ./...", shell=True, cwd="beego")
-    subprocess.Popen("setup.bat", shell=True, cwd="beego")
+    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\beego&&go get ./...", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
+    subprocess.Popen("setup.bat", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
     return 0
-  subprocess.call("go get ./...", shell=True, cwd="beego")
-  subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="beego")
+  subprocess.call("go get ./...", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
+  subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="beego", stderr=errfile, stdout=logfile)
   return 0
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.call("taskkill /f /im go.exe > NUL", shell=True)
-    subprocess.call("taskkill /f /im hello.exe > NUL", shell=True)
+    subprocess.call("taskkill /f /im go.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("taskkill /f /im hello.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
     return 0
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()

+ 1 - 1
beego/src/hello/hello.go

@@ -2,7 +2,7 @@ package main
 
 import (
 	"github.com/astaxie/beego"
-	"runtime"
+	//"runtime"
 )
 
 type MessageStruct struct {

+ 31 - 0
benchmark.cfg.example

@@ -0,0 +1,31 @@
+[Defaults]
+# Available Keys: 
+# client_host='localhost'
+# client_identity_file=None
+# client_user=None
+# database_host=None
+# database_identity_file=None
+# database_os='linux'
+# database_user=None
+# duration=60
+# exclude=None
+# install='all'
+# install_error_action='continue'
+# install_software=False
+# list_test_metadata=False
+# list_tests=False
+# max_concurrency=256
+# max_queries=20
+# max_threads=8
+# mode='benchmark'
+# name='ec2'
+# os='linux'
+# parse=None
+# password_prompt=False
+# query_interval=5
+# server_host='localhost'
+# sleep=60
+# starting_concurrency=8
+# test=None
+# type='all'
+# verbose=True

+ 3 - 3
bottle/setup.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("bottle/app.py", "DBHOSTNAME", args.database_host)
     proc = subprocess.Popen([
@@ -19,10 +19,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="bottle")
+        cwd="bottle", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 6 - 6
bottle/setup_nginxuwsgi.py

@@ -7,21 +7,21 @@ bin_dir = os.path.expanduser('~/FrameworkBenchmarks/installs/py2/bin')
 config_dir = os.path.expanduser('~/FrameworkBenchmarks/config')
 NCPU = multiprocessing.cpu_count()
 
-def start(args):
+def start(args, logfile, errfile):
     setup_util.replace_text("bottle/app.py", "DBHOSTNAME", args.database_host)
     try:
         subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' +
-            config_dir + '/nginx_uwsgi.conf', shell=True)
+            config_dir + '/nginx_uwsgi.conf', shell=True, stderr=errfile, stdout=logfile)
         # Run in the background, but keep stdout/stderr for easy debugging
         subprocess.Popen(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi.ini' +
             ' --processes ' + str(NCPU * 3) +
             ' --wsgi app:app',
-            shell=True, cwd='bottle')
+            shell=True, cwd='bottle', stderr=errfile, stdout=logfile)
         return 0
     except subprocess.CalledProcessError:
         return 1
 
-def stop():
-    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True)
-    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True)
+def stop(logfile, errfile):
+    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True, stderr=errfile, stdout=logfile)
     return 0

+ 3 - 3
bottle/setup_py3.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("bottle/app.py", "DBHOSTNAME", args.database_host)
     proc = subprocess.Popen([
@@ -19,10 +19,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="bottle")
+        cwd="bottle", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 3 - 3
bottle/setup_pypy.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("bottle/app.py", "DBHOSTNAME", args.database_host)
     proc = subprocess.Popen([
@@ -19,10 +19,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="bottle")
+        cwd="bottle", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 11 - 11
cake/setup.py

@@ -7,7 +7,7 @@ from os.path import expanduser
 
 home = expanduser("~")
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("cake/app/Config/database.php", "'host' => '.*',", "'host' => '" + args.database_host + "',")
   setup_util.replace_text("cake/deploy/cake", "\".*\/FrameworkBenchmarks", "\"" + home + "/FrameworkBenchmarks")
   setup_util.replace_text("cake/deploy/cake", "Directory .*\/FrameworkBenchmarks", "Directory " + home + "/FrameworkBenchmarks")
@@ -16,28 +16,28 @@ def start(args):
   try:
     if os.name == 'nt':
       setup_util.replace_text("cake/app/Config/core.php", "'Apc'", "'Wincache'")
-      subprocess.check_call('icacls "C:\\FrameworkBenchmarks\\cake" /grant "IIS_IUSRS:(OI)(CI)F"', shell=True)
-      subprocess.check_call('appcmd add site /name:PHP /bindings:http/*:8080: /physicalPath:"C:\\FrameworkBenchmarks\\cake\\app\\webroot"', shell=True)
+      subprocess.check_call('icacls "C:\\FrameworkBenchmarks\\cake" /grant "IIS_IUSRS:(OI)(CI)F"', shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call('appcmd add site /name:PHP /bindings:http/*:8080: /physicalPath:"C:\\FrameworkBenchmarks\\cake\\app\\webroot"', shell=True, stderr=errfile, stdout=logfile)
       return 0
     #subprocess.check_call("sudo cp cake/deploy/cake /etc/apache2/sites-available/", shell=True)
     #subprocess.check_call("sudo a2ensite cake", shell=True)
-    subprocess.check_call("sudo chown -R www-data:www-data cake", shell=True)
+    subprocess.check_call("sudo chown -R www-data:www-data cake", shell=True, stderr=errfile, stdout=logfile)
     #subprocess.check_call("sudo /etc/init.d/apache2 start", shell=True)
-    subprocess.check_call("sudo php-fpm --fpm-config config/php-fpm.conf -g " + home + "/FrameworkBenchmarks/cake/deploy/php-fpm.pid", shell=True)
-    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/cake/deploy/nginx.conf", shell=True)
+    subprocess.check_call("sudo php-fpm --fpm-config config/php-fpm.conf -g " + home + "/FrameworkBenchmarks/cake/deploy/php-fpm.pid", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/cake/deploy/nginx.conf", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
     if os.name == 'nt':
-      subprocess.call('appcmd delete site PHP', shell=True)
+      subprocess.call('appcmd delete site PHP', shell=True, stderr=errfile, stdout=logfile)
       return 0
-    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
-    subprocess.call("sudo kill -QUIT $( cat cake/deploy/php-fpm.pid )", shell=True)
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("sudo kill -QUIT $( cat cake/deploy/php-fpm.pid )", shell=True, stderr=errfile, stdout=logfile)
     #subprocess.check_call("sudo a2dissite cake", shell=True)
     #subprocess.check_call("sudo /etc/init.d/apache2 stop", shell=True)
-    subprocess.check_call("sudo chown -R $USER:$USER cake", shell=True)
+    subprocess.check_call("sudo chown -R $USER:$USER cake", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 7 - 7
compojure/setup.py

@@ -3,20 +3,20 @@ import subprocess
 import sys
 import setup_util
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("compojure/hello/src/hello/handler.clj", ":subname \"//.*:3306", ":subname \"//" + args.database_host + ":3306")
 
   try:
-    subprocess.check_call("lein ring uberwar", shell=True, cwd="compojure/hello")
-    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
-    subprocess.check_call("cp compojure/hello/target/hello-compojure-standalone.war $RESIN_HOME/webapps/compojure.war", shell=True)
-    subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True)
+    subprocess.check_call("lein ring uberwar", shell=True, cwd="compojure/hello", stderr=errfile, stdout=logfile)
+    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("cp compojure/hello/target/hello-compojure-standalone.war $RESIN_HOME/webapps/compojure.war", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
-    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
+    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 1 - 1
config/benchmark_profile

@@ -1,6 +1,6 @@
 export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
 export RESIN_HOME=~/FrameworkBenchmarks/installs/resin-4.0.36
-export GRAILS_HOME=~/FrameworkBenchmarks/installs/grails-2.3.1
+export GRAILS_HOME=~/FrameworkBenchmarks/installs/grails-2.3.3
 export VERTX_HOME=~/FrameworkBenchmarks/installs/vert.x-2.0.2-final
 export GOROOT=~/FrameworkBenchmarks/installs/go
 export GOPATH=~/FrameworkBenchmarks/go:~/FrameworkBenchmarks/webgo:~/FrameworkBenchmarks/revel

+ 5 - 5
cowboy/setup_erlang.py

@@ -2,17 +2,17 @@ import subprocess
 import sys
 import setup_util
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("cowboy/src/hello_world_app.erl", "\"benchmarkdbpass\", \".*\", 3306", "\"benchmarkdbpass\", \"" + args.database_host + "\", 3306")
 
   try:
-    subprocess.check_call("./rebar get-deps", shell=True, cwd="cowboy")
-    subprocess.check_call("./rebar compile", shell=True, cwd="cowboy")
-    subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached", shell=True, cwd="cowboy")
+    subprocess.check_call("./rebar get-deps", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
+    subprocess.check_call("./rebar compile", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
+    subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached", shell=True, cwd="cowboy", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
     subprocess.check_call("killall beam.smp", shell=True, cwd="/usr/bin")
     return 0

+ 4 - 4
cpoll_cppsp/setup.py

@@ -3,13 +3,13 @@ import sys
 import os
 import setup_util 
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("cpoll_cppsp/www/connectioninfo.H", "\\#define BENCHMARK_DB_HOST \".*\"", "#define BENCHMARK_DB_HOST \"" + args.database_host + "\"")
-  subprocess.check_call("make", shell=True, cwd="cpoll_cppsp")
-  subprocess.Popen("./run_application \"$(pwd)\"/www -g g++-4.8 -m /forcedynamic.cppsm", shell=True, cwd="cpoll_cppsp");
+  subprocess.check_call("make", shell=True, cwd="cpoll_cppsp", stderr=errfile, stdout=logfile)
+  subprocess.Popen("./run_application \"$(pwd)\"/www -g g++-4.8 -m /forcedynamic.cppsm", shell=True, cwd="cpoll_cppsp", stderr=errfile, stdout=logfile);
   return 0
 
-def stop():
+def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():

+ 4 - 4
dancer/setup.py

@@ -7,18 +7,18 @@ import getpass
 
 home = expanduser("~")
 
-def start(args):
+def start(args, logfile, errfile):
   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)
+    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", stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/dancer/nginx.conf", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
     subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
     p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)

+ 6 - 6
dart-start/setup.py

@@ -3,19 +3,19 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text('dart-start/postgresql.yaml', 'host: .*', 'host: ' + args.database_host)
   setup_util.replace_text('dart-start/mongodb.yaml', 'host: .*', 'host: ' + args.database_host)
   try:
     #
     # install dart dependencies
     #
-    subprocess.check_call('pub install', shell=True, cwd='dart-start')
+    subprocess.check_call('pub install', shell=True, cwd='dart-start', stderr=errfile, stdout=logfile)
     #
     # start dart servers
     #
     for port in range(9001, 9001 + args.max_threads):
-      subprocess.Popen('dart server.dart -a 127.0.0.1 -p ' + str(port) + ' -d ' + str(args.max_concurrency / args.max_threads), shell=True, cwd='dart-start')
+      subprocess.Popen('dart server.dart -a 127.0.0.1 -p ' + str(port) + ' -d ' + str(args.max_concurrency / args.max_threads), shell=True, cwd='dart-start', stderr=errfile, stdout=logfile)
     #
     # create nginx configuration
     #
@@ -52,16 +52,16 @@ def start(args):
     #
     # start nginx
     #
-    subprocess.Popen('sudo /usr/sbin/nginx -c `pwd`/nginx.conf', shell=True, cwd='dart-start');
+    subprocess.Popen('sudo /usr/sbin/nginx -c `pwd`/nginx.conf', shell=True, cwd='dart-start', stderr=errfile, stdout=logfile);
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   #
   # stop nginx
   #
-  subprocess.check_call('sudo /usr/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd='dart-start')
+  subprocess.check_call('sudo /usr/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd='dart-start', stderr=errfile, stdout=logfile)
   os.remove('dart-start/nginx.conf')
   #
   # stop dart servers

+ 10 - 10
dart-stream/server.dart

@@ -81,7 +81,7 @@ class World {
 
   World(this.id, this.randomnumber);
 
-  toJson() => { "id": id, "randomnumber": randomnumber };
+  toJson() => { "id": id, "randomNumber": randomnumber };
 }
 
 main() {
@@ -188,8 +188,8 @@ _dbMongoTest(HttpConnect connect) {
   
   return _mongoQuery().then((data) {
     connect.response.write(json.stringify({
-      "id": data["id"],
-      "randomnumber": data["randomnumber"]
+      "id": data["_id"],
+      "randomNumber": data["randomNumber"]
     }));
   });
 }
@@ -207,8 +207,8 @@ _queriesMongoTest(HttpConnect connect) {
     .then((response) {
       var results = response.map((world) {
         return {
-          "id": world["id"],
-          "randomnumber": world["randomnumber"]
+          "id": world["_id"],
+          "randomNumber": world["randomNumber"]
         };
       });
       connect.response.write(json.stringify(results.toList()));
@@ -221,7 +221,7 @@ _updatesMongoTest(HttpConnect connect) {
   return Future.wait(new List.generate(queries, (index) {
       return _mongoQuery()
           .then((world) {
-            world["randomnumber"] = _RANDOM.nextInt(_WORLD_TABLE_SIZE);
+            world["randomNumber"] = _RANDOM.nextInt(_WORLD_TABLE_SIZE);
             return _worldCollection.update( { "_id": world["_id"] }, world)
                 .then((_) => world);
           });
@@ -229,8 +229,8 @@ _updatesMongoTest(HttpConnect connect) {
     .then((worlds) {
       var result = worlds.map((world) {
         return {
-          "id": world["id"],
-          "randomnumber": world["randomnumber"]
+          "id": world["_id"],
+          "randomNumber": world["randomNumber"]
         };
       });
       connect.response.write(json.stringify(result.toList()));
@@ -241,7 +241,7 @@ _fortunesMongoTest(HttpConnect connect) {
   
   return _fortuneCollection.find().toList().then((fortunes) {
     fortunes = fortunes.map((fortune) {
-      return new Fortune(fortune["id"], fortune["message"]);
+      return new Fortune(fortune["_id"], fortune["message"]);
     }).toList();
     fortunes.add(new Fortune(0, 'Additional fortune added at request time.'));
     fortunes.sort();
@@ -301,6 +301,6 @@ _query() {
 // runs a mongo query and returns a promise
 _mongoQuery() {
   return _worldCollection.findOne({
-    "id": _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1
+    "_id": _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1
   });
 }

+ 6 - 6
dart-stream/setup.py

@@ -3,19 +3,19 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text('dart-stream/postgresql.yaml', 'host: .*', 'host: ' + args.database_host)
   setup_util.replace_text('dart-stream/mongodb.yaml', 'host: .*', 'host: ' + args.database_host)
   try:
     #
     # install dart dependencies
     #
-    subprocess.check_call('pub install', shell=True, cwd='dart-stream')
+    subprocess.check_call('pub install', shell=True, cwd='dart-stream', stderr=errfile, stdout=logfile)
     #
     # start dart servers
     #
     for port in range(9001, 9001 + args.max_threads):
-      subprocess.Popen('dart server.dart -a 127.0.0.1 -p ' + str(port) + ' -d ' + str(args.max_concurrency / args.max_threads), shell=True, cwd='dart-stream')
+      subprocess.Popen('dart server.dart -a 127.0.0.1 -p ' + str(port) + ' -d ' + str(args.max_concurrency / args.max_threads), shell=True, cwd='dart-stream', stderr=errfile, stdout=logfile)
     #
     # create nginx configuration
     #
@@ -52,16 +52,16 @@ def start(args):
     #
     # start nginx
     #
-    subprocess.Popen('sudo /usr/sbin/nginx -c `pwd`/nginx.conf', shell=True, cwd='dart-stream');
+    subprocess.Popen('sudo /usr/sbin/nginx -c `pwd`/nginx.conf', shell=True, cwd='dart-stream', stderr=errfile, stdout=logfile);
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   #
   # stop nginx
   #
-  subprocess.check_call('sudo /usr/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd='dart-stream')
+  subprocess.check_call('sudo /usr/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd='dart-stream', stderr=errfile, stdout=logfile)
   os.remove('dart-stream/nginx.conf')
   #
   # stop dart servers

+ 6 - 6
dart/setup.py

@@ -3,18 +3,18 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text('dart/postgresql.yaml', 'host: .*', 'host: ' + args.database_host)
   try:
     #
     # install dart dependencies
     #
-    subprocess.check_call('pub install', shell=True, cwd='dart')
+    subprocess.check_call('pub install', shell=True, cwd='dart', stderr=errfile, stdout=logfile)
     #
     # start dart servers
     #
     for port in range(9001, 9001 + args.max_threads):
-      subprocess.Popen('dart server.dart -a 127.0.0.1 -p ' + str(port) + ' -d ' + str(args.max_concurrency / args.max_threads), shell=True, cwd='dart')
+      subprocess.Popen('dart server.dart -a 127.0.0.1 -p ' + str(port) + ' -d ' + str(args.max_concurrency / args.max_threads), shell=True, cwd='dart', stderr=errfile, stdout=logfile)
     #
     # create nginx configuration
     #
@@ -51,16 +51,16 @@ def start(args):
     #
     # start nginx
     #
-    subprocess.Popen('sudo /usr/local/nginx/sbin/nginx -c `pwd`/nginx.conf', shell=True, cwd='dart');
+    subprocess.Popen('sudo /usr/local/nginx/sbin/nginx -c `pwd`/nginx.conf', shell=True, cwd='dart', stderr=errfile, stdout=logfile);
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   #
   # stop nginx
   #
-  subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd='dart')
+  subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c `pwd`/nginx.conf -s stop', shell=True, cwd='dart', stderr=errfile, stdout=logfile)
   os.remove('dart/nginx.conf')
   #
   # stop dart servers

+ 3 - 3
django/setup.py

@@ -10,7 +10,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("django/hello/hello/settings.py", "HOST': '.*'", "HOST': '" + args.database_host + "'")
     setup_util.replace_text("django/hello/hello/settings.py", "\/home\/ubuntu",  home)
@@ -24,10 +24,10 @@ def start(args):
         '-w', str(NCPU*3),
         "--log-level=critical"],
         cwd="django/hello",
-        env=env)
+        env=env, stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 3 - 3
django/setup_pg.py

@@ -10,7 +10,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("django/hello/hello/settings.py", "HOST': '.*'", "HOST': '" + args.database_host + "'")
     setup_util.replace_text("django/hello/hello/settings.py", "\/home\/ubuntu",  home)
@@ -24,10 +24,10 @@ def start(args):
         '-w', str(NCPU*3),
         "--log-level=critical"],
         cwd="django/hello",
-        env=env)
+        env=env, stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 3 - 3
django/setup_py3.py

@@ -10,7 +10,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("django/hello/hello/settings.py", "HOST': '.*'", "HOST': '" + args.database_host + "'")
     setup_util.replace_text("django/hello/hello/settings.py", "\/home\/ubuntu",  home)
@@ -21,10 +21,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="django/hello")
+        cwd="django/hello", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 4 - 4
dropwizard/setup.py

@@ -6,16 +6,16 @@ import os
 
 home = expanduser("~")
 
-def start(args):
+def start(args, logfile, errfile):
     setup_util.replace_text("dropwizard/hello-world.yml", "url: jdbc:mysql://.*/hello_world", "url: jdbc:mysql://" + args.database_host + ":3306/hello_world")
 
     try:
-        subprocess.check_call("mvn clean package;", shell=True, cwd="dropwizard")
-        subprocess.Popen("java -jar target/hello-world-0.0.1-SNAPSHOT.jar server hello-world.yml", shell=True, cwd="dropwizard")
+        subprocess.check_call("mvn clean package;", shell=True, cwd="dropwizard", stderr=errfile, stdout=logfile)
+        subprocess.Popen("java -jar target/hello-world-0.0.1-SNAPSHOT.jar server hello-world.yml", shell=True, cwd="dropwizard", stderr=errfile, stdout=logfile)
         return 0
     except subprocess.CalledProcessError:
         return 1
-def stop():
+def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():

+ 6 - 6
elli/setup_erlang.py

@@ -2,20 +2,20 @@ import subprocess
 import sys
 import setup_util
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("elli/src/elli_bench_sup.erl", "\"benchmarkdbpass\", \".*\", 3306", "\"benchmarkdbpass\", \"" + args.database_host + "\", 3306")
   
   try:
-    subprocess.check_call("./rebar get-deps", shell=True, cwd="elli")
-    subprocess.check_call("./rebar compile", shell=True, cwd="elli")
+    subprocess.check_call("./rebar get-deps", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
+    subprocess.check_call("./rebar compile", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
     # adding +K true seemed to actually slow performance
-    subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached", shell=True, cwd="elli")
+    subprocess.check_call("erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached", shell=True, cwd="elli", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
-    subprocess.check_call("killall beam.smp", shell=True, cwd="/usr/bin")
+    subprocess.check_call("killall beam.smp", shell=True, cwd="/usr/bin", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 8 - 0
evhttp-sharp/.gitignore

@@ -0,0 +1,8 @@
+*.user
+*.suo
+*/bin/*
+*/obj/*
+obj/
+[Bb]in
+[Dd]ebug*/
+[Rr]elease*/

+ 24 - 0
evhttp-sharp/benchmark_config

@@ -0,0 +1,24 @@
+{
+  "framework": "evhttp-sharp",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/",
+      "plaintext_url": "/plaintext",
+      "port": 8085,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "None",
+      "framework": "evhttp-sharp",
+      "language": "C#",
+      "orm": "Raw",
+      "platform": "Mono",
+      "webserver": "none",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "evhttp-sharp",
+      "notes": "",
+      "versus": ""
+    }
+  }]
+}

+ 28 - 0
evhttp-sharp/setup.py

@@ -0,0 +1,28 @@
+import subprocess
+import sys
+import setup_util
+import os
+
+root = os.getcwd() + "/evhttp-sharp"
+app = root + "/src"
+
+def start(args, logfile, errfile):
+  if os.name == 'nt':
+    return 1
+
+  try:
+    # build
+    subprocess.check_call("rm -rf bin obj", shell=True, cwd=app, stdout=logfile, stderr=errfile)
+    subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd=app, stdout=logfile, stderr=errfile)
+    
+    subprocess.Popen("mono -O=all bin/Release/EvHttpSharpBenchmark.exe 127.0.0.1 8085 " + str(args.max_threads) + " &", shell=True, cwd=app, stdout=logfile, stderr=errfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+
+def stop(logfile, errfile):
+  if os.name == 'nt':
+    return 0
+  
+  subprocess.check_call("pkill -9 mono", shell=True)
+  return 0

+ 69 - 0
evhttp-sharp/src/EvHttpSharpBenchmark.csproj

@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{94B0D092-4377-4A5C-B222-4F005D316DB0}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>EvHttpSharpBenchmark</RootNamespace>
+    <AssemblyName>EvHttpSharpBenchmark</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="EvHttpSharp">
+      <HintPath>lib\EvHttpSharp.dll</HintPath>
+    </Reference>
+    <Reference Include="Newtonsoft.Json">
+      <HintPath>lib\Newtonsoft.Json.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="libevent_core-2-0-5.dll">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="libevent_extra-2-0-5.dll">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 20 - 0
evhttp-sharp/src/EvHttpSharpBenchmark.sln

@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EvHttpSharpBenchmark", "EvHttpSharpBenchmark.csproj", "{94B0D092-4377-4A5C-B222-4F005D316DB0}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{94B0D092-4377-4A5C-B222-4F005D316DB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{94B0D092-4377-4A5C-B222-4F005D316DB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{94B0D092-4377-4A5C-B222-4F005D316DB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{94B0D092-4377-4A5C-B222-4F005D316DB0}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 37 - 0
evhttp-sharp/src/Program.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+using EvHttpSharp;
+using Newtonsoft.Json;
+
+namespace EvHttpSharpBenchmark
+{
+	class Program
+	{
+		public static readonly JsonSerializer Serializer = new JsonSerializer();
+
+		static void Main (string[] args)
+		{
+			var host = new EventHttpListener(Handler);
+			host.Start(args[0], ushort.Parse(args[1]), int.Parse(args[2]));
+		}
+
+		private static void Handler(EventHttpRequest req)
+		{
+			var headers = new Dictionary<string, string>();
+			var resp = "Hello, World!";
+
+			if (!req.Uri.Contains("plaintext"))
+			{
+				var sw = new StringWriter();
+				Serializer.Serialize(sw, new {message = "Hello, world"});
+				resp = sw.ToString();
+				headers["Content-Type"] = "application/json";
+			}
+			req.Respond (HttpStatusCode.OK, headers, Encoding.UTF8.GetBytes (resp));
+		}
+	}
+}

+ 36 - 0
evhttp-sharp/src/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle ("EvHttpSharpBenchmark")]
+[assembly: AssemblyDescription ("")]
+[assembly: AssemblyConfiguration ("")]
+[assembly: AssemblyCompany ("")]
+[assembly: AssemblyProduct ("EvHttpSharpBenchmark")]
+[assembly: AssemblyCopyright ("Copyright ©  2013")]
+[assembly: AssemblyTrademark ("")]
+[assembly: AssemblyCulture ("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible (false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid ("8c379b35-c45f-4d4b-b54a-2a38ec7112d4")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion ("1.0.0.0")]
+[assembly: AssemblyFileVersion ("1.0.0.0")]

BIN
evhttp-sharp/src/lib/EvHttpSharp.dll


BIN
evhttp-sharp/src/lib/Newtonsoft.Json.dll


BIN
evhttp-sharp/src/lib/libevent_core-2-0-5.dll


BIN
evhttp-sharp/src/lib/libevent_extra-2-0-5.dll


BIN
evhttp-sharp/src/libevent_core-2-0-5.dll


BIN
evhttp-sharp/src/libevent_extra-2-0-5.dll


+ 12 - 12
express/setup.py

@@ -4,37 +4,37 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("express/app.js", "mongodb:\/\/.*\/hello_world", "mongodb://" + args.database_host + "/hello_world")
   setup_util.replace_text("express/app.js", "localhost", args.database_host)
 
   try:
-    npm()
+    npm(logfile,errfile)
     if os.name == 'nt':
-      subprocess.Popen("set NODE_ENV=production", shell=True)
-      subprocess.Popen("node app", shell=True, cwd="express")
+      subprocess.Popen("set NODE_ENV=production", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.Popen("node app", shell=True, cwd="express", stderr=errfile, stdout=logfile)
     else:
-      subprocess.Popen("NODE_ENV=production node app", shell=True, cwd="express")
+      subprocess.Popen("NODE_ENV=production node app", shell=True, cwd="express", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def npm():
+def npm(logfile, errfile):
   if os.name == 'nt':
-    subprocess.check_call("copy package.json package.json.dist /y > NUL", shell=True, cwd="express")
+    subprocess.check_call("copy package.json package.json.dist /y > NUL", shell=True, cwd="express", stderr=errfile, stdout=logfile)
     setup_util.replace_text("express/package.json", ".*mysql.*", "")
     setup_util.replace_text("express/package.json", ".*mapper.*", "")
   
   try:
-    subprocess.check_call("npm install", shell=True, cwd="express")
+    subprocess.check_call("npm install", shell=True, cwd="express", stderr=errfile, stdout=logfile)
   finally:
     if os.name == 'nt':
-      subprocess.check_call("del package.json", shell=True, cwd="express")
-      subprocess.check_call("ren package.json.dist package.json", shell=True, cwd="express")
+      subprocess.check_call("del package.json", shell=True, cwd="express", stderr=errfile, stdout=logfile)
+      subprocess.check_call("ren package.json.dist package.json", shell=True, cwd="express", stderr=errfile, stdout=logfile)
 
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.Popen("taskkill /f /im node.exe > NUL", shell=True)
+    subprocess.Popen("taskkill /f /im node.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
     return 0
   
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)

+ 3 - 3
falcon/setup.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     proc = subprocess.Popen([
         bin_dir + "/gunicorn",
@@ -18,10 +18,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="falcon")
+        cwd="falcon", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
     out, err = p.communicate()
     for line in out.splitlines():

+ 3 - 3
falcon/setup_py3.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     proc = subprocess.Popen([
         bin_dir + "/gunicorn",
@@ -18,10 +18,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="falcon")
+        cwd="falcon", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 3 - 3
falcon/setup_pypy.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     proc = subprocess.Popen([
         bin_dir + "/gunicorn",
@@ -18,10 +18,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="falcon")
+        cwd="falcon", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 9 - 9
falcore/setup.py

@@ -3,27 +3,27 @@ import sys
 import os
 import setup_util
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("falcore/src/framework_benchmarks/falcore.go", "tcp\(.*:3306\)", "tcp(" + args.database_host + ":3306)")
   if os.name == 'nt':
     #subprocess.call("rmdir /s /q pkg\\windows_amd64", shell=True, cwd="go")
     #subprocess.call("rmdir /s /q src\\github.com", shell=True, cwd="go")
     #subprocess.call("del /s /q /f bin\\hello.exe", shell=True, cwd="go")
-    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\falcore&& go get ./...", shell=True, cwd="falcore")
-    subprocess.Popen("setup.bat", shell=True, cwd="falcore") 
+    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\falcore&& go get ./...", shell=True, cwd="falcore", stderr=errfile, stdout=logfile)
+    subprocess.Popen("setup.bat", shell=True, cwd="falcore", stderr=errfile, stdout=logfile) 
     return 0
-  subprocess.call("go get ./...", shell=True, cwd="falcore") 
-  subprocess.Popen("go run src/framework_benchmarks/falcore.go".rsplit(" "), cwd="falcore")
+  subprocess.call("go get ./...", shell=True, cwd="falcore", stderr=errfile, stdout=logfile) 
+  subprocess.Popen("go run src/framework_benchmarks/falcore.go".rsplit(" "), cwd="falcore", stderr=errfile, stdout=logfile)
   return 0
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.call("taskkill /f /im go.exe > NUL", shell=True)
-    subprocess.call("taskkill /f /im falcore.exe > NUL", shell=True)
+    subprocess.call("taskkill /f /im go.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("taskkill /f /im falcore.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
     return 0
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():
-    if 'falcore' in line:
+    if 'falcore' in line and 'run-tests' not in line:
       pid = int(line.split(None, 2)[1])
       os.kill(pid, 9)
   return 0

+ 1 - 3
falcore/src/framework_benchmarks/falcore.go

@@ -31,11 +31,9 @@ type Fortune struct {
 	Message string `json:"message"`
 }
 
-// TODO: remove ?charset=utf8 from DSN after the next Go-MySQL-Driver release
-// https://github.com/go-sql-driver/mysql#unicode-support
 const (
 	// Database
-	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world?charset=utf8"
+	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world"
 	worldSelect        = "SELECT id, randomNumber FROM World WHERE id = ?"
 	worldUpdate        = "UPDATE World SET randomNumber = ? WHERE id = ?"
 	fortuneSelect      = "SELECT id, message FROM Fortune;"

+ 7 - 7
finagle/setup.py

@@ -4,24 +4,24 @@ import sys
 import time
 import os
 
-def start(args=None):
+def start(args, logfile, errfile):
 
 
     if os.name == 'nt':
-      subprocess.check_call("..\\sbt\\sbt.bat update compile", shell=True, cwd="finagle")
-      subprocess.Popen("..\\sbt\\sbt.bat -Ddb.host=" + args.database_host + " run", cwd="finagle", shell=True)
+      subprocess.check_call("..\\sbt\\sbt.bat update compile", shell=True, cwd="finagle", stderr=errfile, stdout=logfile)
+      subprocess.Popen("..\\sbt\\sbt.bat -Ddb.host=" + args.database_host + " run", cwd="finagle", shell=True, stderr=errfile, stdout=logfile)
     else:
-      subprocess.check_call("../sbt/sbt update compile", shell=True, cwd="finagle")
-      subprocess.Popen("../sbt/sbt -Ddb.host=" + args.database_host + " run", cwd="finagle", shell=True)
+      subprocess.check_call("../sbt/sbt update compile", shell=True, cwd="finagle", stderr=errfile, stdout=logfile)
+      subprocess.Popen("../sbt/sbt -Ddb.host=" + args.database_host + " run", cwd="finagle", shell=True, stderr=errfile, stdout=logfile)
 
     time.sleep(5)
     return 0
 
 
 
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.check_call("wmic process where \"CommandLine LIKE '%\\\\sbt\\\\sbt%'\" call terminate")
+    subprocess.check_call("wmic process where \"CommandLine LIKE '%\\\\sbt\\\\sbt%'\" call terminate", stderr=errfile, stdout=logfile)
   else:
     p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
     out, err = p.communicate()

+ 65 - 35
finagle/src/main/scala/com/falmarri/finagle/Finagle.scala

@@ -1,25 +1,40 @@
 package com.falmarri.finagle
 
+import scala.util.Random
+import scala.collection.immutable.StringOps
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.module.scala.DefaultScalaModule
-import com.twitter.finagle.builder.ClientBuilder
-import com.twitter.finagle.exp.mysql.{Client, IntValue, MySQL, Row}
-import com.twitter.finagle.http.{HttpMuxer, Request, Response}
-import com.twitter.finagle.{Http, Service}
-import com.twitter.util.{Future, FuturePool}
-import java.net.InetSocketAddress
 import java.util.concurrent.Executors
+import com.twitter.finagle.Service
+import com.twitter.finagle.exp.Mysql
+import com.twitter.finagle.exp.mysql._
+import org.jboss.netty.handler.codec.http._
+import org.jboss.netty.handler.codec.http.HttpResponseStatus._
+import org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1
 import org.jboss.netty.buffer.ChannelBuffers.wrappedBuffer
-import scala.util.Random
+import com.twitter.util.{Future, FuturePool}
+import java.net.InetSocketAddress
+import com.twitter.finagle.builder.{Server, ServerBuilder}
+import com.twitter.finagle.http.{Http,HttpMuxer}
 
 object FinagleBenchmark extends App {
   val maxConnections = 256
 
-  val mysql = new Client(ClientBuilder()
-    .codec(new MySQL("benchmarkdbuser", "benchmarkdbpass", Some("hello_world")))
-    .hosts(new InetSocketAddress(System.getProperty("db.host", "localhost"), 3306))
-    .hostConnectionLimit(maxConnections)
-    .buildFactory())
+  //val mysql = new Client(ClientBuilder()
+  //  .codec(new MySQL("benchmarkdbuser", "benchmarkdbpass", Some("hello_world")))
+  //  .hosts(new InetSocketAddress(System.getProperty("db.host", "localhost"), 3306))
+  //  .hostConnectionLimit(maxConnections)
+  //  .buildFactory())
+
+  val username = "benchmarkdbuser"
+  val password = "benchmarkdbpass"
+  val db = "hello_world"
+  val host = System.getProperty("db.host", "localhost")
+
+  val mysql = Mysql
+      .withCredentials(username, password)
+      .withDatabase(db)
+      .newRichClient(host + ":3306")
 
   val pool = FuturePool(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 2))
 
@@ -41,37 +56,52 @@ object FinagleBenchmark extends App {
   def serialize(result: Any): Array[Byte] =
     mapper.writeValueAsBytes(result)
 
-  def createResponse(req: Request, bytes: Array[Byte]) = {
+  def createResponse(req: HttpRequest, bytes: Array[Byte]) = {
     val body = wrappedBuffer(bytes)
-    val resp = req.response
-    resp.setContentTypeJson
+    val resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)
+    //resp.setContentTypeJson
     resp.setContent(body)
-    resp.contentLength = body.readableBytes
+    //resp.contentLength = body.readableBytes
     resp
   }
 
-  HttpMuxer.addRichHandler("/json", new Service[Request, Response] {
-    def apply(req: Request): Future[Response] = pool {
-      createResponse(req, serialize(Map("message" -> "Hello, World!")))
-    }
-  })
-
-  HttpMuxer.addRichHandler("/db", new Service[Request, Response] {
-    val rand = new Random()
-    val sql = "SELECT * FROM world WHERE id = "
+  val muxService = new HttpMuxer()
+    .withHandler("/json", new Service[HttpRequest, HttpResponse] {
+      def apply(req: HttpRequest): Future[HttpResponse] = pool {
+        createResponse(req, serialize(Map("message" -> "Hello, World!")))
+      }
+    })
+    .withHandler("/db", new Service[HttpRequest, HttpResponse] {
+      val rand = new Random()
+      val sql = "SELECT * FROM world WHERE id = "
 
-    def apply(req: Request): Future[Response] = {
-      val n = req.params.getIntOrElse("queries", 1)
+      def apply(req: HttpRequest): Future[HttpResponse] = {
+        //val n = req.params.getIntOrElse("queries", 1)
+        val decoder = new QueryStringDecoder(req.getUri())
+        val n = {
+          val queries = decoder.getParameters().get("queries")
+          if(queries == null) {
+            1
+          }
+          else {
+            queries.get(0).toInt
+          }
+        }
 
-      val qs = (0 until n) map { i =>
-        mysql.select(sql + rand.nextInt(10000))(rowToMap)
-      }
+        val qs = (0 until n) map { i =>
+          mysql.select(sql + rand.nextInt(10000))(rowToMap)
+        }
 
-      Future.collect(qs) map { results =>
-        createResponse(req, serialize(results.flatten))
+        Future.collect(qs) map { results =>
+          createResponse(req, serialize(results.flatten))
+        }
       }
-    }
-  })
+    })
 
-  Http.serve(new InetSocketAddress(8080), HttpMuxer)
+  //Http.serve(new InetSocketAddress(8080), HttpMuxer)
+  val server: Server = ServerBuilder()
+    .codec(Http())
+    .bindTo(new InetSocketAddress(8080))
+    .name("HttpServer")
+    .build(muxService)
 }

+ 3 - 3
flask/setup.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("flask/app.py", "DBHOSTNAME", args.database_host)
     proc = subprocess.Popen([
@@ -19,10 +19,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="flask")
+        cwd="flask", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
     out, err = p.communicate()
     for line in out.splitlines():

+ 6 - 6
flask/setup_nginxuwsgi.py

@@ -7,23 +7,23 @@ bin_dir = os.path.expanduser('~/FrameworkBenchmarks/installs/py2/bin')
 config_dir = os.path.expanduser('~/FrameworkBenchmarks/config')
 NCPU = multiprocessing.cpu_count()
 
-def start(args):
+def start(args, logfile, errfile):
     setup_util.replace_text("flask/app.py", "DBHOSTNAME", args.database_host)
     try:
         subprocess.check_call('sudo /usr/local/nginx/sbin/nginx -c ' +
-            config_dir + '/nginx_uwsgi.conf', shell=True)
+            config_dir + '/nginx_uwsgi.conf', shell=True, stderr=errfile, stdout=logfile)
         # Run in the background, but keep stdout/stderr for easy debugging
         subprocess.Popen(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi.ini' +
             ' --processes ' + str(NCPU * 3) +
             ' --wsgi app:app',
-            shell=True, cwd='flask')
+            shell=True, cwd='flask', stderr=errfile, stdout=logfile)
         return 0
     except subprocess.CalledProcessError:
         return 1
 
-def stop():
-    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True)
-    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True)
+def stop(logfile, errfile):
+    subprocess.call('sudo /usr/local/nginx/sbin/nginx -s stop', shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call(bin_dir + '/uwsgi --ini ' + config_dir + '/uwsgi_stop.ini', shell=True, stderr=errfile, stdout=logfile)
 
     p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
     out, err = p.communicate()

+ 3 - 3
flask/setup_py3.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("flask/app.py", "DBHOSTNAME", args.database_host)
     proc = subprocess.Popen([
@@ -19,10 +19,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="flask")
+        cwd="flask", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 3 - 3
flask/setup_pypy.py

@@ -9,7 +9,7 @@ NCPU = multiprocessing.cpu_count()
 proc = None
 
 
-def start(args):
+def start(args, logfile, errfile):
     global proc
     setup_util.replace_text("flask/app.py", "DBHOSTNAME", args.database_host)
     proc = subprocess.Popen([
@@ -19,10 +19,10 @@ def start(args):
         "-b", "0.0.0.0:8080",
         '-w', str(NCPU*3),
         "--log-level=critical"],
-        cwd="flask")
+        cwd="flask", stderr=errfile, stdout=logfile)
     return 0
 
-def stop():
+def stop(logfile, errfile):
     global proc
     if proc is None:
         return 0

+ 7 - 6
gemini/setup.py

@@ -6,20 +6,21 @@ from os.path import expanduser
 
 home = expanduser("~")
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("gemini/Docroot/WEB-INF/GeminiHello.conf", "db.ConnectString = .*:3306", "db.ConnectString = " + args.database_host + ":3306")
   setup_util.replace_text("gemini/Docroot/WEB-INF/resin.xml", "root-directory=\".*\/FrameworkBenchmarks", "root-directory=\"" + home + "/FrameworkBenchmarks")
   
   try:
-    subprocess.call("mkdir classes", shell=True, cwd="gemini/Docroot/WEB-INF")
-    subprocess.check_call("ant compile", shell=True, cwd="gemini")
-    subprocess.check_call("$RESIN_HOME/bin/resinctl -conf $HOME/FrameworkBenchmarks/gemini/Docroot/WEB-INF/resin.xml start", shell=True)
+    # This was reporting an error because it already exists... not sure.
+    #subprocess.call("mkdir classes", shell=True, cwd="gemini/Docroot/WEB-INF", stderr=errfile, stdout=logfile)
+    subprocess.check_call("ant compile", shell=True, cwd="gemini", stderr=errfile, stdout=logfile)
+    subprocess.check_call("$RESIN_HOME/bin/resinctl -conf $HOME/FrameworkBenchmarks/gemini/Docroot/WEB-INF/resin.xml start", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
-    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
+    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 8 - 8
go/setup.py

@@ -3,22 +3,22 @@ import sys
 import os
 import setup_util
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("go/src/hello/hello.go", "tcp\(.*:3306\)", "tcp(" + args.database_host + ":3306)")
   if os.name == 'nt':
     #subprocess.call("rmdir /s /q pkg\\windows_amd64", shell=True, cwd="go")
     #subprocess.call("rmdir /s /q src\\github.com", shell=True, cwd="go")
     #subprocess.call("del /s /q /f bin\\hello.exe", shell=True, cwd="go")
-    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\go&& go get ./...", shell=True, cwd="go")
-    subprocess.Popen("setup.bat", shell=True, cwd="go") 
+    subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\go&& go get ./...", shell=True, cwd="go", stderr=errfile, stdout=logfile)
+    subprocess.Popen("setup.bat", shell=True, cwd="go", stderr=errfile, stdout=logfile) 
     return 0
-  subprocess.call("go get ./...", shell=True, cwd="go") 
-  subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="go")
+  subprocess.call("go get ./...", shell=True, cwd="go", stderr=errfile, stdout=logfile) 
+  subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="go", stderr=errfile, stdout=logfile)
   return 0
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.call("taskkill /f /im go.exe > NUL", shell=True)
-    subprocess.call("taskkill /f /im hello.exe > NUL", shell=True)
+    subprocess.call("taskkill /f /im go.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.call("taskkill /f /im hello.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
     return 0
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()

+ 1 - 3
go/src/hello/hello.go

@@ -28,11 +28,9 @@ type Fortune struct {
 	Message string `json:"message"`
 }
 
-// TODO: remove ?charset=utf8 from DSN after the next Go-MySQL-Driver release
-// https://github.com/go-sql-driver/mysql#unicode-support
 const (
 	// Database
-	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world?charset=utf8"
+	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world"
 	worldSelect        = "SELECT id, randomNumber FROM World WHERE id = ?"
 	worldUpdate        = "UPDATE World SET randomNumber = ? WHERE id = ?"
 	fortuneSelect      = "SELECT id, message FROM Fortune;"

+ 21 - 4
grails/README.md

@@ -4,17 +4,34 @@ This is the Grails portion of a [benchmarking test suite](../) comparing a varie
 
 ## Infrastructure Software Versions
 The tests were run with:
-* [Grails 2.3.1](http://grails.org/)
+* [Grails 2.3.3](http://grails.org/)
 * [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
 * [Resin 4.0.34](http://www.caucho.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 
 ## Test URLs
-### JSON Encoding Test
+
+### Test type 1: JSON serialization
 
 http://localhost:8080/grails/hello/json
 
-### Data-Store/Database Mapping Test
+### Test type 2: Single database query
+
+http://localhost:8080/grails/hello/db
+
+### Test type 3: Multiple database queries
+
+http://localhost:8080/grails/hello/queries?queries=10
+
+### Test type 4: Fortunes
+
+http://localhost:8080/grails/hello/fortunes
+
+### Test type 5: Database updates
+
+http://localhost:8080/grails/hello/updates?queries=10
+
+### Test type 6: Plaintext
 
-http://localhost:8080/grails/hello/db?queries=5
+http://localhost:8080/grails/hello/plaintext

+ 5 - 3
grails/benchmark_config

@@ -5,7 +5,10 @@
       "setup_file": "setup",
       "json_url": "/grails/hello/json",
       "db_url": "/grails/hello/db",
-      "query_url": "/grails/hello/db?queries=",
+      "query_url": "/grails/hello/queries?queries=",
+      "fortune_url": "/grails/hello/fortunes",
+      "update_url": "/grails/hello/updates?queries=",
+      "plaintext_url": "/grails/hello/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Fullstack",
@@ -19,8 +22,7 @@
       "database_os": "Linux",
       "display_name": "grails",
       "notes": "",
-      "versus": "servlet",
-      "skip": "true"
+      "versus": "servlet"
     }
   }]
 }

+ 15 - 13
grails/hello/.classpath

@@ -1,14 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <classpath>
-    <classpathentry kind="src" path="src/java"/>
-    <classpathentry kind="src" path="src/groovy"/>
-    <classpathentry kind="src" path="grails-app/conf"/>
-    <classpathentry kind="src" path="grails-app/controllers"/>
-    <classpathentry kind="src" path="grails-app/domain"/>
-    <classpathentry kind="src" path="grails-app/services"/>
-    <classpathentry kind="src" path="grails-app/taglib"/>
-    <classpathentry kind="src" path="test/integration"/>
-    <classpathentry kind="src" path="test/unit"/>
-    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
-    <classpathentry kind="con" path="com.springsource.sts.grails.core.CLASSPATH_CONTAINER"/>
-    <classpathentry kind="output" path="web-app/WEB-INF/classes"/>
-</classpath>
+	<classpathentry kind="src" path="src/java"/>
+	<classpathentry kind="src" path="src/groovy"/>
+	<classpathentry kind="src" path="grails-app/conf"/>
+	<classpathentry kind="src" path="grails-app/controllers"/>
+	<classpathentry kind="src" path="grails-app/domain"/>
+	<classpathentry kind="src" path="grails-app/services"/>
+	<classpathentry kind="src" path="grails-app/taglib"/>
+	<classpathentry kind="src" path="grails-app/utils"/>
+	<classpathentry kind="src" path="test/integration"/>
+	<classpathentry kind="src" path="test/unit"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.grails.ide.eclipse.core.CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target-eclipse/classes"/>
+</classpath>

+ 17 - 0
grails/hello/.gitignore

@@ -0,0 +1,17 @@
+*.iws
+*Db.properties
+*Db.script
+.settings
+stacktrace.log
+/*.zip
+/plugin.xml
+/*.log
+/*DB.*
+/cobertura.ser
+.DS_Store
+/target/
+/out/
+/web-app/plugins
+/web-app/WEB-INF/classes
+/.link_to_grails_plugins/
+/target-eclipse/

+ 7 - 1
grails/hello/.project

@@ -5,6 +5,11 @@
 	<projects>
 	</projects>
 	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.common.project.facet.core.builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
 		<buildCommand>
 			<name>org.eclipse.jdt.core.javabuilder</name>
 			<arguments>
@@ -12,8 +17,9 @@
 		</buildCommand>
 	</buildSpec>
 	<natures>
-	    <nature>com.springsource.sts.grails.core.nature</nature>
+		<nature>org.grails.ide.eclipse.core.nature</nature>
 		<nature>org.eclipse.jdt.groovy.core.groovyNature</nature>
 		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
 	</natures>
 </projectDescription>

+ 2 - 2
grails/hello/application.properties

@@ -1,6 +1,6 @@
 #Grails Metadata file
-#Sat Oct 26 13:32:20 PDT 2013
-app.grails.version=2.3.1
+#Sun Oct 20 22:08:59 EEST 2013
+app.grails.version=2.3.3
 app.name=hello
 app.servlet.version=2.5
 app.version=0.1

+ 32 - 5
grails/hello/grails-app/conf/BuildConfig.groovy

@@ -2,10 +2,34 @@ grails.servlet.version = "2.5" // Change depending on target container complianc
 grails.project.class.dir = "target/classes"
 grails.project.test.class.dir = "target/test-classes"
 grails.project.test.reports.dir = "target/test-reports"
+grails.project.work.dir = "target/work"
 grails.project.target.level = 1.7
 grails.project.source.level = 1.7
 //grails.project.war.file = "target/${appName}-${appVersion}.war"
 
+grails.project.fork = [
+    // configure settings for compilation JVM, note that if you alter the Groovy version forked compilation is required
+    //  compile: [maxMemory: 256, minMemory: 64, debug: false, maxPerm: 256, daemon:true],
+
+    // configure settings for the test-app JVM, uses the daemon by default
+    test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, daemon:true],
+    // configure settings for the run-app JVM
+    run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
+    // configure settings for the run-war JVM
+    war: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
+    // configure settings for the Console UI JVM
+    console: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256]
+]
+
+def yjpConfig = [jvmArgs: [
+        "-agentpath:/opt/yjp/bin/linux-x86-64/libyjpagent.so=delay=30000,disablealloc,disablej2ee,noj2ee,builtinprobes=none,sampling,monitors,onexit=snapshot,telemetryperiod=250"
+    ]]
+if (System.getProperty("grails.yjp")) {
+    grails.project.fork.war += yjpConfig
+    println "Using YJP for run-war"
+}
+
+grails.project.dependency.resolver = "maven" // or ivy
 grails.project.dependency.resolution = {
     // inherit Grails' default dependencies
     inherits("global") {
@@ -14,11 +38,13 @@ grails.project.dependency.resolution = {
     }
     log "error" // log level of Ivy resolver, either 'error', 'warn', 'info', 'debug' or 'verbose'
     checksums true // Whether to verify checksums on resolve
+    legacyResolve false // whether to do a secondary resolve on plugin installation, not advised and here for backwards compatibility
 
     repositories {
         inherits true // Whether to inherit repository definitions from plugins
         grailsPlugins()
         grailsHome()
+		mavenLocal()
         grailsCentral()
         mavenCentral()
 
@@ -33,18 +59,19 @@ grails.project.dependency.resolution = {
     dependencies {
         // specify dependencies here under either 'build', 'compile', 'runtime', 'test' or 'provided' scopes eg.
 
-        runtime 'mysql:mysql-connector-java:5.1.22'
+        runtime 'mysql:mysql-connector-java:5.1.27'
     }
 
     plugins {
-        compile ":hibernate:3.6.10.2"
-        runtime ":jquery:1.7.1"
-        runtime ":resources:1.1.6"
+        runtime ":hibernate:3.6.10.4"
+        //runtime ":jquery:1.10.2"
+        //runtime ":resources:1.2.1"
 
         // Uncomment these (or add new ones) to enable additional resources capabilities
         //runtime ":zipped-resources:1.0"
         //runtime ":cached-resources:1.0"
         //runtime ":yui-minify-resources:0.1.4"
-        build ':tomcat:7.0.40.1'
+
+        build ":tomcat:7.0.47"
     }
 }

+ 49 - 42
grails/hello/grails-app/conf/Config.groovy

@@ -12,21 +12,26 @@
 
 
 grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination
-grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format
-grails.mime.use.accept.header = false
-grails.mime.types = [ html: ['text/html','application/xhtml+xml'],
-                      xml: ['text/xml', 'application/xml'],
-                      text: 'text/plain',
-                      js: 'text/javascript',
-                      rss: 'application/rss+xml',
-                      atom: 'application/atom+xml',
-                      css: 'text/css',
-                      csv: 'text/csv',
-                      all: '*/*',
-                      json: ['application/json','text/json'],
-                      form: 'application/x-www-form-urlencoded',
-                      multipartForm: 'multipart/form-data'
-                    ]
+
+grails.app.context = '/grails'
+
+// The ACCEPT header will not be used for content negotiation for user agents containing the following strings (defaults to the 4 major rendering engines)
+grails.mime.disable.accept.header.userAgents = ['Gecko', 'WebKit', 'Presto', 'Trident']
+grails.mime.types = [
+    all:           '*/*',
+    atom:          'application/atom+xml',
+    css:           'text/css',
+    csv:           'text/csv',
+    form:          'application/x-www-form-urlencoded',
+    html:          ['text/html','application/xhtml+xml'],
+    js:            'text/javascript',
+    json:          ['application/json', 'text/json'],
+    multipartForm: 'multipart/form-data',
+    rss:           'application/rss+xml',
+    text:          'text/plain',
+    hal:           ['application/hal+json','application/hal+xml'],
+    xml:           ['text/xml', 'application/xml']
+]
 
 // URL Mapping Cache Max Size, defaults to 5000
 //grails.urlmapping.cache.maxsize = 1000
@@ -34,10 +39,33 @@ grails.mime.types = [ html: ['text/html','application/xhtml+xml'],
 // What URL patterns should be processed by the resources plugin
 grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']
 
+// Legacy setting for codec used to encode data with ${}
+grails.views.default.codec = "html"
+
+// The default scope for controllers. May be prototype, session or singleton.
+// If unspecified, controllers are prototype scoped.
+grails.controllers.defaultScope = 'singleton'
 
-// The default codec used to encode data with ${}
-grails.views.default.codec = "none" // none, html, base64
-grails.views.gsp.encoding = "UTF-8"
+// GSP settings
+grails {
+    views {
+        gsp {
+            encoding = 'UTF-8'
+            htmlcodec = 'xml' // use xml escaping instead of HTML4 escaping
+            codecs {
+                expression = 'html' // escapes values inside ${}
+                scriptlet = 'html' // escapes output from scriptlets in GSPs
+                taglib = 'none' // escapes output from taglibs
+                staticparts = 'none' // escapes output from static template parts
+            }
+        }
+        // escapes all not-encoded output at final stage of outputting
+        filteringCodecForContentType {
+            //'text/html' = 'html'
+        }
+    }
+}
+ 
 grails.converters.encoding = "UTF-8"
 // enable Sitemesh preprocessing of GSP pages
 grails.views.gsp.sitemesh.preprocess = true
@@ -59,6 +87,9 @@ grails.exceptionresolver.params.exclude = ['password']
 // disabling query cache
 grails.hibernate.cache.queries = false
 
+// OSIV is readonly by default
+grails.hibernate.osiv.readonly = true
+
 // set per-environment serverURL stem for creating absolute links
 environments {
     development {
@@ -91,27 +122,3 @@ log4j = {
            'org.hibernate',
            'net.sf.ehcache.hibernate'
 }
-
-// Uncomment and edit the following lines to start using Grails encoding & escaping improvements
-
-/* remove this line 
-// GSP settings
-grails {
-    views {
-        gsp {
-            encoding = 'UTF-8'
-            htmlcodec = 'xml' // use xml escaping instead of HTML4 escaping
-            codecs {
-                expression = 'html' // escapes values inside null
-                scriptlet = 'none' // escapes output from scriptlets in GSPs
-                taglib = 'none' // escapes output from taglibs
-                staticparts = 'none' // escapes output from static template parts
-            }
-        }
-        // escapes all not-encoded output at final stage of outputting
-        filteringCodecForContentType {
-            //'text/html' = 'html'
-        }
-    }
-}
-remove this line */

+ 31 - 3
grails/hello/grails-app/conf/DataSource.groovy

@@ -1,25 +1,53 @@
+import org.springframework.beans.factory.config.PropertiesFactoryBean
+import org.springframework.core.io.support.ResourceArrayPropertyEditor
+
 dataSource {
     pooled = true
     dbCreate = "update"
-    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"
+    url = "jdbc:mysql://localhost:3306/hello_world"
     driverClassName = "com.mysql.jdbc.Driver"
     dialect = org.hibernate.dialect.MySQL5InnoDBDialect
     username = "benchmarkdbuser"
     password = "benchmarkdbpass"
     properties {
-        maxActive = 256
+        fairQueue = false
+        maxActive = 512
         maxIdle = 25
         minIdle = 5
         initialSize = 5
         minEvictableIdleTimeMillis = 60000
         timeBetweenEvictionRunsMillis = 60000
         maxWait = 10000
-        validationQuery = "/* ping */"
+        maxAge = 1800 * 1000
+        numTestsPerEvictionRun=3
+        testOnBorrow=false
+        testWhileIdle=true
+        testOnReturn=false
+        validationQuery="/* ping */"
+        validationInterval=15000
+        jdbcInterceptors="ConnectionState;StatementCache"
+        defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_UNCOMMITTED
+        dbProperties = this.loadProperties("classpath:mysql-connection.properties")
     }
 }
+
 hibernate {
     // Purposely turning off query cache
     cache.use_second_level_cache = false
     cache.use_query_cache = false
     cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
+    default_batch_fetch_size=256
+    jdbc.fetch_size=256
+    jdbc.batch_size=500
 }
+
+static Properties loadProperties(String path) {
+    PropertiesFactoryBean pfb=new PropertiesFactoryBean()
+    pfb.setIgnoreResourceNotFound(true)
+    def converter=new ResourceArrayPropertyEditor()
+    converter.setAsText(path)
+    pfb.setLocations(converter.getValue())
+    pfb.afterPropertiesSet()
+    return pfb.object
+}
+

+ 18 - 0
grails/hello/grails-app/conf/JsonBootStrap.groovy

@@ -0,0 +1,18 @@
+import org.codehaus.groovy.grails.web.converters.Converter
+import org.codehaus.groovy.grails.web.json.JSONWriter
+import grails.converters.JSON
+import hello.World
+
[email protected]
+class JsonBootStrap {
+    def init = { servletContext ->
+        JSON.registerObjectMarshaller(World, { World world, Converter converter ->
+            JSONWriter writer = (JSONWriter)converter.writer
+            writer.object()
+            writer.key('id').value(world.id)
+            writer.key('randomNumber').value(world.randomNumber)
+            writer.endObject()
+            null
+        })
+    }
+}

+ 19 - 0
grails/hello/grails-app/conf/JsonWorkaroundBootStrap.groovy

@@ -0,0 +1,19 @@
+import org.codehaus.groovy.grails.web.json.JSONObject
+import org.springframework.util.ClassUtils
+import org.springframework.util.ReflectionUtils
+
+class JsonWorkaroundBootStrap {
+    def init = { servletContext ->
+        // activate workaround for GRAILS-10823
+        println("activating workaround for GRAILS-10823 - use this only for Grails 2.3.3")
+        def encoderInstance = ClassUtils.forName("org.codehaus.groovy.grails.plugins.codecs.JSONEncoder", JSONObject.class.getClassLoader()).newInstance()
+        ['javascriptEncoderStateless', 'javascriptEncoder'].each { fieldName ->
+            ReflectionUtils.findField(JSONObject, fieldName).with {
+                accessible = true
+                set(null, encoderInstance)
+            }
+        }
+    }
+    def destroy = {
+    }
+}

+ 1 - 1
grails/hello/grails-app/conf/UrlMappings.groovy

@@ -1,7 +1,7 @@
 class UrlMappings {
 
 	static mappings = {
-		"/$controller/$action?/$id?"{
+        "/$controller/$action?/$id?(.${format})?"{
 			constraints {
 				// apply constraints here
 			}

+ 60 - 0
grails/hello/grails-app/conf/mysql-connection.properties

@@ -0,0 +1,60 @@
+# MYSQL JDBC Connection properties
+# http://dev.mysql.com/doc/refman/5.5/en/connector-j-reference-configuration-properties.html
+jdbcCompliantTruncation=false
+autoReconnect=false
+zeroDateTimeBehavior=convertToNull
+
+# disable unicode handling
+useUnicode=false
+
+# Get rid of SQL exceptions thrown in Mysql jdbc driver
+holdResultsOpenOverStatementClose=true
+
+# charset
+#useUnicode=true
+#characterEncoding=Cp1252
+
+#dumpQueriesOnException=true
+
+dontTrackOpenResources=true
+
+#useCompression=true
+#tcpRcvBuf=262144
+#tcpSndBuf=262144
+
+# setAutocommit / setIsolationLevel optimizations
+useLocalSessionState=true
+useLocalTransactionState=true
+elideSetAutoCommits=true
+alwaysSendSetIsolation=false
+relaxAutoCommit=true
+
+# metadata caching
+cacheServerConfiguration=true
+cacheResultSetMetadata=true
+metadataCacheSize=100
+
+# enable MySQL query cache - server prep stmts wont use caching
+useServerPrepStmts=false
+
+# prepared statement caching on JDBC client
+cachePrepStmts=false
+cacheCallableStmts=false
+prepStmtCacheSize=4096
+prepStmtCacheSqlLimit=32000
+
+# log slow queries
+#logSlowQueries=true
+#slowQueryThresholdMillis=2000
+
+noDatetimeStringSync=true
+enableQueryTimeouts=false
+
+traceProtocol=false
+useUnbufferedInput=true
+useReadAheadInput=true
+maintainTimeStats=false
+
+# timeouts for TCP/IP
+connectTimeout=15000
+socketTimeout=120000

+ 85 - 16
grails/hello/grails-app/controllers/hello/HelloController.groovy

@@ -1,32 +1,101 @@
 package hello
 
 import grails.converters.JSON
+import grails.transaction.Transactional
+import groovy.transform.CompileStatic
+import groovy.transform.TypeCheckingMode;
+
 import java.util.concurrent.ThreadLocalRandom
 
+import org.springframework.transaction.annotation.Isolation;
+
+@CompileStatic
 class HelloController {
 
     def index() {
-      def response = [
-        message: "Hello, world"
-      ]
-      render response as JSON
+        plaintext()
+    }
+
+    // benchmark specification
+    // http://www.techempower.com/benchmarks/#section=code
+    
+    // Test type 1: JSON serialization
+    def json() {
+        def msg = [
+            message: "Hello, world"
+        ]
+        render msg as JSON
     }
 
+    // Test type 2: Single database query
+    @Transactional(readOnly=true)
     def db() {
-      int queries = params.queries ? params.int('queries') : 1
-      def worlds = new ArrayList(queries)
-      def random = ThreadLocalRandom.current();
+        def random = ThreadLocalRandom.current()
+        def world = World.read(random.nextInt(10000) + 1)
+        render world as JSON
+    }
+    
+    // Test type 3: Multiple database queries
+    @Transactional(readOnly=true)
+    def queries(int queries) {
+        def worlds = fetchRandomWorlds(queries, false)
+        render worlds as JSON
+    }
+
+    private List<World> fetchRandomWorlds(int queries, boolean updateAlso) {
+        if(queries < 1) queries=1
+        if(queries > 500) queries=500
+        def random = ThreadLocalRandom.current()
 
-      for (int i = 0; i < queries; i++) {
-        worlds.add(World.read(random.nextInt(10000) + 1));
-      }
-      render worlds as JSON
+        List<Integer> worldIds = new ArrayList<Integer>(queries)
+        for (int i = 0; i < queries; i++) {
+            worldIds.add(random.nextInt(10000) + 1)
+        }
+        List<World> worlds
+        if (updateAlso) {
+            worlds = getAllLocked(worldIds as Serializable[])
+            for (World world : worlds) {
+                world.randomNumber = random.nextInt(10000) + 1
+            }
+        } else {
+            worlds = new ArrayList<World>(queries)
+            for (Integer id : worldIds) {
+                worlds.add(World.read(id))
+            }
+        }
+        return worlds
     }
     
-    def json() {
-      def response = [
-        message: "Hello, world"
-      ]
-      render response as JSON
+    @CompileStatic(TypeCheckingMode.SKIP)
+    private List<World> getAllLocked(Serializable[] worldIds) {
+        World.withCriteria {
+            'in'('id', worldIds as Serializable[])
+            lock true
+        }
+    }
+    
+    // Test type 4: Fortunes
+    @Transactional(readOnly=true)
+    def fortunes() {
+        def fortunes = Fortune.getAll()
+        fortunes << new Fortune(message: 'Additional fortune added at request time.')
+        fortunes.sort(true){Fortune it -> it.message}
+        [fortunes: fortunes]
+    }
+    
+    // Test type 5: Database updates
+    def updates(int queries) {
+        def worlds = updateWorlds(queries)
+        render worlds as JSON
+    }
+
+    @Transactional(isolation=Isolation.READ_COMMITTED)
+    private List updateWorlds(int queries) {
+        fetchRandomWorlds(queries, true)
+    }
+    
+    // Test type 6: Plaintext
+    def plaintext() {
+        render text:'Hello, world', contentType:'text/plain'
     }
 }

+ 14 - 0
grails/hello/grails-app/domain/hello/Fortune.groovy

@@ -0,0 +1,14 @@
+package hello
+
+class Fortune {
+    Integer id
+    String message
+
+    static constraints = {
+    }
+
+    static mapping = {
+      table name: 'Fortune'
+      version false
+    }
+}

+ 2 - 0
grails/hello/grails-app/domain/hello/World.groovy

@@ -1,12 +1,14 @@
 package hello
 
 class World {
+    Integer id
     Integer randomNumber
 
     static constraints = {
     }
 
     static mapping = {
+      table name: 'World'
       version false
       columns {
         randomNumber     column:"randomNumber"

+ 12 - 5
grails/hello/grails-app/views/error.gsp

@@ -1,11 +1,18 @@
-<!doctype html>
+<!DOCTYPE html>
 <html>
 	<head>
-		<title>Grails Runtime Exception</title>
+		<title><g:if env="development">Grails Runtime Exception</g:if><g:else>Error</g:else></title>
 		<meta name="layout" content="main">
-		<link rel="stylesheet" href="${resource(dir: 'css', file: 'errors.css')}" type="text/css">
+		<g:if env="development"><link rel="stylesheet" href="${resource(dir: 'css', file: 'errors.css')}" type="text/css"></g:if>
 	</head>
 	<body>
-		<g:renderException exception="${exception}" />
+		<g:if env="development">
+			<g:renderException exception="${exception}" />
+		</g:if>
+		<g:else>
+			<ul class="errors">
+				<li>An error has occurred</li>
+			</ul>
+		</g:else>
 	</body>
-</html>
+</html>

+ 10 - 0
grails/hello/grails-app/views/hello/fortunes.gsp

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head><title>Fortunes</title></head>
+<body>
+<table>
+<tr><th>id</th><th>message</th></tr>
+<g:each var="fortune" in="${fortunes}"><tr><td>${fortune.id}</td><td>${fortune.message}</td></tr></g:each>
+</table>
+</body>
+</html>

+ 3 - 3
grails/hello/grails-app/views/index.gsp

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <html>
 	<head>
 		<meta name="layout" content="main"/>
@@ -29,7 +29,7 @@
 				margin-bottom: 0.6em;
 				padding: 0;
 			}
-            
+
 			#status li {
 				line-height: 1.3;
 			}
@@ -87,7 +87,7 @@
 			<ul>
 				<li>App version: <g:meta name="app.version"/></li>
 				<li>Grails version: <g:meta name="app.grails.version"/></li>
-				<li>Groovy version: ${org.codehaus.groovy.runtime.InvokerHelper.getVersion()}</li>
+				<li>Groovy version: ${GroovySystem.getVersion()}</li>
 				<li>JVM version: ${System.getProperty('java.version')}</li>
 				<li>Reloading active: ${grails.util.Environment.reloadingAgentEnabled}</li>
 				<li>Controllers: ${grailsApplication.controllerClasses.size()}</li>

+ 85 - 0
grails/hello/src/groovy/org/codehaus/groovy/grails/plugins/codecs/JSONEncoder.java

@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.codehaus.groovy.grails.plugins.codecs;
+
+import org.apache.commons.lang.StringUtils;
+import org.codehaus.groovy.grails.support.encoding.CodecIdentifier;
+import org.codehaus.groovy.grails.support.encoding.DefaultCodecIdentifier;
+
+/**
+ * Escapes characters in JSON output
+ *
+ * @author Lari Hotari
+ * @since 2.3.4
+ */
+public class JSONEncoder extends AbstractCharReplacementEncoder {
+    public static final CodecIdentifier JSON_CODEC_IDENTIFIER = new DefaultCodecIdentifier(
+            "JSON", "Json") {
+        public boolean isEquivalent(CodecIdentifier other) {
+            return super.isEquivalent(other) || JavaScriptEncoder.JAVASCRIPT_CODEC_IDENTIFIER.getCodecName().equals(other.getCodecName());
+        };
+    };
+
+    public JSONEncoder() {
+        super(JSON_CODEC_IDENTIFIER);
+    }
+
+    /* (non-Javadoc)
+     * @see org.codehaus.groovy.grails.plugins.codecs.AbstractCharReplacementEncoder#escapeCharacter(char, char)
+     */
+    @Override
+    protected String escapeCharacter(char ch, char previousChar) {
+        switch (ch) {
+            case '"':
+                return "\\\"";
+            case '\\':
+                return "\\\\";
+            case '\t':
+                return "\\t";
+            case '\n':
+                return "\\n";
+            case '\r':
+                return "\\r";
+            case '\f':
+                return "\\f";
+            case '\b':
+                return "\\b";
+            case '\u000B': // vertical tab: http://bclary.com/2004/11/07/#a-7.8.4
+                return "\\v";
+            case '\u2028':
+                return "\\u2028"; // Line separator
+            case '\u2029':
+                return "\\u2029"; // Paragraph separator
+            case '/':
+                // preserve special handling that exists in JSONObject.quote to improve security if JSON is embedded in HTML document
+                // prevents outputting "</" gets outputted with unicode escaping for the slash
+                if (previousChar == '<') {
+                    return "\\u002f"; 
+                }
+                break;
+        }
+        if(ch < ' ') {
+            // escape all other control characters
+            return "\\u" + StringUtils.leftPad(Integer.toHexString(ch), 4, '0');
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isApplyToSafelyEncoded() {
+        return true;
+    }
+}

+ 8 - 0
grails/hello/web-app/WEB-INF/sitemesh-excludes.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sitemesh-excludes>
+  <excludes>
+      <pattern>/hello/*</pattern>
+      <pattern>/hello</pattern>
+  </excludes>
+</sitemesh-excludes>
+

+ 2 - 1
grails/hello/web-app/WEB-INF/sitemesh.xml

@@ -1,4 +1,5 @@
 <sitemesh>
+    <excludes file="/WEB-INF/sitemesh-excludes.xml" />
     <page-parsers>
         <parser content-type="text/html"
             class="org.codehaus.groovy.grails.web.sitemesh.GrailsHTMLPageParser" />
@@ -11,4 +12,4 @@
     <decorator-mappers>
         <mapper class="org.codehaus.groovy.grails.web.sitemesh.GrailsLayoutDecoratorMapper" />
     </decorator-mappers>
-</sitemesh>
+</sitemesh>

+ 10 - 10
grails/setup.py

@@ -3,22 +3,22 @@ import subprocess
 import sys
 import setup_util
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("grails/hello/grails-app/conf/DataSource.groovy", "jdbc:mysql:\/\/.*:3306", "jdbc:mysql://" + args.database_host + ":3306")
   
   try:
-    subprocess.check_call("grails install-dependency mysql:mysql-connector-java:5.1.22", shell=True, cwd="grails/hello")
-    subprocess.check_call("grails war", shell=True, cwd="grails/hello")
-    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
-    subprocess.check_call("cp grails/hello/target/hello-0.1.war $RESIN_HOME/webapps/grails.war", shell=True)
-    subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True)
+    subprocess.check_call("grails -non-interactive -plain-output compile", shell=True, cwd="grails/hello", stderr=errfile, stdout=logfile)
+    subprocess.check_call("grails prod -non-interactive -plain-output war", shell=True, cwd="grails/hello", stderr=errfile, stdout=logfile)
+    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("cp grails/hello/target/hello-0.1.war $RESIN_HOME/webapps/grails.war", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
-    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
-    subprocess.check_call("rm -rf $RESIN_HOME/resin-data/*", shell=True)
+    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True, stderr=errfile, stdout=logfile)
+    subprocess.check_call("rm -rf $RESIN_HOME/resin-data/*", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
-    return 1
+    return 1

+ 3 - 3
grizzly-bm/benchmark_config

@@ -9,16 +9,16 @@
       "approach": "Realistic",
       "classification": "Micro",
       "database": "None",
-      "framework": "grizzly-bm",
+      "framework": "grizzly",
       "language": "Java",
       "orm": "Raw",
       "platform": "Servlet",
       "webserver": "Grizzly",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "grizzly-bm",
+      "display_name": "grizzly",
       "notes": "",
-      "versus": "servlet"
+      "versus": ""
     }
   }]
 }

+ 4 - 4
grizzly-bm/setup.py

@@ -3,14 +3,14 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   try:
-    subprocess.check_call("mvn clean compile assembly:single", shell=True, cwd="grizzly-bm")
-    subprocess.Popen("java -jar grizzly-bm-0.1-jar-with-dependencies.jar".rsplit(" "), cwd="grizzly-bm/target")
+    subprocess.check_call("mvn clean compile assembly:single", shell=True, cwd="grizzly-bm", stderr=errfile, stdout=logfile)
+    subprocess.Popen("java -jar grizzly-bm-0.1-jar-with-dependencies.jar".rsplit(" "), cwd="grizzly-bm/target", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():

+ 14 - 16
grizzly-bm/src/main/java/org/glassfish/grizzly/bm/JsonHttpHandler.java

@@ -2,6 +2,7 @@ package org.glassfish.grizzly.bm;
 
 import com.fasterxml.jackson.core.JsonFactory;
 import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.*;
 import java.io.IOException;
 import java.util.concurrent.ExecutorService;
 import org.glassfish.grizzly.http.server.HttpHandler;
@@ -14,7 +15,10 @@ import org.glassfish.grizzly.http.util.Header;
  */
 public class JsonHttpHandler extends HttpHandler {
 
-    private final JsonFactory factory = new JsonFactory();
+    // Response message class.
+    public static class HelloMessage {
+      public final String message = "Hello, World!";
+    }
 
     @Override
     public void service(final Request request, final Response response)
@@ -22,22 +26,16 @@ public class JsonHttpHandler extends HttpHandler {
         response.setContentType("application/json");
         response.setHeader(Header.Server, Server.SERVER_VERSION);
 
-        JsonGenerator generator = null;
+        ObjectMapper MAPPER = new ObjectMapper();
 
-        try {
-            generator = factory.createGenerator(response.getOutputStream());
-            generator.writeStartObject();
-            generator.writeStringField("message", "Hello, world");
-            generator.writeEndObject();
-        } catch (IOException e) {
-            throw new IllegalStateException(e);
-        } finally {
-            if (generator != null) {
-                try {
-                    generator.close();
-                } catch (IOException e) {
-                }
-            }
+        // Write JSON encoded message to the response.
+        try
+        {
+          MAPPER.writeValue(response.getOutputStream(), new HelloMessage());
+        }
+        catch (IOException ioe) 
+        {
+          // do nothing
         }
     }
 

+ 1 - 1
grizzly-jersey/benchmark_config

@@ -20,7 +20,7 @@
       "database_os": "Linux",
       "display_name": "grizzly-jersey",
       "notes": "",
-      "versus": "servlet"
+      "versus": "grizzly"
     }
   }]
 }

+ 4 - 4
grizzly-jersey/setup.py

@@ -3,15 +3,15 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   try:
-    subprocess.check_call("mvn clean package", shell=True, cwd="grizzly-jersey")
-    subprocess.Popen(("java -jar target/grizzly-jersey-example.jar -dbhost " + args.database_host).rsplit(" "), cwd="grizzly-jersey")
+    subprocess.check_call("mvn clean package", shell=True, cwd="grizzly-jersey", stderr=errfile, stdout=logfile)
+    subprocess.Popen(("java -jar target/grizzly-jersey-example.jar -dbhost " + args.database_host).rsplit(" "), cwd="grizzly-jersey", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   for line in out.splitlines():

+ 12 - 12
hapi/setup.py

@@ -3,35 +3,35 @@ import sys
 import setup_util
 import os
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("hapi/app.js", "localhost", args.database_host)
 
   try:
-    npm()
+    npm(logfile, errfile)
     if os.name == 'nt':
-      subprocess.Popen("set NODE_ENV=production", shell=True)
-      subprocess.Popen("node app", shell=True, cwd="hapi")
+      subprocess.Popen("set NODE_ENV=production", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.Popen("node app", shell=True, cwd="hapi", stderr=errfile, stdout=logfile)
     else:
-      subprocess.Popen("NODE_ENV=production node app", shell=True, cwd="hapi")
+      subprocess.Popen("NODE_ENV=production node app", shell=True, cwd="hapi", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def npm():
+def npm(logfile, errfile):
   if os.name == 'nt':
-    subprocess.check_call("copy package.json package.json.dist /y > NUL", shell=True, cwd="hapi")
+    subprocess.check_call("copy package.json package.json.dist /y > NUL", shell=True, cwd="hapi", stderr=errfile, stdout=logfile)
     setup_util.replace_text("hapi/package.json", ".*mapper.*", "")
 
   try:
-    subprocess.check_call("npm install", shell=True, cwd="hapi")
+    subprocess.check_call("npm install", shell=True, cwd="hapi", stderr=errfile, stdout=logfile)
   finally:
     if os.name == 'nt':
-      subprocess.check_call("del package.json", shell=True, cwd="hapi")
-      subprocess.check_call("ren package.json.dist package.json", shell=True, cwd="hapi")
+      subprocess.check_call("del package.json", shell=True, cwd="hapi", stderr=errfile, stdout=logfile)
+      subprocess.check_call("ren package.json.dist package.json", shell=True, cwd="hapi", stderr=errfile, stdout=logfile)
 
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.Popen("taskkill /f /im node.exe > NUL", shell=True)
+    subprocess.Popen("taskkill /f /im node.exe > NUL", shell=True, stderr=errfile, stdout=logfile)
     return 0
 
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)

+ 6 - 6
http-kit/setup.py

@@ -3,25 +3,25 @@ import subprocess
 import sys
 import setup_util
 
-def start(args):
+def start(args, logfile, errfile):
 
   try:
-    subprocess.check_call("lein deps", shell=True, cwd="http-kit/hello")
+    subprocess.check_call("lein deps", shell=True, cwd="http-kit/hello", stderr=errfile, stdout=logfile)
     subprocess.check_call("rm -rf target", shell=True, cwd="http-kit/hello")
     # pack all dependencies into a single jar: target/http-kit-standalone.jar
-    subprocess.check_call("lein uberjar", shell=True, cwd="http-kit/hello")
+    subprocess.check_call("lein uberjar", shell=True, cwd="http-kit/hello", stderr=errfile, stdout=logfile)
     # -server is much faster
     # 'lein run' passes '-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' which make it starts fast, but runs slow
     command = "java -server -jar target/http-kit-standalone.jar --db-host " + args.database_host
-    subprocess.Popen(command, shell=True, cwd="http-kit/hello")
+    subprocess.Popen(command, shell=True, cwd="http-kit/hello", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
 
-def stop():
+def stop(logfile, errfile):
   try:
     # listen on 8080
-    subprocess.check_call("lsof -t -sTCP:LISTEN -i:8080 | xargs kill", shell=True)
+    subprocess.check_call("lsof -t -sTCP:LISTEN -i:8080 | xargs kill", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1

+ 6 - 6
jester/setup.py

@@ -6,16 +6,16 @@ from os.path import expanduser
 
 home = expanduser("~")
 
-def start(args):
-  subprocess.check_call("nimrod c -d:release --path:../installs/jester/jester hello.nim", shell=True, cwd="jester")
-  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/jester/config/nginx.conf", shell=True)
+def start(args, logfile, errfile):
+  subprocess.check_call("nimrod c -d:release --path:../installs/jester/jester hello.nim", shell=True, cwd="jester", stderr=errfile, stdout=logfile)
+  subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/jester/config/nginx.conf", shell=True, stderr=errfile, stdout=logfile)
   
   for i in range(0, 8):
-    subprocess.Popen("./hello 900" + str(i) + " > /dev/null", shell=True, cwd="jester")
+    subprocess.Popen("./hello 900" + str(i), shell=True, cwd="jester", stderr=errfile, stdout=logfile)
   return 0
 
-def stop():
-  subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
+def stop(logfile, errfile):
+  subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True, stderr=errfile, stdout=logfile)
 
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()

+ 15 - 0
jetty-servlet/README.md

@@ -0,0 +1,15 @@
+# Jetty-9 Benchmarking Test
+
+This is the Jetty portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+* [JSON test source](src/main/java/hello/HelloWebServer.java)
+
+## Versions
+Jetty-9.1.0 (http://eclipse.org/jetty)
+
+## Test URLs
+
+### JSON Encoding Test
+
+    http://localhost:8080

+ 0 - 0
jetty-servlet/__init__.py


+ 24 - 0
jetty-servlet/benchmark_config

@@ -0,0 +1,24 @@
+{
+  "framework": "jetty-servlet",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "Servlet-3.1",
+      "language": "Java",
+      "orm": "None",
+      "platform": "Jetty",
+      "webserver": "Jetty",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "jetty-servlet",
+      "notes": "Jetty 9.1 with ServletContext",
+      "versus": ""
+    }
+  }]
+}

+ 64 - 0
jetty-servlet/pom.xml

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>com.techempower</groupId>
+    <artifactId>jetty-servlet-example</artifactId>
+    <version>0.1</version>
+
+    <dependencies>
+        <!-- Web server -->
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-servlet</artifactId>
+            <version>9.1.0.v20131115</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-util-ajax</artifactId>
+            <version>9.1.0.v20131115</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <inherited>true</inherited>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.2</version>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                    <optimize>true</optimize>
+                    <debug>false</debug>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>hello.HelloWebServer</mainClass>
+                        </manifest>
+                    </archive>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
+                        <phase>package</phase> <!-- bind to the packaging phase -->
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 19 - 0
jetty-servlet/setup.py

@@ -0,0 +1,19 @@
+import subprocess
+import sys
+import os
+
+def start(args, logfile, errfile):
+  try:
+    subprocess.check_call("mvn clean compile assembly:single", shell=True, cwd="jetty-servlet", stderr=errfile, stdout=logfile)
+    subprocess.Popen("java -jar jetty-servlet-example-0.1-jar-with-dependencies.jar".rsplit(" "), cwd="jetty-servlet/target", stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop(logfile, errfile):
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'jetty-servlet-example' in line:
+      pid = int(line.split(None, 2)[1])
+      os.kill(pid, 9)
+  return 0

+ 4 - 0
jetty-servlet/source_code

@@ -0,0 +1,4 @@
+./jetty-servlet/src/main/java/hello/
+./jetty-servlet/src/main/java/hello/HelloWebServer.java
+./jetty-servlet/src/main/java/hello/JsonServlet.java
+./jetty-servlet/src/main/java/hello/PlaintextServlet.java

+ 36 - 0
jetty-servlet/src/main/java/hello/HelloWebServer.java

@@ -0,0 +1,36 @@
+package hello;
+
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+
+
+/**
+ * An implementation of the TechEmpower benchmark tests using the Jetty web
+ * server.  
+ */
+public final class HelloWebServer 
+{
+
+    public static void main(String[] args) throws Exception
+    {
+        Server server = new Server(8080);
+        ServerConnector connector = server.getBean(ServerConnector.class);
+        HttpConfiguration config = connector.getBean(HttpConnectionFactory.class).getHttpConfiguration();
+        config.setSendDateHeader(true);
+        config.setSendServerVersion(true);
+
+        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SECURITY|ServletContextHandler.NO_SESSIONS);
+        context.setContextPath("/");
+        server.setHandler(context);
+
+        context.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class,"/");
+        context.addServlet(JsonServlet.class,"/json");
+        context.addServlet(PlaintextServlet.class,"/plaintext");
+
+        server.start();
+        server.join();
+    }
+}

+ 31 - 0
jetty-servlet/src/main/java/hello/JsonServlet.java

@@ -0,0 +1,31 @@
+package hello;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.util.ajax.JSON;
+
+
+
+public class JsonServlet extends GenericServlet
+{
+    private JSON json = new JSON();
+    
+    @Override
+    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
+    {
+        HttpServletResponse response= (HttpServletResponse)res;
+        response.setContentType("application/json");
+        Map<String,String> map = Collections.singletonMap("message","Hello, World!");
+        
+        json.append(response.getWriter(),map);
+    }
+
+}

+ 28 - 0
jetty-servlet/src/main/java/hello/PlaintextServlet.java

@@ -0,0 +1,28 @@
+package hello;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
+
+import javax.activation.MimeType;
+import javax.servlet.GenericServlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.http.MimeTypes;
+
+public class PlaintextServlet extends GenericServlet
+{
+    byte[] helloWorld = "Hello, World!".getBytes(StandardCharsets.ISO_8859_1);
+    @Override
+    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
+    {
+        HttpServletResponse response= (HttpServletResponse)res;
+        response.setContentType(MimeTypes.Type.TEXT_PLAIN.asString());
+        response.getOutputStream().write(helloWorld);
+    }
+}

+ 5 - 5
kelp/setup.py

@@ -7,20 +7,20 @@ import getpass
 
 home = expanduser("~")
 
-def start(args):
+def start(args, logfile, errfile):
   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)
+    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", stderr=errfile, stdout=logfile)
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/kelp/nginx.conf", shell=True, stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
-def stop():
+def stop(logfile, errfile):
   try:
-    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True, stderr=errfile, stdout=logfile)
     p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
     out, err = p.communicate()
     for line in out.splitlines():

+ 4 - 4
lapis/setup.py

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

+ 7 - 7
lift-stateless/setup.py

@@ -5,21 +5,21 @@ import setup_util
 import os
 import time
 
-def start(args):
+def start(args, logfile, errfile):
   setup_util.replace_text("lift-stateless/src/main/scala/Main.scala", "> \".*:3306", "> \"" + args.database_host + ":3306")
 
   if os.name == 'nt':
-    subprocess.check_call('"..\\sbt\\sbt.bat" update assembly', shell=True, cwd="lift-stateless")
-    subprocess.Popen(".\\run.bat", shell=True, cwd="lift-stateless")  
+    subprocess.check_call('"..\\sbt\\sbt.bat" update assembly', shell=True, cwd="lift-stateless", stderr=errfile, stdout=logfile)
+    subprocess.Popen(".\\run.bat", shell=True, cwd="lift-stateless", stderr=errfile, stdout=logfile)  
   else:
-    subprocess.check_call("../sbt/sbt update assembly", shell=True, cwd="lift-stateless")
-    subprocess.Popen("./run", shell=True, cwd="lift-stateless")
+    subprocess.check_call("../sbt/sbt update assembly", shell=True, cwd="lift-stateless", stderr=errfile, stdout=logfile)
+    subprocess.Popen("./run", shell=True, cwd="lift-stateless", stderr=errfile, stdout=logfile)
 
   time.sleep(5)
   return 0
-def stop():
+def stop(logfile, errfile):
   if os.name == 'nt':
-    subprocess.check_call("wmic process where \"CommandLine LIKE '%lift-stateless-assembly%'\" call terminate")
+    subprocess.check_call("wmic process where \"CommandLine LIKE '%lift-stateless-assembly%'\" call terminate", stderr=errfile, stdout=logfile)
   else:
     p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
     out, err = p.communicate()

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