Browse Source

Merge branch 'master' into unicorn

Patrick Falls 12 years ago
parent
commit
3a8712b884
100 changed files with 1992 additions and 186 deletions
  1. 4 4
      README.md
  2. 4 3
      compojure/hello/project.clj
  3. 7 7
      compojure/hello/src/hello/handler.clj
  4. 7 0
      compojure/hello/src/log4j.xml
  5. 1 1
      config/benchmark_profile
  6. 38 0
      django-optimized/README.md
  7. 0 0
      django-optimized/__init__.py
  8. 13 0
      django-optimized/benchmark_config
  9. 0 0
      django-optimized/hello/hello/__init__.py
  10. 168 0
      django-optimized/hello/hello/settings.py
  11. 19 0
      django-optimized/hello/hello/urls.py
  12. 28 0
      django-optimized/hello/hello/wsgi.py
  13. 10 0
      django-optimized/hello/manage.py
  14. 11 0
      django-optimized/hello/templates/base.html
  15. 0 0
      django-optimized/hello/world/__init__.py
  16. 9 0
      django-optimized/hello/world/models.py
  17. 25 0
      django-optimized/hello/world/views.py
  18. 23 0
      django-optimized/setup.py
  19. 2 4
      django/setup.py
  20. 17 0
      flask/README.md
  21. 0 0
      flask/__init__.py
  22. 38 0
      flask/app.py
  23. 13 0
      flask/benchmark_config
  24. 23 0
      flask/setup.py
  25. 13 12
      go/hello.go
  26. 2 2
      grails/hello/grails-app/controllers/hello/HelloController.groovy
  27. 22 6
      installer.py
  28. 1 1
      netty/README.md
  29. 1 1
      netty/pom.xml
  30. 23 11
      netty/src/main/java/hello/HelloServerHandler.java
  31. 103 93
      nodejs/hello.js
  32. 2 1
      nodejs/package.json
  33. 8 12
      php/dbraw.php
  34. 0 1
      play-java/README.md
  35. 2 2
      play-java/setup.py
  36. 7 0
      play-scala/.gitignore
  37. 27 0
      play-scala/README.md
  38. 0 0
      play-scala/__init__.py
  39. 40 0
      play-scala/app/controllers/Application.scala
  40. 24 0
      play-scala/app/models/World.java
  41. 11 0
      play-scala/benchmark_config
  42. 74 0
      play-scala/conf/application.conf
  43. 10 0
      play-scala/conf/routes
  44. 23 0
      play-scala/project/Build.scala
  45. 1 0
      play-scala/project/build.properties
  46. 8 0
      play-scala/project/plugins.sbt
  47. 28 0
      play-scala/setup.py
  48. 8 0
      rails-optimized/Gemfile-jruby
  49. 5 0
      rails-optimized/Gemfile-ruby
  50. 41 0
      rails-optimized/README.md
  51. 7 0
      rails-optimized/Rakefile
  52. 0 0
      rails-optimized/__init__.py
  53. BIN
      rails-optimized/app/assets/images/rails.png
  54. 15 0
      rails-optimized/app/assets/javascripts/application.js
  55. 13 0
      rails-optimized/app/assets/stylesheets/application.css
  56. 3 0
      rails-optimized/app/controllers/application_controller.rb
  57. 19 0
      rails-optimized/app/controllers/hello_world_controller.rb
  58. 2 0
      rails-optimized/app/helpers/application_helper.rb
  59. 0 0
      rails-optimized/app/mailers/.gitkeep
  60. 4 0
      rails-optimized/app/models/world.rb
  61. 11 0
      rails-optimized/app/views/layouts/application.html.erb
  62. 21 0
      rails-optimized/benchmark_config
  63. 4 0
      rails-optimized/config.ru
  64. 62 0
      rails-optimized/config/application.rb
  65. 6 0
      rails-optimized/config/boot.rb
  66. 31 0
      rails-optimized/config/database-jruby.yml
  67. 22 0
      rails-optimized/config/database-ruby.yml
  68. 31 0
      rails-optimized/config/database.yml
  69. 5 0
      rails-optimized/config/environment.rb
  70. 37 0
      rails-optimized/config/environments/development.rb
  71. 67 0
      rails-optimized/config/environments/production.rb
  72. 7 0
      rails-optimized/config/initializers/backtrace_silencers.rb
  73. 15 0
      rails-optimized/config/initializers/inflections.rb
  74. 5 0
      rails-optimized/config/initializers/mime_types.rb
  75. 7 0
      rails-optimized/config/initializers/secret_token.rb
  76. 8 0
      rails-optimized/config/initializers/session_store.rb
  77. 14 0
      rails-optimized/config/initializers/wrap_parameters.rb
  78. 5 0
      rails-optimized/config/locales/en.yml
  79. 62 0
      rails-optimized/config/routes.rb
  80. 151 0
      rails-optimized/config/warble.rb
  81. 2 0
      rails-optimized/doc/README_FOR_APP
  82. 0 0
      rails-optimized/lib/assets/.gitkeep
  83. 0 0
      rails-optimized/lib/tasks/.gitkeep
  84. 0 0
      rails-optimized/log/.gitkeep
  85. 26 0
      rails-optimized/public/404.html
  86. 26 0
      rails-optimized/public/422.html
  87. 25 0
      rails-optimized/public/500.html
  88. 0 0
      rails-optimized/public/favicon.ico
  89. 241 0
      rails-optimized/public/index.html
  90. 5 0
      rails-optimized/public/robots.txt
  91. 13 0
      rails-optimized/resin-web.xml
  92. 6 0
      rails-optimized/script/rails
  93. 29 0
      rails-optimized/setup_jruby.py
  94. 25 0
      rails-optimized/setup_ruby.py
  95. 0 0
      rails-optimized/vendor/assets/javascripts/.gitkeep
  96. 0 0
      rails-optimized/vendor/assets/stylesheets/.gitkeep
  97. 0 0
      rails-optimized/vendor/plugins/.gitkeep
  98. 5 5
      rails/app/controllers/hello_world_controller.rb
  99. 3 4
      sinatra/hello_world.rb
  100. 8 16
      spring/src/main/java/hello/web/HelloDbController.java

+ 4 - 4
README.md

@@ -2,7 +2,7 @@
 
 
 Guesses and anecdotes can dominate discussions about the performance of web application frameworks.  Here we attempt to provide some objective performance measures across a wide field of frameworks, covering several platforms: Go, Python, Java, Ruby, PHP, Clojure, Groovy, and JavaScript.  The tests exercise the frameworks' JSON seralization and object-relational model (ORM).  Future versions will exercise server-side template libraries and other computation.
 Guesses and anecdotes can dominate discussions about the performance of web application frameworks.  Here we attempt to provide some objective performance measures across a wide field of frameworks, covering several platforms: Go, Python, Java, Ruby, PHP, Clojure, Groovy, and JavaScript.  The tests exercise the frameworks' JSON seralization and object-relational model (ORM).  Future versions will exercise server-side template libraries and other computation.
 
 
-See results data we've collected from Amazon EC2 instances and our physical hardware at our blog.  (LINK TBD)
+See results data we've collected from Amazon EC2 instances and our physical hardware at our blog. http://www.techempower.com/blog/2013/03/28/framework-benchmarks/
 
 
 ## Running the test suite
 ## Running the test suite
 
 
@@ -48,7 +48,7 @@ Next, we're going to setup the servers with all the necessary software:
     go get github.com/hoisie/web
     go get github.com/hoisie/web
 	mongo --host client-private-ip < config/create.js
 	mongo --host client-private-ip < config/create.js
 
 
-Assuming The above finished without error, we're ready to start the test suite:
+Assuming the above finished without error, we're ready to start the test suite:
 
 
 	nohup ./run-tests.py -s server-private-ip -c client-private-ip -i path-to-pem --max-threads number-of-cores &
 	nohup ./run-tests.py -s server-private-ip -c client-private-ip -i path-to-pem --max-threads number-of-cores &
 
 
@@ -172,7 +172,7 @@ This test will:
 * Set the response Content-Type to application/json.
 * Set the response Content-Type to application/json.
 * Serialize the row to JSON and send the resulting string as the response.
 * Serialize the row to JSON and send the resulting string as the response.
 
 
-By convnetion, if the test does not use an ORM, and instead uses the raw database connectivity provided by the platform (e.g., JDBC), we append a "-raw" to the test name in the [benchmark_config](#the-benchmark_config-file) file.  For example, "php-raw".
+By convention, if the test does not use an ORM, and instead uses the raw database connectivity provided by the platform (e.g., JDBC), we append a "-raw" to the test name in the [benchmark_config](#the-benchmark_config-file) file.  For example, "php-raw".
 
 
 Pseudo-code:
 Pseudo-code:
 
 
@@ -279,4 +279,4 @@ The setup file is a python file that contains a start() and a stop() function. H
       subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
       subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
       return 0
       return 0
     except subprocess.CalledProcessError:
     except subprocess.CalledProcessError:
-      return 1
+      return 1

+ 4 - 3
compojure/hello/project.clj

@@ -1,10 +1,11 @@
 (defproject hello "compojure"
 (defproject hello "compojure"
   :description "JSON/Database tests"
   :description "JSON/Database tests"
   :url "http://example.com/FIXME"
   :url "http://example.com/FIXME"
-  :dependencies [[org.clojure/clojure "1.4.0"]
+  :dependencies [[org.clojure/clojure "1.5.1"]
                  [compojure "1.1.5"]
                  [compojure "1.1.5"]
-                 [ring/ring-json "0.1.2"]
-                 [korma "0.3.0-RC2"]
+                 [ring/ring-json "0.2.0"]
+                 [korma "0.3.0-RC5"]
+                 [log4j "1.2.15" :exclusions [javax.mail/mail javax.jms/jms com.sun.jdmk/jmxtools com.sun.jmx/jmxri]]
                  [mysql/mysql-connector-java "5.1.6"]
                  [mysql/mysql-connector-java "5.1.6"]
                  ]
                  ]
   :plugins [[lein-ring "0.8.2"]]
   :plugins [[lein-ring "0.8.2"]]

+ 7 - 7
compojure/hello/src/hello/handler.clj

@@ -9,13 +9,13 @@
 
 
 ; Database connection
 ; Database connection
 (defdb db (mysql {:db "hello_world"
 (defdb db (mysql {:db "hello_world"
-                       :user "benchmarkdbuser"
-                       :password "benchmarkdbpass"
-                       ;;OPTIONAL KEYS
-                       :host "localhost"
-                       :port "3306"
-                       :delimiters "" ;; remove delimiters
-                       :maximum-pool-size 256
+                  :user "benchmarkdbuser"
+                  :password "benchmarkdbpass"
+                  ;;OPTIONAL KEYS
+                  :host "localhost"
+                  :port "3306"
+                  :delimiters "" ;; remove delimiters
+                  :maximum-pool-size 256
                   }))
                   }))
 
 
 ; Set up entity World and the database representation
 ; Set up entity World and the database representation

+ 7 - 0
compojure/hello/src/log4j.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+  <logger name="com.mchange">
+    <level value="WARN"/>
+  </logger>
+</log4j:configuration>

+ 1 - 1
config/benchmark_profile

@@ -4,7 +4,7 @@ export GRAILS_HOME=~/FrameworkBenchmarks/installs/grails-2.1.1
 export VERTX_HOME=~/FrameworkBenchmarks/installs/vert.x-1.3.1.final
 export VERTX_HOME=~/FrameworkBenchmarks/installs/vert.x-1.3.1.final
 export GOROOT=~/FrameworkBenchmarks/installs/go
 export GOROOT=~/FrameworkBenchmarks/installs/go
 export TOMCAT_HOME=~/FrameworkBenchmarks/installs/apache-tomcat-7.0.35
 export TOMCAT_HOME=~/FrameworkBenchmarks/installs/apache-tomcat-7.0.35
-export NODE_HOME=~/FrameworkBenchmarks/installs/node-v0.10.0-linux-x64
+export NODE_HOME=~/FrameworkBenchmarks/installs/node-v0.10.2-linux-x64
 export PLAY_HOME=~/FrameworkBenchmarks/installs/play-2.1.0
 export PLAY_HOME=~/FrameworkBenchmarks/installs/play-2.1.0
 export PATH="$JAVA_HOME/bin:$GRAILS_HOME/bin:$PLAY_HOME:$VERTX_HOME/bin:$GOROOT/bin:$NODE_HOME/bin:$HOME/FrameworkBenchmarks/installs/bin:$PATH"
 export PATH="$JAVA_HOME/bin:$GRAILS_HOME/bin:$PLAY_HOME:$VERTX_HOME/bin:$GOROOT/bin:$NODE_HOME/bin:$HOME/FrameworkBenchmarks/installs/bin:$PATH"
 
 

+ 38 - 0
django-optimized/README.md

@@ -0,0 +1,38 @@
+# Django Benchmarking Test
+
+This is the Django portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](hello/world/views.py)
+
+
+### Data-Store/Database Mapping Test
+
+* [DB test controller](hello/world/views.py)
+* [DB test model](hello/world/models.py)
+
+
+## Infrastructure Software Versions
+The tests were run with:
+* [Python 2.7.3](http://www.python.org/)
+* [Django 1.4](https://www.djangoproject.com/)
+* [Gunicorn 0.17.2](http://gunicorn.org/)
+* [MySQL 5.5.29](https://dev.mysql.com/)
+
+
+## Resources
+* https://docs.djangoproject.com/en/dev/intro/tutorial01/
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost:8080/db
+
+### Variable Query Test
+
+http://localhost:8080/db?queries=2

+ 0 - 0
django-optimized/__init__.py


+ 13 - 0
django-optimized/benchmark_config

@@ -0,0 +1,13 @@
+{
+  "framework": "django-optimized",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 33
+    }
+  }]
+}

+ 0 - 0
django-optimized/hello/hello/__init__.py


+ 168 - 0
django-optimized/hello/hello/settings.py

@@ -0,0 +1,168 @@
+# Django settings for hello project.
+
+DEBUG = False
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = (
+    # ('Your Name', '[email protected]'),
+)
+
+MANAGERS = ADMINS
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
+        'NAME': 'hello_world',                      # Or path to database file if using sqlite3.
+        'USER': 'benchmarkdbuser',                      # Not used with sqlite3.
+        'PASSWORD': 'benchmarkdbpass',                  # Not used with sqlite3.
+        'HOST': 'localhost',                      # Set to empty string for localhost. Not used with sqlite3.
+        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
+    }
+}
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = 'America/Chicago'
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'en-us'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale.
+USE_L10N = True
+
+# If you set this to False, Django will not use timezone-aware datetimes.
+USE_TZ = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/media/"
+MEDIA_ROOT = ''
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash.
+# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
+MEDIA_URL = ''
+
+# Absolute path to the directory static files should be collected to.
+# Don't put anything in this directory yourself; store your static files
+# in apps' "static/" subdirectories and in STATICFILES_DIRS.
+# Example: "/home/media/media.lawrence.com/static/"
+STATIC_ROOT = ''
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = '/static/'
+
+# Additional locations of static files
+STATICFILES_DIRS = (
+    # Put strings here, like "/home/html/static" or "C:/www/django/static".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+)
+
+# List of finder classes that know how to find static files in
+# various locations.
+STATICFILES_FINDERS = (
+    'django.contrib.staticfiles.finders.FileSystemFinder',
+    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
+)
+
+# Make this unique, and don't share it with anybody.
+SECRET_KEY = '_7mb6#v4yf@qhc(r(zbyh&amp;z_iby-na*7wz&amp;-v6pohsul-d#y5f'
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = (
+    'django.template.loaders.filesystem.Loader',
+    'django.template.loaders.app_directories.Loader',
+)
+
+MIDDLEWARE_CLASSES = (
+    # In our optimized version, we can remove this middleware that we're not using
+    # 'django.middleware.common.CommonMiddleware',
+    # 'django.contrib.sessions.middleware.SessionMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    # 'django.contrib.auth.middleware.AuthenticationMiddleware',
+    # 'django.contrib.messages.middleware.MessageMiddleware',
+)
+
+ROOT_URLCONF = 'hello.urls'
+
+# Python dotted path to the WSGI application used by Django's runserver.
+WSGI_APPLICATION = 'hello.wsgi.application'
+
+TEMPLATE_DIRS = (
+    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
+    # Always use forward slashes, even on Windows.
+    # Don't forget to use absolute paths, not relative paths.
+    "/home/ubuntu/FrameworkBenchmarks/django/hello/templates",
+)
+
+INSTALLED_APPS = (
+    # Removing these for our optimized version
+    # 'django.contrib.auth',
+    # 'django.contrib.contenttypes',
+    # 'django.contrib.sessions',
+    # 'django.contrib.sites',
+    # 'django.contrib.messages',
+    # 'django.contrib.staticfiles',
+    # Uncomment the next line to enable the admin:
+    # 'django.contrib.admin',
+    # Uncomment the next line to enable admin documentation:
+    # 'django.contrib.admindocs',
+    'world',
+)
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error when DEBUG=False.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': True,
+    'formatters': {
+        'verbose': {
+            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
+        },
+        'simple': {
+            'format': '%(levelname)s %(message)s'
+        },
+    },
+    'filters': {
+        'require_debug_false': {
+            '()': 'django.utils.log.RequireDebugFalse'
+        }
+    },
+    'handlers': {
+        'mail_admins': {
+            'level': 'ERROR',
+            'filters': ['require_debug_false'],
+            'class': 'django.utils.log.AdminEmailHandler'
+        },
+        'console':{
+            'level': 'ERROR',
+            'class': 'logging.StreamHandler',
+            'formatter': 'simple'
+        },
+    },
+    'loggers': {
+        'django.request': {
+            'handlers': ['mail_admins', 'console'],
+            'level': 'ERROR',
+            'propagate': True,
+        },
+    }
+}

+ 19 - 0
django-optimized/hello/hello/urls.py

@@ -0,0 +1,19 @@
+from django.conf.urls import patterns, include, url
+
+# Uncomment the next two lines to enable the admin:
+# from django.contrib import admin
+# admin.autodiscover()
+
+urlpatterns = patterns('',
+    # Examples:
+    # url(r'^$', 'hello.views.home', name='home'),
+    # url(r'^hello/', include('hello.foo.urls')),
+
+    # Uncomment the admin/doc line below to enable admin documentation:
+    # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+
+    # Uncomment the next line to enable the admin:
+    # url(r'^admin/', include(admin.site.urls)),
+    url(r'^json$', 'world.views.json'),
+    url(r'^db$', 'world.views.db'),
+)

+ 28 - 0
django-optimized/hello/hello/wsgi.py

@@ -0,0 +1,28 @@
+"""
+WSGI config for hello project.
+
+This module contains the WSGI application used by Django's development server
+and any production WSGI deployments. It should expose a module-level variable
+named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
+this application via the ``WSGI_APPLICATION`` setting.
+
+Usually you will have the standard Django WSGI application here, but it also
+might make sense to replace the whole Django WSGI application with a custom one
+that later delegates to the Django one. For example, you could introduce WSGI
+middleware here, or combine a Django application with an application of another
+framework.
+
+"""
+import os
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hello.settings")
+
+# This application object is used by any WSGI server configured to use this
+# file. This includes Django's development server, if the WSGI_APPLICATION
+# setting points here.
+from django.core.wsgi import get_wsgi_application
+application = get_wsgi_application()
+
+# Apply WSGI middleware here.
+# from helloworld.wsgi import HelloWorldApplication
+# application = HelloWorldApplication(application)

+ 10 - 0
django-optimized/hello/manage.py

@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+import os
+import sys
+
+if __name__ == "__main__":
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "hello.settings")
+
+    from django.core.management import execute_from_command_line
+
+    execute_from_command_line(sys.argv)

+ 11 - 0
django-optimized/hello/templates/base.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+
+<body>
+  <div id="content">
+    {% block content %}{% endblock %}
+  </div>
+</body>
+</html>

+ 0 - 0
django-optimized/hello/world/__init__.py


+ 9 - 0
django-optimized/hello/world/models.py

@@ -0,0 +1,9 @@
+from django.db import models
+
+# Create your models here.
+
+class World(models.Model):
+  randomNumber = models.IntegerField()
+  class Meta:
+    db_table = 'World'
+

+ 25 - 0
django-optimized/hello/world/views.py

@@ -0,0 +1,25 @@
+# Create your views here.
+
+from django.template import Context, loader
+from django.http import HttpResponse
+from django.core import serializers
+from world.models import World
+import simplejson
+import random
+
+def json(request):
+  response = {
+    "message": "Hello, World!"
+  }
+  return HttpResponse(simplejson.dumps(response), mimetype="application/json")
+
+def db(request):
+  queries = int(request.GET.get('queries', 1))
+  worlds  = []
+
+  for i in range(queries):
+    # get a random row, we know the ids are between 1 and 10000
+    worlds.append(World.objects.get(id=random.randint(1, 10000)))
+
+  return HttpResponse(serializers.serialize("json", worlds), mimetype="application/json")
+

+ 23 - 0
django-optimized/setup.py

@@ -0,0 +1,23 @@
+
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args):
+  setup_util.replace_text("django-optimized/hello/hello/settings.py", "HOST': '.*'", "HOST': '" + args.database_host + "'")
+
+  subprocess.Popen("gunicorn hello.wsgi:application -k gevent -b 0.0.0.0:8080 -w " + str((args.max_threads * 2)) + " --log-level=critical", shell=True, cwd="django-optimized/hello")
+  return 0
+def stop():
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'gunicorn' in line:
+      try:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+      except OSError:
+        pass
+
+  return 0

+ 2 - 4
django/setup.py

@@ -1,4 +1,3 @@
-
 import subprocess
 import subprocess
 import sys
 import sys
 import setup_util
 import setup_util
@@ -6,8 +5,7 @@ import os
 
 
 def start(args):
 def start(args):
   setup_util.replace_text("django/hello/hello/settings.py", "HOST': '.*'", "HOST': '" + args.database_host + "'")
   setup_util.replace_text("django/hello/hello/settings.py", "HOST': '.*'", "HOST': '" + args.database_host + "'")
-
-  subprocess.Popen("gunicorn hello.wsgi:application -b 0.0.0.0:8080 -w " + str((args.max_threads * 2)) + " --log-level=critical", shell=True, cwd="django/hello")
+  subprocess.Popen("gunicorn hello.wsgi:application -k gevent  -b 0.0.0.0:8080 -w " + str((args.max_threads * 2)) + " --log-level=critical", shell=True, cwd="django/hello")
   return 0
   return 0
 def stop():
 def stop():
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
@@ -20,4 +18,4 @@ def stop():
       except OSError:
       except OSError:
         pass
         pass
 
 
-  return 0
+  return 0

+ 17 - 0
flask/README.md

@@ -0,0 +1,17 @@
+# Flask Benchmark Test
+
+Single file test, [app.py](app.py)
+
+
+## Test URLs
+### JSON Encoding 
+
+http://localhost:8080/json
+
+### Single Row Random Query
+
+http://localhost:8080/db
+
+### Variable Row Query Test
+
+http://localhost:8080/db?queries=2

+ 0 - 0
flask/__init__.py


+ 38 - 0
flask/app.py

@@ -0,0 +1,38 @@
+from flask import Flask, jsonify, request
+from flask.ext.sqlalchemy import SQLAlchemy
+from random import randint
+
+app = Flask(__name__)
+app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://benchmarkdbuser:benchmarkdbpass@DBHOSTNAME:3306/hello_world'
+db = SQLAlchemy(app)
+
+class World(db.Model):
+  __tablename__ = "World"
+  id = db.Column(db.Integer, primary_key=True)
+  randomNumber = db.Column(db.Integer)
+  
+  # http://stackoverflow.com/questions/7102754/jsonify-a-sqlalchemy-result-set-in-flask
+  @property
+  def serialize(self):
+     """Return object data in easily serializeable format"""
+     return {
+         'id'         : self.id,
+         'randomNumber': self.randomNumber
+     }
+
[email protected]("/json")
+def hello():
+  resp = {"message": "Hello, World!"}
+  return jsonify(resp)
+
[email protected]("/db")
+def get_random_world():
+  num_queries = request.args.get("queries", 1)
+  worlds = []
+  for i in range(int(num_queries)):
+    wid = randint(1, 10000)
+    worlds.append(World.query.get(wid).serialize)
+  return jsonify(worlds=worlds)
+  
+if __name__ == "__main__":
+    app.run()

+ 13 - 0
flask/benchmark_config

@@ -0,0 +1,13 @@
+{
+  "framework": "flask",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 31
+    }
+  }]
+}

+ 23 - 0
flask/setup.py

@@ -0,0 +1,23 @@
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args):
+  setup_util.replace_text("flask/app.py", "DBHOSTNAME", args.database_host)
+  subprocess.Popen("gunicorn app:app -b 0.0.0.0:8080 -w " + str((args.max_threads * 2)) + " --log-level=critical", shell=True, cwd="flask")
+  
+  return 0
+
+def stop():
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'gunicorn' in line:
+      try:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+      except OSError:
+        pass
+  
+  return 0

+ 13 - 12
go/hello.go

@@ -1,24 +1,25 @@
 package main
 package main
 
 
 import (
 import (
-  "net/http";
-  "encoding/json";
-  "runtime";
-  "fmt";
+	"encoding/json"
+	"net/http"
+	"runtime"
+	"strconv"
 )
 )
 
 
 type MessageStruct struct {
 type MessageStruct struct {
-    Message string
+	Message string
 }
 }
 
 
 func hello(w http.ResponseWriter, r *http.Request) {
 func hello(w http.ResponseWriter, r *http.Request) {
-  m := MessageStruct{"Hello, world"}
-  j, _ := json.Marshal(m)
-  fmt.Fprintf(w, string(j))
+	w.Header().Set("Content-Type", "application/javascript")
+	j, _ := json.Marshal(&MessageStruct{"Hello, world"})
+	w.Header().Set("Content-Length", strconv.Itoa(len(j)))
+	w.Write(j)
 }
 }
 
 
 func main() {
 func main() {
-  runtime.GOMAXPROCS(runtime.NumCPU())
-  http.HandleFunc("/json", hello)
-  http.ListenAndServe(":8080", nil)
-}
+	runtime.GOMAXPROCS(runtime.NumCPU())
+	http.HandleFunc("/json", hello)
+	http.ListenAndServe(":8080", nil)
+}

+ 2 - 2
grails/hello/grails-app/controllers/hello/HelloController.groovy

@@ -13,8 +13,8 @@ class HelloController {
     }
     }
 
 
     def db() {
     def db() {
-      def queries = params.queries ? params.int('queries') : 1
-      def worlds = []
+      int queries = params.queries ? params.int('queries') : 1
+      def worlds = new ArrayList(queries)
       def random = ThreadLocalRandom.current();
       def random = ThreadLocalRandom.current();
 
 
       for (int i = 0; i < queries; i++) {
       for (int i = 0; i < queries; i++) {

+ 22 - 6
installer.py

@@ -22,7 +22,7 @@ class Installer:
     #######################################
     #######################################
     self.__run_command("sudo apt-get update", True)
     self.__run_command("sudo apt-get update", True)
     self.__run_command("sudo apt-get upgrade", True)    
     self.__run_command("sudo apt-get upgrade", True)    
-    self.__run_command("sudo apt-get install build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev python-software-properties unzip git-core libcurl4-openssl-dev libbz2-dev libmysqlclient-dev mongodb-clients libreadline6-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgdbm-dev ncurses-dev automake libffi-dev htop", True)
+    self.__run_command("sudo apt-get install build-essential libpcre3 libpcre3-dev libpcrecpp0 libssl-dev zlib1g-dev python-software-properties unzip git-core libcurl4-openssl-dev libbz2-dev libmysqlclient-dev mongodb-clients libreadline6-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev libgdbm-dev ncurses-dev automake libffi-dev htop libtool bison", True)
 
 
     self.__run_command("cp ../config/benchmark_profile ../../.bash_profile")
     self.__run_command("cp ../config/benchmark_profile ../../.bash_profile")
 
 
@@ -48,13 +48,13 @@ class Installer:
     # nodejs
     # nodejs
     #
     #
 
 
-    self.__run_command("curl http://nodejs.org/dist/v0.10.0/node-v0.10.0-linux-x64.tar.gz | tar xvz")
+    self.__run_command("curl http://nodejs.org/dist/v0.10.2/node-v0.10.2-linux-x64.tar.gz | tar xvz")
 
 
     #
     #
     # Java
     # Java
     #
     #
     
     
-    self.__run_command("sudo apt-get install openjdk-7-jdk", True)
+    self.__run_command("sudo apt-get install openjdk-7-jdk=", True)
     self.__run_command("sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless", True)
     self.__run_command("sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless", True)
     
     
     #
     #
@@ -71,7 +71,7 @@ class Installer:
     # We need a newer version of jruby-rack
     # We need a newer version of jruby-rack
     self.__run_command("git clone git://github.com/jruby/jruby-rack.git")
     self.__run_command("git clone git://github.com/jruby/jruby-rack.git")
     subprocess.call(["bash", "-c", "cd installs/jruby-rack && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do bundle install"])
     subprocess.call(["bash", "-c", "cd installs/jruby-rack && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do bundle install"])
-    subprocess.call(["bash", "-c", "cd installs/jruby-rack && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do jruby -S rake clean gem SKIP_SPECS=true"])
+    subprocess.call(["bash", "-c", "cd installs/jruby-rack && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do jruby -S bundle exec rake clean gem SKIP_SPECS=true"])
     subprocess.call(["bash", "-c", "cd installs/jruby-rack/target && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do gem install jruby-rack-1.2.0.SNAPSHOT.gem"])
     subprocess.call(["bash", "-c", "cd installs/jruby-rack/target && source ~/.rvm/scripts/'rvm' && rvm jruby-1.7.3 do gem install jruby-rack-1.2.0.SNAPSHOT.gem"])
 
 
     #
     #
@@ -100,13 +100,22 @@ class Installer:
     self.__run_command("sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.orig")
     self.__run_command("sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.orig")
     self.__run_command("sudo sh -c \"cat ../config/ports.conf > /etc/apache2/ports.conf\"")
     self.__run_command("sudo sh -c \"cat ../config/ports.conf > /etc/apache2/ports.conf\"")
     self.__run_command("sudo /etc/init.d/apache2 stop")
     self.__run_command("sudo /etc/init.d/apache2 stop")
-
+    
+    #
+    # Nginx
+    #
+    self.__run_command("curl http://nginx.org/download/nginx-1.2.7.tar.gz | tar xvz")
+    self.__run_command("./configure", cwd="nginx-1.2.7")
+    self.__run_command("make", cwd="nginx-1.2.7")
+    self.__run_command("sudo make install", cwd="nginx-1.2.7")
+    
     #
     #
     # Gunicorn
     # Gunicorn
     #
     #
 
 
     self.__run_command("sudo easy_install -U 'gunicorn==0.17.2'")
     self.__run_command("sudo easy_install -U 'gunicorn==0.17.2'")
     self.__run_command("sudo easy_install -U 'eventlet==0.12.1'")
     self.__run_command("sudo easy_install -U 'eventlet==0.12.1'")
+    self.__run_command("sudo pip install --upgrade 'gevent==0.13.8'")
 
 
     #
     #
     # Resin
     # Resin
@@ -169,6 +178,7 @@ class Installer:
     self.__run_command("curl http://www.djangoproject.com/m/releases/1.4/Django-1.4.tar.gz | tar xvz")
     self.__run_command("curl http://www.djangoproject.com/m/releases/1.4/Django-1.4.tar.gz | tar xvz")
     self.__run_command("sudo rm -rf /usr/local/lib/python2.7/site-packages/django")
     self.__run_command("sudo rm -rf /usr/local/lib/python2.7/site-packages/django")
     self.__run_command("sudo python setup.py install", cwd="Django-1.4")
     self.__run_command("sudo python setup.py install", cwd="Django-1.4")
+    self.__run_command("sudo easy_install -U 'ujson==1.30'")
 
 
     ##############################
     ##############################
     # Grails
     # Grails
@@ -176,6 +186,12 @@ class Installer:
     self.__run_command("wget http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.1.1.zip")
     self.__run_command("wget http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.1.1.zip")
     self.__run_command("unzip -o grails-2.1.1.zip")
     self.__run_command("unzip -o grails-2.1.1.zip")
     self.__run_command("rm grails-2.1.1.zip")
     self.__run_command("rm grails-2.1.1.zip")
+    
+
+    ##############################
+    # Flask
+    ##############################
+    self.__run_command("sudo pip install flask flask-sqlalchemy")
 
 
     ##############################
     ##############################
     # Play
     # Play
@@ -304,4 +320,4 @@ class Installer:
       pass
       pass
   ############################################################
   ############################################################
   # End __init__
   # End __init__
-  ############################################################
+  ############################################################

+ 1 - 1
netty/README.md

@@ -11,7 +11,7 @@ This is the netty portion of a [benchmarking test suite](../) comparing a variet
 * [Netty 4.0.0.Beta2](http://netty.io/)
 * [Netty 4.0.0.Beta2](http://netty.io/)
 
 
 ## References
 ## References
-* shttps://github.com/netty/netty/tree/master/example/src/main/java/io/netty/example/http/snoop
+* https://github.com/netty/netty/tree/master/example/src/main/java/io/netty/example/http/snoop
 
 
 ## Test URLs
 ## Test URLs
 
 

+ 1 - 1
netty/pom.xml

@@ -12,7 +12,7 @@
     <dependency>
     <dependency>
     	<groupId>io.netty</groupId>
     	<groupId>io.netty</groupId>
     	<artifactId>netty-codec-http</artifactId>
     	<artifactId>netty-codec-http</artifactId>
-    	<version>4.0.0.Beta2</version>
+    	<version>4.0.0.CR1</version>
     </dependency>
     </dependency>
 	 <dependency>
 	 <dependency>
 		<groupId>com.fasterxml.jackson.core</groupId>
 		<groupId>com.fasterxml.jackson.core</groupId>

+ 23 - 11
netty/src/main/java/hello/HelloServerHandler.java

@@ -1,6 +1,6 @@
 package hello;
 package hello;
 
 
-import io.netty.buffer.ByteBuf;
+import io.netty.buffer.MessageBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelHandlerContext;
@@ -17,14 +17,11 @@ import io.netty.handler.codec.http.HttpObject;
 import io.netty.handler.codec.http.HttpRequest;
 import io.netty.handler.codec.http.HttpRequest;
 import io.netty.handler.codec.http.HttpResponse;
 import io.netty.handler.codec.http.HttpResponse;
 import io.netty.handler.codec.http.LastHttpContent;
 import io.netty.handler.codec.http.LastHttpContent;
-import io.netty.handler.codec.http.QueryStringDecoder;
 import io.netty.handler.codec.http.ServerCookieEncoder;
 import io.netty.handler.codec.http.ServerCookieEncoder;
 import io.netty.util.CharsetUtil;
 import io.netty.util.CharsetUtil;
 
 
-import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.HashMap;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.Set;
 
 
 import java.io.*;
 import java.io.*;
@@ -43,13 +40,22 @@ public class HelloServerHandler extends ChannelInboundMessageHandlerAdapter<Obje
     private final StringBuilder buf = new StringBuilder();
     private final StringBuilder buf = new StringBuilder();
     private static final ObjectMapper mapper = new ObjectMapper();
     private static final ObjectMapper mapper = new ObjectMapper();
 
 
+    private boolean flush;
+
+    @Override
+    public boolean beginMessageReceived(ChannelHandlerContext ctx) throws Exception {
+        flush = false;
+        return super.beginMessageReceived(ctx);
+    }
+
     @Override
     @Override
     public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
     public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
+        MessageBuf<Object> out = ctx.nextOutboundMessageBuffer();
         if (msg instanceof HttpRequest) {
         if (msg instanceof HttpRequest) {
             HttpRequest request = this.request = (HttpRequest) msg;
             HttpRequest request = this.request = (HttpRequest) msg;
 
 
             if (is100ContinueExpected(request)) {
             if (is100ContinueExpected(request)) {
-                send100Continue(ctx);
+                send100Continue(out);
             }
             }
             
             
             Map<String, String> data = new HashMap<String, String>();
             Map<String, String> data = new HashMap<String, String>();
@@ -71,7 +77,7 @@ public class HelloServerHandler extends ChannelInboundMessageHandlerAdapter<Obje
         if (msg instanceof HttpContent) {
         if (msg instanceof HttpContent) {
             if (msg instanceof LastHttpContent) {
             if (msg instanceof LastHttpContent) {
               LastHttpContent trailer = (LastHttpContent) msg;
               LastHttpContent trailer = (LastHttpContent) msg;
-              writeResponse(ctx, trailer);
+              writeResponse(ctx, out, trailer);
             }
             }
         }
         }
     }
     }
@@ -87,7 +93,7 @@ public class HelloServerHandler extends ChannelInboundMessageHandlerAdapter<Obje
         buf.append("\r\n");
         buf.append("\r\n");
     }
     }
 
 
-    private void writeResponse(ChannelHandlerContext ctx, HttpObject currentObj) {
+    private void writeResponse(ChannelHandlerContext ctx, MessageBuf<Object> out, HttpObject currentObj) {
         // Decide whether to close the connection or not.
         // Decide whether to close the connection or not.
         boolean keepAlive = isKeepAlive(request);
         boolean keepAlive = isKeepAlive(request);
         // Build the response object.
         // Build the response object.
@@ -122,22 +128,28 @@ public class HelloServerHandler extends ChannelInboundMessageHandlerAdapter<Obje
         }
         }
 
 
         // Write the response.
         // Write the response.
-        ctx.nextOutboundMessageBuffer().add(response);
+        out.add(response);
 
 
         // Close the non-keep-alive connection after the write operation is done.
         // Close the non-keep-alive connection after the write operation is done.
         if (!keepAlive) {
         if (!keepAlive) {
+            flush = false;
             ctx.flush().addListener(ChannelFutureListener.CLOSE);
             ctx.flush().addListener(ChannelFutureListener.CLOSE);
+        } else {
+            flush = true;
         }
         }
     }
     }
 
 
-    private static void send100Continue(ChannelHandlerContext ctx) {
+    private void send100Continue(MessageBuf<Object> out) {
         HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
         HttpResponse response = new DefaultHttpResponse(HTTP_1_1, CONTINUE);
-        ctx.nextOutboundMessageBuffer().add(response);
+        out.add(response);
+        flush = true;
     }
     }
 
 
     @Override
     @Override
     public void endMessageReceived(ChannelHandlerContext ctx) throws Exception {
     public void endMessageReceived(ChannelHandlerContext ctx) throws Exception {
-        ctx.flush();
+        if (flush) {
+            ctx.flush();
+        }
     }
     }
 
 
     @Override
     @Override

+ 103 - 93
nodejs/hello.js

@@ -1,6 +1,20 @@
 var cluster = require('cluster')
 var cluster = require('cluster')
-  , numCPUs = require('os').cpus().length
-  , http = require('http')
+  , numCPUs = require('os').cpus().length;
+
+if (cluster.isMaster) {
+  // Fork workers.
+  for (var i = 0; i < numCPUs; i++) {
+    cluster.fork();
+  }
+
+  cluster.on('exit', function(worker, code, signal) {
+    console.log('worker ' + worker.pid + ' died');
+  });
+
+  return;
+}
+
+var http = require('http')
   , url = require('url')
   , url = require('url')
   , async = require('async')
   , async = require('async')
   , mongoose = require('mongoose')
   , mongoose = require('mongoose')
@@ -37,107 +51,103 @@ var WorldSchema = new Schema({
 }, { collection : 'world' });
 }, { collection : 'world' });
 var MWorld = conn.model('World', WorldSchema);
 var MWorld = conn.model('World', WorldSchema);
 
 
-if (cluster.isMaster) {
-  // Fork workers.
-  for (var i = 0; i < numCPUs; i++) {
-    cluster.fork();
-  }
 
 
-  cluster.on('exit', function(worker, code, signal) {
-    console.log('worker ' + worker.pid + ' died');
+
+function getRandomNumber() {
+  return Math.floor(Math.random() * 10000) + 1;
+}
+
+function mongooseQuery(callback) {
+  MWorld.findOne({ id: getRandomNumber()}).exec(function (err, world) {
+    callback(err, world);
   });
   });
-} else {
-  http.createServer(function (req, res) {
-
-    // JSON response object
-    var hello = {message: "Hello, world"};
-
-    var path = url.parse(req.url).pathname;
-    if (path === '/json') {
-      // JSON Response Test
-      res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
-      // Write JSON object to response
-      res.end(JSON.stringify(hello));
-    } else if (path === '/mongoose') {
-      // Database Test
-      var queries = 1,
-        worlds  = [],
-        queryFunctions = [],
-        values = url.parse(req.url, true);
-
-      if (values.query.queries) {
-        queries = values.query.queries;
-      }
+}
+
+function sequelizeQuery(callback) {
+  World.find(getRandomNumber()).success(function (world) {
+    callback(null, world);
+  });
+}
 
 
-      res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
+http.createServer(function (req, res) {
+  // JSON response object
+  var hello = {message: "Hello, world"};
 
 
-      for (var i = 1; i <= queries; i++ ) {
-        queryFunctions.push(function(callback) {
-          MWorld.findOne({ id: (Math.floor(Math.random() * 10000) + 1 )}).exec(function (err, world) {
-            worlds.push(world);
-            callback(null, 'success');
-          });
-        });
-      }
+  var path = url.parse(req.url).pathname;
 
 
-      async.parallel(queryFunctions, function(err, results) {
-        res.end(JSON.stringify(worlds));
-      });
-    } else if (path === '/sequelize') {
-      var queries = 1,
-        worlds  = [],
-        queryFunctions = [],
-        values = url.parse(req.url, true);
-
-      if ( values.query.queries ) {
-        queries = values.query.queries;
-      }
+  switch (path) {
+  case '/json':
+    // JSON Response Test
+    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
+    // Write JSON object to response
+    res.end(JSON.stringify(hello));
+    break;
+
+  case '/mongoose':
+    // Database Test
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var queryFunctions = new Array(queries);
+
+    for (var i = 0; i < queries; i += 1) {
+      queryFunctions[i] = mongooseQuery;
+    }
+
+    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
+
+    async.parallel(queryFunctions, function(err, results) {
+      res.end(JSON.stringify(results));
+    });
+    break;
+
+  case '/sequelize':
+    var values = url.parse(req.url, true);
+    var queries = values.query.queries || 1;
+    var queryFunctions = new Array(queries);
 
 
-      res.writeHead(200, {'Content-Type': 'application/json'});
+    for (var i = 0; i < queries; i += 1) {
+      queryFunctions[i] = sequelizeQuery;
+    }
+
+    res.writeHead(200, {'Content-Type': 'application/json'});
+
+    async.parallel(queryFunctions, function(err, results) {
+      res.end(JSON.stringify(results));
+    });
+    break;
+
+  case '/mysql':
+    res.writeHead(200, {'Content-Type': 'application/json'});
+    
+    pool.getConnection(function(err, connection) {
+      if (err || !connection) {
+        return res.end('MYSQL CONNECTION ERROR.');
+      } 
 
 
-      for (var i = 1; i <= queries; i++ ) {
-        queryFunctions.push(function(callback) {
-          World.find(Math.floor(Math.random()*10000) + 1).success(function(world) {
-            worlds.push(world);
-            callback(null, 'success');
-          });
+      function mysqlQuery(callback) {
+        connection.query("SELECT * FROM World WHERE id = " + getRandomNumber(), function(err, rows) {
+          callback(null, rows[0]);
         });
         });
       }
       }
 
 
-      async.parallel(queryFunctions, function(err, results) {
-        res.end(JSON.stringify(worlds));
-      });
-    }  else if (path === '/mysql') {
-      var queries = 1,
-        worlds  = [],
-        queryFunctions = [],
-        values = url.parse(req.url, true);
-
-      if ( values.query.queries ) {
-        queries = values.query.queries;
+      var values = url.parse(req.url, true);
+      var queries = values.query.queries || 1;
+      var queryFunctions = new Array(queries);
+
+      for (var i = 0; i < queries; i += 1) {
+        queryFunctions[i] = mysqlQuery;
       }
       }
 
 
-      res.writeHead(200, {'Content-Type': 'application/json'});
-      
-      pool.getConnection(function(err, connection) {
-        for (var i = 1; i <= queries; i++ ) {
-          queryFunctions.push(function(callback) {
-            connection.query("SELECT * FROM World WHERE id = " + (Math.floor(Math.random()*10000) + 1), function(err, rows) {
-              worlds.push(rows[0]);
-              callback(null, 'success');
-            });
-          });
-        }
-
-        async.parallel(queryFunctions, function(err, results) {
-          res.end(JSON.stringify(worlds));
-          connection.end();
-        });
+      async.parallel(queryFunctions, function(err, results) {
+        res.end(JSON.stringify(results));
+        connection.end();
       });
       });
-    } else {
-      // File not found handler
-      res.writeHead(404, {'Content-Type': 'text/html; charset=UTF-8'});
-      res.end("NOT IMPLEMENTED");
-    }
-  }).listen(8080);
-}
+    });
+    break;
+
+  default:
+    // File not found handler
+    res.writeHead(404, {'Content-Type': 'text/html; charset=UTF-8'});
+    res.end("NOT IMPLEMENTED");
+  }
+}).listen(8080);

+ 2 - 1
nodejs/package.json

@@ -8,4 +8,5 @@
     , "async": "0.2.5"
     , "async": "0.2.5"
     , "mysql": "2.0.0-alpha7"
     , "mysql": "2.0.0-alpha7"
   }
   }
-}
+  , "main": "hello.js"
+}

+ 8 - 12
php/dbraw.php

@@ -11,29 +11,25 @@ $pdo = new PDO('mysql:host=localhost;dbname=hello_world', 'benchmarkdbuser', 'be
 
 
 // Read number of queries to run from URL parameter
 // Read number of queries to run from URL parameter
 $query_count = 1;
 $query_count = 1;
-if (!empty($_GET)) {
-  $query_count = $_GET["queries"];
+if (TRUE === isset($_GET['queries'])) {
+  $query_count = $_GET['queries'];
 }
 }
 
 
 // Create an array with the response string.
 // Create an array with the response string.
 $arr = array();
 $arr = array();
+$id = mt_rand(1, 10000);
 
 
 // Define query
 // Define query
-$statement = $pdo->prepare("SELECT * FROM World WHERE id = :id");
+$statement = $pdo->prepare('SELECT randomNumber FROM World WHERE id = :id');
+$statement->bindParam(':id', $id, PDO::PARAM_INT);
 
 
 // For each query, store the result set values in the response array
 // For each query, store the result set values in the response array
-for ($i = 0; $i < $query_count; $i++) {
-  // Choose a random row
-  // http://www.php.net/mt_rand
-  $id = mt_rand(1, 10000);
-
-  // Bind id to query
-  $statement->bindValue(':id', $id, PDO::PARAM_INT);
+while (0 < $query_count--) {
   $statement->execute();
   $statement->execute();
-  $row = $statement->fetch(PDO::FETCH_ASSOC);
   
   
   // Store result in array.
   // Store result in array.
-  $arr[] = array("id" => $id, "randomNumber" => $row['randomNumber']);
+  $arr[] = array('id' => $id, 'randomNumber' => $statement->fetchColumn());
+  $id = mt_rand(1, 10000);
 }
 }
 
 
 // Use the PHP standard JSON encoder.
 // Use the PHP standard JSON encoder.

+ 0 - 1
play-java/README.md

@@ -15,7 +15,6 @@ This is the Play portion of a [benchmarking test suite](../) comparing a variety
 The tests were run with:
 The tests were run with:
 
 
 * [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
 * [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
-* [Resin 4.0.34](http://www.caucho.com/)
 * [Play 2.1.0](http://http://www.playframework.com/)
 * [Play 2.1.0](http://http://www.playframework.com/)
 
 
 ## Test URLs
 ## Test URLs

+ 2 - 2
play-java/setup.py

@@ -17,7 +17,7 @@ def stop():
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
   out, err = p.communicate()
   out, err = p.communicate()
   for line in out.splitlines():
   for line in out.splitlines():
-    if 'play' in line and 'java' in line:
+    if './start' in line or ('play' in line and 'java' in line):   
       pid = int(line.split(None, 2)[1])
       pid = int(line.split(None, 2)[1])
       os.kill(pid, 9)
       os.kill(pid, 9)
   try:
   try:
@@ -25,4 +25,4 @@ def stop():
   except OSError:
   except OSError:
     pass
     pass
     
     
-  return 0
+  return 0

+ 7 - 0
play-scala/.gitignore

@@ -0,0 +1,7 @@
+logs
+project/project
+project/target
+target
+tmp
+.history
+dist

+ 27 - 0
play-scala/README.md

@@ -0,0 +1,27 @@
+#Play Benchmarking Test
+
+This is the Play portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](app/controllers/Application.java)
+
+### Data-Store/Database Mapping Test
+
+* [Database test controller](app/controllers/Application.scala)
+* [Database test model](app/models/World.java)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Play 2.1.0](http://http://www.playframework.com/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost/db?queries=5

+ 0 - 0
play-scala/__init__.py


+ 40 - 0
play-scala/app/controllers/Application.scala

@@ -0,0 +1,40 @@
+package controllers
+
+import play._
+import play.api.libs.concurrent._
+import play.api.mvc._
+import play.libs.Json
+import org.codehaus.jackson.node.ObjectNode
+import views.html._
+import models._
+import java.util._
+import java.util.concurrent.ThreadLocalRandom
+import scala.concurrent._
+
+object Application extends Controller {
+  private val TEST_DATABASE_ROWS = 10000
+
+  def json() = Action {
+    val result = Json.newObject()
+    result.put("message", "Hello World!")
+    Ok(result.toString)
+  }
+
+  def db(queries: Int) = Action {
+    import play.api.libs.concurrent.Execution.Implicits._
+
+    val random = ThreadLocalRandom.current()
+
+    Async {
+      Future {
+        (1 to queries) map {
+          _ =>
+            World.find.byId(random.nextInt(TEST_DATABASE_ROWS) + 1)
+        }
+      } map {
+        worlds =>
+          Ok(Json.toJson(worlds).toString())
+      }
+    }
+  }
+}

+ 24 - 0
play-scala/app/models/World.java

@@ -0,0 +1,24 @@
+package models;
+
+import java.util.*;
+import javax.persistence.*;
+
+import play.db.ebean.*;
+import play.db.ebean.Model.Finder;
+import play.data.format.*;
+import play.data.validation.*;
+
+@Entity
+public class World extends Model {
+
+  @Id
+  public Long id;
+
+  @Column(name = "randomNumber")
+  public Long randomNumber;
+
+  public static Finder<Long,World> find = new Finder<Long,World>(
+    Long.class, World.class
+  );
+
+}

+ 11 - 0
play-scala/benchmark_config

@@ -0,0 +1,11 @@
+{
+  "framework": "play-scala",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "port": 9000,
+      "sort": 32
+    }
+  }]
+}

+ 74 - 0
play-scala/conf/application.conf

@@ -0,0 +1,74 @@
+# This is the main configuration file for the application.
+# ~~~~~
+
+# Secret key
+# ~~~~~
+# The secret key is used to secure cryptographics functions.
+# If you deploy your application to several instances be sure to use the same key!
+application.secret="RItx1I:80?W@]8GAtPDuF8Ydd3mXM85p/<7og]Q;uBOdijQAauRDgu73B6`wQP59"
+
+# The application languages
+# ~~~~~
+application.langs="en"
+
+# Global object class
+# ~~~~~
+# Define the Global object class for this application.
+# Default to Global in the root package.
+# global=Global
+
+# Database configuration
+# ~~~~~ 
+# You can declare as many datasources as you want.
+# By convention, the default datasource is named `default`
+#
+# db.default.driver=org.h2.Driver
+# db.default.url="jdbc:h2:mem:play"
+# db.default.user=sa
+# db.default.password=
+#
+# You can expose this datasource via JNDI if needed (Useful for JPA)
+# db.default.jndiName=DefaultDS
+db.default.driver= com.mysql.jdbc.Driver
+db.default.url="jdbc:mysql://localhost:3306/hello_world"
+db.default.user=benchmarkdbuser
+db.default.password=benchmarkdbpass
+db.default.jndiName=DefaultDS
+
+db.default.partitionCount=2
+
+# The number of connections to create per partition. Setting this to 
+# 5 with 3 partitions means you will have 15 unique connections to the 
+# database. Note that BoneCP will not create all these connections in 
+# one go but rather start off with minConnectionsPerPartition and 
+# gradually increase connections as required.
+db.default.maxConnectionsPerPartition=5
+
+# The number of initial connections, per partition.
+db.default.minConnectionsPerPartition=5
+
+# Evolutions
+# ~~~~~
+# You can disable evolutions if needed
+# evolutionplugin=disabled
+
+# Ebean configuration
+# ~~~~~
+# You can declare as many Ebean servers as you want.
+# By convention, the default server is named `default`
+#
+ebean.default="models.*"
+
+# Logger
+# ~~~~~
+# You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
+
+# Root logger:
+logger.root=ERROR
+
+# Logger used by the framework:
+logger.play=ERROR
+
+# Logger provided to your application:
+logger.application=ERROR
+

+ 10 - 0
play-scala/conf/routes

@@ -0,0 +1,10 @@
+# Routes
+# This file defines all application routes (Higher priority routes first)
+# ~~~~
+
+# Home page
+GET     /json                           controllers.Application.json
+GET     /db                             controllers.Application.db(queries: Int ?= 1)
+
+# Map static resources from the /public folder to the /assets URL path
+GET     /assets/*file               controllers.Assets.at(path="/public", file)

+ 23 - 0
play-scala/project/Build.scala

@@ -0,0 +1,23 @@
+import sbt._
+import Keys._
+import PlayProject._
+
+object ApplicationBuild extends Build {
+
+    val appName         = "play-scala"
+    val appVersion      = "1.0-SNAPSHOT"
+
+    val appDependencies = Seq(
+      // Add your project dependencies here,
+      javaCore,
+      javaJdbc,
+      javaEbean,
+      "mysql" % "mysql-connector-java" % "5.1.22"
+
+    )
+
+    val main = play.Project(appName, appVersion, appDependencies).settings(
+      // Add your own project settings here
+    )
+
+}

+ 1 - 0
play-scala/project/build.properties

@@ -0,0 +1 @@
+sbt.version=0.12.2

+ 8 - 0
play-scala/project/plugins.sbt

@@ -0,0 +1,8 @@
+// Comment to get more information during initialization
+logLevel := Level.Warn
+
+// The Typesafe repository 
+resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
+
+// Use the Play sbt plugin for Play projects
+addSbtPlugin("play" % "sbt-plugin" % "2.1.0")

+ 28 - 0
play-scala/setup.py

@@ -0,0 +1,28 @@
+
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args):
+  setup_util.replace_text("play-scala/conf/application.conf", "jdbc:mysql:\/\/.*:3306", "jdbc:mysql://" + args.database_host + ":3306")
+
+  subprocess.check_call("play dist", shell=True, cwd="play-scala")
+  subprocess.check_call("unzip play-scala-1.0-SNAPSHOT.zip", shell=True, cwd="play-scala/dist")
+  subprocess.check_call("chmod +x start", shell=True, cwd="play-scala/dist/play-scala-1.0-SNAPSHOT")
+  subprocess.Popen("./start", shell=True, cwd="play-scala/dist/play-scala-1.0-SNAPSHOT")
+
+  return 0
+def stop():
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if './start' in line or ('play' in line and 'java' in line):
+      pid = int(line.split(None, 2)[1])
+      os.kill(pid, 9)
+  try:
+    os.remove("play-scala/RUNNING_PID")
+  except OSError:
+    pass
+
+  return 0

+ 8 - 0
rails-optimized/Gemfile-jruby

@@ -0,0 +1,8 @@
+source 'https://rubygems.org'
+
+gem 'jruby-openssl', '0.8.5'
+gem 'rails', '3.2.11'
+gem 'jruby-rack', '1.2.0.SNAPSHOT'
+gem 'warbler', '1.3.6'
+gem 'jruby-jars', '1.7.3'
+gem 'activerecord-jdbcmysql-adapter', '1.2.6'

+ 5 - 0
rails-optimized/Gemfile-ruby

@@ -0,0 +1,5 @@
+source 'https://rubygems.org'
+
+gem 'rails', '3.2.11'
+gem 'mysql2', '0.3.11'
+gem 'passenger', '3.9.5.rc3'

+ 41 - 0
rails-optimized/README.md

@@ -0,0 +1,41 @@
+# Ruby on Rails Benchmarking Test
+
+This is the Ruby on Rails portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+* [JSON test source](app/controllers/hello_world_controller.rb)
+
+### Data-Store/Database Mapping Test
+
+* [Database test source](app/controllers/hello_world_controller.rb)
+
+
+## Infrastructure Software Versions
+The tests were run with:
+* [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
+* [JRuby 1.7.3](http://jruby.org/)
+* [Rails 3.2.11](http://rubyonrails.org/)
+* [Passenger 3.9.5-rc3](https://www.phusionpassenger.com/)
+* [Resin 4.0.34](http://www.caucho.com/)
+* [MySQL 5.5.29](https://dev.mysql.com/)
+
+## References
+* https://github.com/FooBarWidget/passenger/pull/71
+* https://github.com/jruby/jruby-rack/issues/146
+
+## Test URLs
+### JSON Encoding Test
+
+Ruby:
+localhost:8080/hello_world/json
+
+JRuby:
+localhost:8080/rails/hello_world/json
+
+### Data-Store/Database Mapping Test
+
+Ruby:
+localhost:8080/hello_world/db?queries=5
+
+JRuby:
+localhost:8080/rails/hello_world/db?queries=5

+ 7 - 0
rails-optimized/Rakefile

@@ -0,0 +1,7 @@
+#!/usr/bin/env rake
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+Hello::Application.load_tasks

+ 0 - 0
rails-optimized/__init__.py


BIN
rails-optimized/app/assets/images/rails.png


+ 15 - 0
rails-optimized/app/assets/javascripts/application.js

@@ -0,0 +1,15 @@
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
+// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
+// the compiled file.
+//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
+//= require jquery
+//= require jquery_ujs
+//= require_tree .

+ 13 - 0
rails-optimized/app/assets/stylesheets/application.css

@@ -0,0 +1,13 @@
+/*
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
+ *= require_self
+ *= require_tree .
+*/

+ 3 - 0
rails-optimized/app/controllers/application_controller.rb

@@ -0,0 +1,3 @@
+class ApplicationController < ActionController::Base
+  protect_from_forgery
+end

+ 19 - 0
rails-optimized/app/controllers/hello_world_controller.rb

@@ -0,0 +1,19 @@
+class HelloWorldController < ActionController::Metal
+  include ActionController::Rendering
+  include ActionController::Renderers::All
+
+  def json
+    render :json => {:message => "Hello World!"}
+  end
+
+  def db
+    queries = (params[:queries] || 1).to_i
+
+    results = (1..queries).map do
+      # get a random row from the database, which we know has 10000
+      # rows with ids 1 - 10000
+      World.find(Random.rand(10000) + 1)
+    end
+    render :json => results
+  end
+end

+ 2 - 0
rails-optimized/app/helpers/application_helper.rb

@@ -0,0 +1,2 @@
+module ApplicationHelper
+end

+ 0 - 0
rails-optimized/app/mailers/.gitkeep


+ 4 - 0
rails-optimized/app/models/world.rb

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

+ 11 - 0
rails-optimized/app/views/layouts/application.html.erb

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

+ 21 - 0
rails-optimized/benchmark_config

@@ -0,0 +1,21 @@
+{
+  "framework": "rails-optimized",
+  "tests": [{
+    "ruby": {
+      "setup_file": "setup_ruby",
+      "json_url": "/hello_world/json",
+      "db_url": "/hello_world/db",
+      "query_url": "/hello_world/db?queries=",
+      "port": 8080,
+      "sort": 34
+    },
+    "jruby": {
+      "setup_file": "setup_jruby",
+      "json_url": "/rails/hello_world/json",
+      "db_url": "/rails/hello_world/db",
+      "query_url": "/rails/hello_world/db?queries=",
+      "port": 8080,
+      "sort": 35
+    }
+  }]
+}

+ 4 - 0
rails-optimized/config.ru

@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment',  __FILE__)
+run Hello::Application

+ 62 - 0
rails-optimized/config/application.rb

@@ -0,0 +1,62 @@
+require File.expand_path('../boot', __FILE__)
+
+require 'rails/all'
+
+if defined?(Bundler)
+  # If you precompile assets before deploying to production, use this line
+  Bundler.require(*Rails.groups(:assets => %w(development test)))
+  # If you want your assets lazily compiled in production, use this line
+  # Bundler.require(:default, :assets, Rails.env)
+end
+
+module Hello
+  class Application < Rails::Application
+    # Settings in config/environments/* take precedence over those specified here.
+    # Application configuration should go into files in config/initializers
+    # -- all .rb files in that directory are automatically loaded.
+
+    # Custom directories with classes and modules you want to be autoloadable.
+    # config.autoload_paths += %W(#{config.root}/extras)
+
+    # Only load the plugins named here, in the order given (default is alphabetical).
+    # :all can be used as a placeholder for all plugins not explicitly named.
+    # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+
+    # Activate observers that should always be running.
+    # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
+
+    # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+    # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+    # config.time_zone = 'Central Time (US & Canada)'
+
+    # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+    # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+    # config.i18n.default_locale = :de
+
+    # Configure the default encoding used in templates for Ruby 1.9.
+    config.encoding = "utf-8"
+
+    # Configure sensitive parameters which will be filtered from the log file.
+    config.filter_parameters += [:password]
+    
+    # Enable escaping HTML in JSON.
+    config.active_support.escape_html_entities_in_json = true
+    
+    # Use SQL instead of Active Record's schema dumper when creating the database.
+    # This is necessary if your schema can't be completely dumped by the schema dumper,
+    # like if you have constraints or database-specific column types
+    # config.active_record.schema_format = :sql
+
+    # Enforce whitelist mode for mass assignment.
+    # This will create an empty whitelist of attributes available for mass-assignment for all models
+    # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
+    # parameters by using an attr_accessible or attr_protected declaration.
+    config.active_record.whitelist_attributes = true
+
+    # Enable the asset pipeline
+    config.assets.enabled = true
+
+    # Version of your assets, change this if you want to expire all your assets
+    config.assets.version = '1.0'
+  end
+end

+ 6 - 0
rails-optimized/config/boot.rb

@@ -0,0 +1,6 @@
+require 'rubygems'
+
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])

+ 31 - 0
rails-optimized/config/database-jruby.yml

@@ -0,0 +1,31 @@
+# SQLite version 3.x
+#   gem install sqlite3
+#
+#   Ensure the SQLite 3 gem is defined in your Gemfile
+#   gem 'sqlite3'
+development:
+  adapter: jdbcmysql 
+  database: hello_world
+  username: benchmarkdbuser
+  password: benchmarkdbpass
+  host: localhost
+  pool: 5
+  timeout: 5000
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+
+#production:
+#  adapter: jdbc
+#  jndi: java:comp/env/jdbc/hello_world
+#  pool: 256
+
+production:
+  adapter: jdbcmysql 
+  database: hello_world
+  username: benchmarkdbuser
+  password: benchmarkdbpass
+  host: localhost
+  pool: 256
+  timeout: 5000

+ 22 - 0
rails-optimized/config/database-ruby.yml

@@ -0,0 +1,22 @@
+# SQLite version 3.x
+#   gem install sqlite3
+#
+#   Ensure the SQLite 3 gem is defined in your Gemfile
+#   gem 'sqlite3'
+development:
+  adapter: mysql2
+  database: hello_world
+  username: benchmarkdbuser
+  password: benchmarkdbpass
+  host: localhost
+  pool: 5
+  timeout: 5000
+
+production:
+  adapter: mysql2
+  database: hello_world
+  username: benchmarkdbuser
+  password: benchmarkdbpass
+  host: loclahost
+  pool: 200
+  timeout: 5000

+ 31 - 0
rails-optimized/config/database.yml

@@ -0,0 +1,31 @@
+# SQLite version 3.x
+#   gem install sqlite3
+#
+#   Ensure the SQLite 3 gem is defined in your Gemfile
+#   gem 'sqlite3'
+development:
+  adapter: jdbcmysql 
+  database: hello_world
+  username: benchmarkdbuser
+  password: benchmarkdbpass
+  host: 172.16.98.98
+  pool: 5
+  timeout: 5000
+
+# Warning: The database defined as "test" will be erased and
+# re-generated from your development database when you run "rake".
+# Do not set this db to the same as development or production.
+
+#production:
+#  adapter: jdbc
+#  jndi: java:comp/env/jdbc/hello_world
+#  pool: 256
+
+production:
+  adapter: jdbcmysql 
+  database: hello_world
+  username: benchmarkdbuser
+  password: benchmarkdbpass
+  host: 172.16.98.98
+  pool: 256
+  timeout: 5000

+ 5 - 0
rails-optimized/config/environment.rb

@@ -0,0 +1,5 @@
+# Load the rails application
+require File.expand_path('../application', __FILE__)
+
+# Initialize the rails application
+Hello::Application.initialize!

+ 37 - 0
rails-optimized/config/environments/development.rb

@@ -0,0 +1,37 @@
+Hello::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # In the development environment your application's code is reloaded on
+  # every request. This slows down response time but is perfect for development
+  # since you don't have to restart the web server when you make code changes.
+  config.cache_classes = false
+
+  # Log error messages when you accidentally call methods on nil.
+  config.whiny_nils = true
+
+  # Show full error reports and disable caching
+  config.consider_all_requests_local       = true
+  config.action_controller.perform_caching = false
+
+  # Don't care if the mailer can't send
+  config.action_mailer.raise_delivery_errors = false
+
+  # Print deprecation notices to the Rails logger
+  config.active_support.deprecation = :log
+
+  # Only use best-standards-support built into browsers
+  config.action_dispatch.best_standards_support = :builtin
+
+  # Raise exception on mass assignment protection for Active Record models
+  config.active_record.mass_assignment_sanitizer = :strict
+
+  # Log the query plan for queries taking more than this (works
+  # with SQLite, MySQL, and PostgreSQL)
+  config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+  # Do not compress assets
+  config.assets.compress = false
+
+  # Expands the lines which load the assets
+  config.assets.debug = true
+end

+ 67 - 0
rails-optimized/config/environments/production.rb

@@ -0,0 +1,67 @@
+Hello::Application.configure do
+  # Settings specified here will take precedence over those in config/application.rb
+
+  # Code is not reloaded between requests
+  config.cache_classes = true
+
+  # Full error reports are disabled and caching is turned on
+  config.consider_all_requests_local       = false
+  config.action_controller.perform_caching = false
+
+  # Disable Rails's static asset server (Apache or nginx will already do this)
+  config.serve_static_assets = false
+
+  # Compress JavaScripts and CSS
+  config.assets.compress = true
+
+  # Don't fallback to assets pipeline if a precompiled asset is missed
+  config.assets.compile = false
+
+  # Generate digests for assets URLs
+  config.assets.digest = true
+
+  # Defaults to Rails.root.join("public/assets")
+  # config.assets.manifest = YOUR_PATH
+
+  # Specifies the header that your server uses for sending files
+  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+
+  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+  # config.force_ssl = true
+
+  # See everything in the log (default is :info)
+  config.log_level = :error
+
+  # Prepend all log lines with the following tags
+  # config.log_tags = [ :subdomain, :uuid ]
+
+  # Use a different logger for distributed setups
+  # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+  # Use a different cache store in production
+  # config.cache_store = :mem_cache_store
+
+  # Enable serving of images, stylesheets, and JavaScripts from an asset server
+  # config.action_controller.asset_host = "http://assets.example.com"
+
+  # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
+  # config.assets.precompile += %w( search.js )
+
+  # Disable delivery errors, bad email addresses will be ignored
+  # config.action_mailer.raise_delivery_errors = false
+
+  # Enable threaded mode
+  config.threadsafe!
+
+  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+  # the I18n.default_locale when a translation can not be found)
+  config.i18n.fallbacks = true
+
+  # Send deprecation notices to registered listeners
+  config.active_support.deprecation = :notify
+
+  # Log the query plan for queries taking more than this (works
+  # with SQLite, MySQL, and PostgreSQL)
+  # config.active_record.auto_explain_threshold_in_seconds = 0.5
+end

+ 7 - 0
rails-optimized/config/initializers/backtrace_silencers.rb

@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!

+ 15 - 0
rails-optimized/config/initializers/inflections.rb

@@ -0,0 +1,15 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format
+# (all these examples are active by default):
+# ActiveSupport::Inflector.inflections do |inflect|
+#   inflect.plural /^(ox)$/i, '\1en'
+#   inflect.singular /^(ox)en/i, '\1'
+#   inflect.irregular 'person', 'people'
+#   inflect.uncountable %w( fish sheep )
+# end
+#
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections do |inflect|
+#   inflect.acronym 'RESTful'
+# end

+ 5 - 0
rails-optimized/config/initializers/mime_types.rb

@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
+# Mime::Type.register_alias "text/html", :iphone

+ 7 - 0
rails-optimized/config/initializers/secret_token.rb

@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+Hello::Application.config.secret_token = '926e786d885e710c50bf02bc2e9d6d8dae9fbe566a517c030acf793f4d4e6cb6c9dc9cce0056ab031a2e045dc3c9e98071b2b20825df4c5e09f6554b1785c668'

+ 8 - 0
rails-optimized/config/initializers/session_store.rb

@@ -0,0 +1,8 @@
+# Be sure to restart your server when you modify this file.
+
+Hello::Application.config.session_store :cookie_store, key: '_rails-mri_session'
+
+# Use the database for sessions instead of the cookie-based default,
+# which shouldn't be used to store highly confidential information
+# (create the session table with "rails generate session_migration")
+# Hello::Application.config.session_store :active_record_store

+ 14 - 0
rails-optimized/config/initializers/wrap_parameters.rb

@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+#
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+  wrap_parameters format: [:json]
+end
+
+# Disable root element in JSON by default.
+ActiveSupport.on_load(:active_record) do
+  self.include_root_in_json = false
+end

+ 5 - 0
rails-optimized/config/locales/en.yml

@@ -0,0 +1,5 @@
+# Sample localization file for English. Add more files in this directory for other locales.
+# See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
+
+en:
+  hello: "Hello world"

+ 62 - 0
rails-optimized/config/routes.rb

@@ -0,0 +1,62 @@
+Hello::Application.routes.draw do
+  get "hello_world/json"
+  get "hello_world/db"
+
+
+  # The priority is based upon order of creation:
+  # first created -> highest priority.
+
+  # Sample of regular route:
+  #   match 'products/:id' => 'catalog#view'
+  # Keep in mind you can assign values other than :controller and :action
+
+  # Sample of named route:
+  #   match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
+  # This route can be invoked with purchase_url(:id => product.id)
+
+  # Sample resource route (maps HTTP verbs to controller actions automatically):
+  #   resources :products
+
+  # Sample resource route with options:
+  #   resources :products do
+  #     member do
+  #       get 'short'
+  #       post 'toggle'
+  #     end
+  #
+  #     collection do
+  #       get 'sold'
+  #     end
+  #   end
+
+  # Sample resource route with sub-resources:
+  #   resources :products do
+  #     resources :comments, :sales
+  #     resource :seller
+  #   end
+
+  # Sample resource route with more complex sub-resources
+  #   resources :products do
+  #     resources :comments
+  #     resources :sales do
+  #       get 'recent', :on => :collection
+  #     end
+  #   end
+
+  # Sample resource route within a namespace:
+  #   namespace :admin do
+  #     # Directs /admin/products/* to Admin::ProductsController
+  #     # (app/controllers/admin/products_controller.rb)
+  #     resources :products
+  #   end
+
+  # You can have the root of your site routed with "root"
+  # just remember to delete public/index.html.
+  # root :to => 'welcome#index'
+
+  # See how all your routes lay out with "rake routes"
+
+  # This is a legacy wild controller route that's not recommended for RESTful applications.
+  # Note: This route will make all actions in every controller accessible via GET requests.
+  # match ':controller(/:action(/:id))(.:format)'
+end

+ 151 - 0
rails-optimized/config/warble.rb

@@ -0,0 +1,151 @@
+# Disable Rake-environment-task framework detection by uncommenting/setting to false
+# Warbler.framework_detection = false
+
+# Warbler web application assembly configuration file
+Warbler::Config.new do |config|
+  # Features: additional options controlling how the jar is built.
+  # Currently the following features are supported:
+  # - gemjar: package the gem repository in a jar file in WEB-INF/lib
+  # - executable: embed a web server and make the war executable
+  # - compiled: compile .rb files to .class files
+  # config.features = %w(gemjar)
+
+  # Application directories to be included in the webapp.
+  config.dirs = %w(app config lib log vendor tmp views)
+
+  # Additional files/directories to include, above those in config.dirs
+  # config.includes = FileList["hello_world.rb"]
+
+  # Additional files/directories to exclude
+  # config.excludes = FileList["lib/tasks/*"]
+
+  # Additional Java .jar files to include.  Note that if .jar files are placed
+  # in lib (and not otherwise excluded) then they need not be mentioned here.
+  # JRuby and JRuby-Rack are pre-loaded in this list.  Be sure to include your
+  # own versions if you directly set the value
+  # config.java_libs += FileList["lib/java/*.jar"]
+
+  # Loose Java classes and miscellaneous files to be included.
+  # config.java_classes = FileList["target/classes/**.*"]
+
+  # One or more pathmaps defining how the java classes should be copied into
+  # the archive. The example pathmap below accompanies the java_classes
+  # configuration above. See http://rake.rubyforge.org/classes/String.html#M000017
+  # for details of how to specify a pathmap.
+  # config.pathmaps.java_classes << "%{target/classes/,}p"
+
+  # Bundler support is built-in. If Warbler finds a Gemfile in the
+  # project directory, it will be used to collect the gems to bundle
+  # in your application. If you wish to explicitly disable this
+  # functionality, uncomment here.
+  # config.bundler = false
+
+  # An array of Bundler groups to avoid including in the war file.
+  # Defaults to ["development", "test"].
+  # config.bundle_without = []
+
+  # Other gems to be included. If you don't use Bundler or a gemspec
+  # file, you need to tell Warbler which gems your application needs
+  # so that they can be packaged in the archive.
+  # For Rails applications, the Rails gems are included by default
+  # unless the vendor/rails directory is present.
+  # config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"]
+  # config.gems << "tzinfo"
+
+  # Uncomment this if you don't want to package rails gem.
+  # config.gems -= ["rails"]
+
+  # The most recent versions of gems are used.
+  # You can specify versions of gems by using a hash assignment:
+  # config.gems["rails"] = "2.3.10"
+
+  # You can also use regexps or Gem::Dependency objects for flexibility or
+  # finer-grained control.
+  # config.gems << /^merb-/
+  # config.gems << Gem::Dependency.new("merb-core", "= 0.9.3")
+
+  # Include gem dependencies not mentioned specifically. Default is
+  # true, uncomment to turn off.
+  # config.gem_dependencies = false
+
+  # Array of regular expressions matching relative paths in gems to be
+  # excluded from the war. Defaults to empty, but you can set it like
+  # below, which excludes test files.
+  # config.gem_excludes = [/^(test|spec)\//]
+
+  # Pathmaps for controlling how application files are copied into the archive
+  # config.pathmaps.application = ["WEB-INF/%p"]
+
+  # Name of the archive (without the extension). Defaults to the basename
+  # of the project directory.
+  # config.jar_name = "mywar"
+
+  # Name of the MANIFEST.MF template for the war file. Defaults to a simple
+  # MANIFEST.MF that contains the version of Warbler used to create the war file.
+  # config.manifest_file = "config/MANIFEST.MF"
+
+  # When using the 'compiled' feature and specified, only these Ruby
+  # files will be compiled. Default is to compile all \.rb files in
+  # the application.
+  # config.compiled_ruby_files = FileList['app/**/*.rb']
+
+  # === War files only below here ===
+
+  # Path to the pre-bundled gem directory inside the war file. Default
+  # is 'WEB-INF/gems'. Specify path if gems are already bundled
+  # before running Warbler. This also sets 'gem.path' inside web.xml.
+  # config.gem_path = "WEB-INF/vendor/bundler_gems"
+
+  # Files for WEB-INF directory (next to web.xml). This contains
+  # web.xml by default. If there is an .erb-File it will be processed
+  # with webxml-config. You may want to exclude this file via
+  # config.excludes.
+  config.webinf_files += FileList["resin-web.xml"]
+
+  # Files to be included in the root of the webapp.  Note that files in public
+  # will have the leading 'public/' part of the path stripped during staging.
+  # config.public_html = FileList["public/**/*", "doc/**/*"]
+
+  # Pathmaps for controlling how public HTML files are copied into the .war
+  # config.pathmaps.public_html = ["%{public/,}p"]
+
+  # Embedded webserver to use with the 'executable' feature. Currently supported
+  # webservers are:
+  # * <tt>winstone</tt> (default) - Winstone 0.9.10 from sourceforge
+  # * <tt>jenkins-ci.winstone</tt> - Improved Winstone from Jenkins CI
+  # * <tt>jetty</tt> - Embedded Jetty from Eclipse
+  # config.webserver = 'jetty'
+
+  # Value of RAILS_ENV for the webapp -- default as shown below
+  # config.webxml.rails.env = ENV['RAILS_ENV'] || 'production'
+
+  # Application booter to use, one of :rack, :rails, or :merb (autodetected by default)
+  # config.webxml.booter = :rails
+
+  # Set JRuby to run in 1.9 mode.
+  # config.webxml.jruby.compat.version = "1.9"
+
+  # When using the :rack booter, "Rackup" script to use.
+  # - For 'rackup.path', the value points to the location of the rackup
+  # script in the web archive file. You need to make sure this file
+  # gets included in the war, possibly by adding it to config.includes
+  # or config.webinf_files above.
+  # - For 'rackup', the rackup script you provide as an inline string
+  #   is simply embedded in web.xml.
+  # The script is evaluated in a Rack::Builder to load the application.
+  # Examples:
+  # config.webxml.rackup.path = 'WEB-INF/hello.ru'
+  # config.webxml.rackup = %{require './lib/demo'; run Rack::Adapter::Camping.new(Demo)}
+  # config.webxml.rackup = require 'cgi' && CGI::escapeHTML(File.read("config.ru"))
+
+  # Control the pool of Rails runtimes. Leaving unspecified means
+  # the pool will grow as needed to service requests. It is recommended
+  # that you fix these values when running a production server!
+  # If you're using threadsafe! mode, you probably don't want to set these values,
+  # since 1 runtime(default for threadsafe mode) will be enough.
+  # config.webxml.jruby.min.runtimes = 24
+  # config.webxml.jruby.max.runtimes = 24
+
+  # JNDI data source name
+  # config.webxml.jndi = 'jdbc/rails'
+end

+ 2 - 0
rails-optimized/doc/README_FOR_APP

@@ -0,0 +1,2 @@
+Use this README file to introduce your application and point to useful places in the API for learning more.
+Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.

+ 0 - 0
rails-optimized/lib/assets/.gitkeep


+ 0 - 0
rails-optimized/lib/tasks/.gitkeep


+ 0 - 0
rails-optimized/log/.gitkeep


+ 26 - 0
rails-optimized/public/404.html

@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>The page you were looking for doesn't exist (404)</title>
+  <style type="text/css">
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+    div.dialog {
+      width: 25em;
+      padding: 0 4em;
+      margin: 4em auto 0 auto;
+      border: 1px solid #ccc;
+      border-right-color: #999;
+      border-bottom-color: #999;
+    }
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+  </style>
+</head>
+
+<body>
+  <!-- This file lives in public/404.html -->
+  <div class="dialog">
+    <h1>The page you were looking for doesn't exist.</h1>
+    <p>You may have mistyped the address or the page may have moved.</p>
+  </div>
+</body>
+</html>

+ 26 - 0
rails-optimized/public/422.html

@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>The change you wanted was rejected (422)</title>
+  <style type="text/css">
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+    div.dialog {
+      width: 25em;
+      padding: 0 4em;
+      margin: 4em auto 0 auto;
+      border: 1px solid #ccc;
+      border-right-color: #999;
+      border-bottom-color: #999;
+    }
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+  </style>
+</head>
+
+<body>
+  <!-- This file lives in public/422.html -->
+  <div class="dialog">
+    <h1>The change you wanted was rejected.</h1>
+    <p>Maybe you tried to change something you didn't have access to.</p>
+  </div>
+</body>
+</html>

+ 25 - 0
rails-optimized/public/500.html

@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>We're sorry, but something went wrong (500)</title>
+  <style type="text/css">
+    body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
+    div.dialog {
+      width: 25em;
+      padding: 0 4em;
+      margin: 4em auto 0 auto;
+      border: 1px solid #ccc;
+      border-right-color: #999;
+      border-bottom-color: #999;
+    }
+    h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
+  </style>
+</head>
+
+<body>
+  <!-- This file lives in public/500.html -->
+  <div class="dialog">
+    <h1>We're sorry, but something went wrong.</h1>
+  </div>
+</body>
+</html>

+ 0 - 0
rails-optimized/public/favicon.ico


+ 241 - 0
rails-optimized/public/index.html

@@ -0,0 +1,241 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Ruby on Rails: Welcome aboard</title>
+    <style type="text/css" media="screen">
+      body {
+        margin: 0;
+        margin-bottom: 25px;
+        padding: 0;
+        background-color: #f0f0f0;
+        font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
+        font-size: 13px;
+        color: #333;
+      }
+
+      h1 {
+        font-size: 28px;
+        color: #000;
+      }
+
+      a  {color: #03c}
+      a:hover {
+        background-color: #03c;
+        color: white;
+        text-decoration: none;
+      }
+
+
+      #page {
+        background-color: #f0f0f0;
+        width: 750px;
+        margin: 0;
+        margin-left: auto;
+        margin-right: auto;
+      }
+
+      #content {
+        float: left;
+        background-color: white;
+        border: 3px solid #aaa;
+        border-top: none;
+        padding: 25px;
+        width: 500px;
+      }
+
+      #sidebar {
+        float: right;
+        width: 175px;
+      }
+
+      #footer {
+        clear: both;
+      }
+
+      #header, #about, #getting-started {
+        padding-left: 75px;
+        padding-right: 30px;
+      }
+
+
+      #header {
+        background-image: url("assets/rails.png");
+        background-repeat: no-repeat;
+        background-position: top left;
+        height: 64px;
+      }
+      #header h1, #header h2 {margin: 0}
+      #header h2 {
+        color: #888;
+        font-weight: normal;
+        font-size: 16px;
+      }
+
+
+      #about h3 {
+        margin: 0;
+        margin-bottom: 10px;
+        font-size: 14px;
+      }
+
+      #about-content {
+        background-color: #ffd;
+        border: 1px solid #fc0;
+        margin-left: -55px;
+        margin-right: -10px;
+      }
+      #about-content table {
+        margin-top: 10px;
+        margin-bottom: 10px;
+        font-size: 11px;
+        border-collapse: collapse;
+      }
+      #about-content td {
+        padding: 10px;
+        padding-top: 3px;
+        padding-bottom: 3px;
+      }
+      #about-content td.name  {color: #555}
+      #about-content td.value {color: #000}
+
+      #about-content ul {
+        padding: 0;
+        list-style-type: none;
+      }
+
+      #about-content.failure {
+        background-color: #fcc;
+        border: 1px solid #f00;
+      }
+      #about-content.failure p {
+        margin: 0;
+        padding: 10px;
+      }
+
+
+      #getting-started {
+        border-top: 1px solid #ccc;
+        margin-top: 25px;
+        padding-top: 15px;
+      }
+      #getting-started h1 {
+        margin: 0;
+        font-size: 20px;
+      }
+      #getting-started h2 {
+        margin: 0;
+        font-size: 14px;
+        font-weight: normal;
+        color: #333;
+        margin-bottom: 25px;
+      }
+      #getting-started ol {
+        margin-left: 0;
+        padding-left: 0;
+      }
+      #getting-started li {
+        font-size: 18px;
+        color: #888;
+        margin-bottom: 25px;
+      }
+      #getting-started li h2 {
+        margin: 0;
+        font-weight: normal;
+        font-size: 18px;
+        color: #333;
+      }
+      #getting-started li p {
+        color: #555;
+        font-size: 13px;
+      }
+
+
+      #sidebar ul {
+        margin-left: 0;
+        padding-left: 0;
+      }
+      #sidebar ul h3 {
+        margin-top: 25px;
+        font-size: 16px;
+        padding-bottom: 10px;
+        border-bottom: 1px solid #ccc;
+      }
+      #sidebar li {
+        list-style-type: none;
+      }
+      #sidebar ul.links li {
+        margin-bottom: 5px;
+      }
+
+      .filename {
+        font-style: italic;
+      }
+    </style>
+    <script type="text/javascript">
+      function about() {
+        info = document.getElementById('about-content');
+        if (window.XMLHttpRequest)
+          { xhr = new XMLHttpRequest(); }
+        else
+          { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
+        xhr.open("GET","rails/info/properties",false);
+        xhr.send("");
+        info.innerHTML = xhr.responseText;
+        info.style.display = 'block'
+      }
+    </script>
+  </head>
+  <body>
+    <div id="page">
+      <div id="sidebar">
+        <ul id="sidebar-items">
+          <li>
+            <h3>Browse the documentation</h3>
+            <ul class="links">
+              <li><a href="http://guides.rubyonrails.org/">Rails Guides</a></li>
+              <li><a href="http://api.rubyonrails.org/">Rails API</a></li>
+              <li><a href="http://www.ruby-doc.org/core/">Ruby core</a></li>
+              <li><a href="http://www.ruby-doc.org/stdlib/">Ruby standard library</a></li>
+            </ul>
+          </li>
+        </ul>
+      </div>
+
+      <div id="content">
+        <div id="header">
+          <h1>Welcome aboard</h1>
+          <h2>You&rsquo;re riding Ruby on Rails!</h2>
+        </div>
+
+        <div id="about">
+          <h3><a href="rails/info/properties" onclick="about(); return false">About your application&rsquo;s environment</a></h3>
+          <div id="about-content" style="display: none"></div>
+        </div>
+
+        <div id="getting-started">
+          <h1>Getting started</h1>
+          <h2>Here&rsquo;s how to get rolling:</h2>
+
+          <ol>
+            <li>
+              <h2>Use <code>rails generate</code> to create your models and controllers</h2>
+              <p>To see all available options, run it without parameters.</p>
+            </li>
+
+            <li>
+              <h2>Set up a default route and remove <span class="filename">public/index.html</span></h2>
+              <p>Routes are set up in <span class="filename">config/routes.rb</span>.</p>
+            </li>
+
+            <li>
+              <h2>Create your database</h2>
+              <p>Run <code>rake db:create</code> to create your database. If you're not using SQLite (the default), edit <span class="filename">config/database.yml</span> with your username and password.</p>
+            </li>
+          </ol>
+        </div>
+      </div>
+
+      <div id="footer">&nbsp;</div>
+    </div>
+  </body>
+</html>

+ 5 - 0
rails-optimized/public/robots.txt

@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-Agent: *
+# Disallow: /

+ 13 - 0
rails-optimized/resin-web.xml

@@ -0,0 +1,13 @@
+<web-app xmlns="http://caucho.com/ns/resin">
+
+<database jndi-name='jdbc/hello_world'>
+  <driver>
+    <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
+    <url>jdbc:mysql://172.16.98.98:3306/hello_world?jdbcCompliantTruncation=false&amp;elideSetAutoCommits=true&amp;useLocalSessionState=true&amp;cachePrepStmts=true&amp;cacheCallableStmts=true&amp;alwaysSendSetIsolation=false&amp;prepStmtCacheSize=4096&amp;cacheServerConfiguration=true&amp;prepStmtCacheSqlLimit=2048&amp;zeroDateTimeBehavior=convertToNull&amp;traceProtocol=false&amp;useUnbufferedInput=false&amp;useReadAheadInput=false&amp;maintainTimeStats=false&amp;useServerPrepStmts&amp;cacheRSMetadata=true</url>
+    <user>benchmarkdbuser</user>
+    <password>benchmarkdbpass</password>
+    <useUnicode/>
+  </driver>
+</database>
+
+</web-app>

+ 6 - 0
rails-optimized/script/rails

@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
+
+APP_PATH = File.expand_path('../../config/application',  __FILE__)
+require File.expand_path('../../config/boot',  __FILE__)
+require 'rails/commands'

+ 29 - 0
rails-optimized/setup_jruby.py

@@ -0,0 +1,29 @@
+
+import subprocess
+import sys
+import setup_util
+
+def start(args):
+  setup_util.replace_text("rails-optimized/config/database-jruby.yml", "host: .*", "host: " + args.database_host)
+  setup_util.replace_text("rails-optimized/resin-web.xml", "mysql:\/\/.*:3306", "mysql://" + args.database_host + ":3306")
+
+  try:
+    subprocess.check_call("rvm jruby-1.7.3 do bundle install --gemfile=Gemfile-jruby", shell=True, cwd="rails-optimized")
+    subprocess.check_call("cp Gemfile-jruby Gemfile", shell=True, cwd="rails-optimized")
+    subprocess.check_call("cp Gemfile-jruby.lock Gemfile.lock", shell=True, cwd="rails-optimized")
+    subprocess.check_call("cp config/database-jruby.yml config/database.yml", shell=True, cwd="rails-optimized")
+    subprocess.check_call("rvm jruby-1.7.3 do warble war", shell=True, cwd="rails-optimized")
+    subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True)
+    subprocess.check_call("cp rails-optimized.war $RESIN_HOME/webapps/rails.war", shell=True, cwd="rails-optimized")
+    subprocess.check_call("$RESIN_HOME/bin/resinctl start", shell=True)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop():
+  try:
+    subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True)
+    subprocess.check_call("rm Gemfile", shell=True, cwd="rails-optimized")
+    subprocess.check_call("rm Gemfile.lock", shell=True, cwd="rails-optimized")
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 25 - 0
rails-optimized/setup_ruby.py

@@ -0,0 +1,25 @@
+
+import subprocess
+import sys
+import setup_util
+
+def start(args):
+  setup_util.replace_text("rails-optimized/config/database-ruby.yml", "host: .*", "host: " + args.database_host)
+  
+  try:
+    subprocess.check_call("rvm ruby-2.0.0-p0 do bundle install --gemfile=Gemfile-ruby", shell=True, cwd="rails-optimized")
+    subprocess.check_call("cp Gemfile-ruby Gemfile", shell=True, cwd="rails-optimized")
+    subprocess.check_call("cp Gemfile-ruby.lock Gemfile.lock", shell=True, cwd="rails-optimized")
+    subprocess.check_call("cp config/database-ruby.yml config/database.yml", shell=True, cwd="rails-optimized")
+    subprocess.check_call("rvm ruby-2.0.0-p0 do bundle exec passenger start -p 8080 -d -e production --pid-file=$HOME/FrameworkBenchmarks/rails/rails.pid --nginx-version=1.2.7 --max-pool-size=24", shell=True, cwd="rails-optimized")
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop():
+  try:
+    subprocess.check_call("rvm ruby-2.0.0-p0 do bundle exec passenger stop --pid-file=$HOME/FrameworkBenchmarks/rails/rails.pid", shell=True, cwd='rails-optimized')
+    subprocess.check_call("rm Gemfile", shell=True, cwd="rails-optimized")
+    subprocess.check_call("rm Gemfile.lock", shell=True, cwd="rails-optimized")
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 0 - 0
rails-optimized/vendor/assets/javascripts/.gitkeep


+ 0 - 0
rails-optimized/vendor/assets/stylesheets/.gitkeep


+ 0 - 0
rails-optimized/vendor/plugins/.gitkeep


+ 5 - 5
rails/app/controllers/hello_world_controller.rb

@@ -1,17 +1,17 @@
 class HelloWorldController < ApplicationController
 class HelloWorldController < ApplicationController
+
   def json
   def json
     render :json => {:message => "Hello World!"}
     render :json => {:message => "Hello World!"}
   end
   end
 
 
   def db
   def db
-    queries = params[:queries] || 1
+    queries = (params[:queries] || 1).to_i
 
 
-    results = []
-    (1..queries.to_i).each do
+    results = (1..queries).map do
       # get a random row from the database, which we know has 10000
       # get a random row from the database, which we know has 10000
       # rows with ids 1 - 10000
       # rows with ids 1 - 10000
-      results << World.find(Random.rand(10000) + 1)
+      World.find(Random.rand(10000) + 1)
     end
     end
     render :json => results
     render :json => results
   end
   end
-end
+end

+ 3 - 4
sinatra/hello_world.rb

@@ -21,11 +21,10 @@ get '/json' do
 end
 end
 
 
 get '/db' do
 get '/db' do
-  queries = params[:queries] || 1
+  queries = (params[:queries] || 1).to_i
 
 
-  results = []
-  (1..queries.to_i).each do
-    results << World.find(Random.rand(10000) + 1)
+  results = (1..queries).map do
+    World.find(Random.rand(10000) + 1)
   end
   end
   
   
   results.to_json
   results.to_json

+ 8 - 16
spring/src/main/java/hello/web/HelloDbController.java

@@ -19,18 +19,20 @@ import org.springframework.stereotype.*;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 @Controller
 @Controller
-public class HelloDbController 
+public class HelloDbController
 {
 {
+
   private static final int    DB_ROWS                = 10000;
   private static final int    DB_ROWS                = 10000;
 
 
-  @RequestMapping(value = "/db")
-  public Object index(HttpServletRequest request, HttpServletResponse response, Integer queries)
+  @RequestMapping(value = "/db", produces = "application/json")
+  @ResponseBody
+  public World[] index(Integer queries)
   {
   {
     if (queries == null)
     if (queries == null)
     {
     {
       queries = 1;
       queries = 1;
     }
     }
-    
+
     final World[] worlds = new World[queries];
     final World[] worlds = new World[queries];
     final Random random = ThreadLocalRandom.current();
     final Random random = ThreadLocalRandom.current();
     final Session session = HibernateUtil.getSessionFactory().openSession();
     final Session session = HibernateUtil.getSessionFactory().openSession();
@@ -41,17 +43,7 @@ public class HelloDbController
     }
     }
 
 
     session.close();
     session.close();
-    
-    try 
-    {
-      new MappingJackson2HttpMessageConverter().write(
-          worlds, MediaType.APPLICATION_JSON, new ServletServerHttpResponse(response));
-    } 
-    catch (IOException e) 
-    {
-      // do nothing
-    }
-    
-    return null;
+
+    return worlds;
   }
   }
 }
 }

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