Browse Source

Merge branch 'master' into remove-install-scripts

Conflicts:
	frameworks/Erlang/cowboy/setup.sh
	frameworks/Erlang/elli/setup.sh
	toolset/setup/linux/languages/erlang.sh
	toolset/setup/linux/languages/php.sh
	toolset/setup/linux/systools/leiningen.sh
	toolset/setup/linux/systools/rebar.sh
msmith-techempower 10 years ago
parent
commit
3fca07db77
100 changed files with 2716 additions and 327 deletions
  1. 4 0
      .gitignore
  2. 4 0
      .travis.yml
  3. 1 0
      config/php.ini
  4. 46 14
      frameworks/CSharp/README.md
  5. 51 31
      frameworks/CSharp/nancy/README.md
  6. 5 0
      frameworks/Clojure/pedestal/.gitignore
  7. 22 0
      frameworks/Clojure/pedestal/README.md
  8. 28 0
      frameworks/Clojure/pedestal/benchmark_config.json
  9. 52 0
      frameworks/Clojure/pedestal/config/logback.xml
  10. 3 0
      frameworks/Clojure/pedestal/install.sh
  11. 25 0
      frameworks/Clojure/pedestal/project.clj
  12. 14 0
      frameworks/Clojure/pedestal/setup.sh
  13. 36 0
      frameworks/Clojure/pedestal/src/pedestal/server.clj
  14. 180 0
      frameworks/Clojure/pedestal/src/pedestal/service.clj
  15. 20 0
      frameworks/Clojure/pedestal/test/pedestal/service_test.clj
  16. 4 0
      frameworks/Elixir/phoenix/.gitignore
  17. 8 0
      frameworks/Elixir/phoenix/README.md
  18. 24 0
      frameworks/Elixir/phoenix/benchmark_config.json
  19. 23 0
      frameworks/Elixir/phoenix/config/config.exs
  20. 13 0
      frameworks/Elixir/phoenix/config/dev.exs
  21. 3 0
      frameworks/Elixir/phoenix/config/locales/en.exs
  22. 38 0
      frameworks/Elixir/phoenix/config/prod.exs
  23. 7 0
      frameworks/Elixir/phoenix/config/test.exs
  24. 3 0
      frameworks/Elixir/phoenix/install.sh
  25. 29 0
      frameworks/Elixir/phoenix/lib/hello.ex
  26. 30 0
      frameworks/Elixir/phoenix/lib/hello/endpoint.ex
  27. 30 0
      frameworks/Elixir/phoenix/mix.exs
  28. 6 0
      frameworks/Elixir/phoenix/priv/static/css/phoenix.css
  29. BIN
      frameworks/Elixir/phoenix/priv/static/images/phoenix.png
  30. 565 0
      frameworks/Elixir/phoenix/priv/static/js/phoenix.js
  31. 15 0
      frameworks/Elixir/phoenix/setup.sh
  32. 7 0
      frameworks/Elixir/phoenix/test/hello_test.exs
  33. 1 0
      frameworks/Elixir/phoenix/test/test_helper.exs
  34. 40 0
      frameworks/Elixir/phoenix/web/controllers/page_controller.ex
  35. 11 0
      frameworks/Elixir/phoenix/web/models/repo.exs
  36. 7 0
      frameworks/Elixir/phoenix/web/models/world.exs
  37. 31 0
      frameworks/Elixir/phoenix/web/router.ex
  38. 31 0
      frameworks/Elixir/phoenix/web/templates/layout/application.html.eex
  39. 1 0
      frameworks/Elixir/phoenix/web/templates/page/error.html.eex
  40. 34 0
      frameworks/Elixir/phoenix/web/templates/page/index.html.eex
  41. 1 0
      frameworks/Elixir/phoenix/web/templates/page/not_found.html.eex
  42. 17 0
      frameworks/Elixir/phoenix/web/view.ex
  43. 16 0
      frameworks/Elixir/phoenix/web/views/error_view.ex
  44. 3 0
      frameworks/Elixir/phoenix/web/views/layout_view.ex
  45. 3 0
      frameworks/Elixir/phoenix/web/views/page_view.ex
  46. 1 2
      frameworks/Erlang/cowboy/.gitignore
  47. 1 1
      frameworks/Erlang/cowboy/benchmark_config.json
  48. 1 1
      frameworks/Erlang/cowboy/setup.sh
  49. 1 2
      frameworks/Erlang/elli/.gitignore
  50. 1 1
      frameworks/Erlang/elli/benchmark_config.json
  51. 2 2
      frameworks/Erlang/elli/rebar.config
  52. 1 0
      frameworks/Erlang/elli/setup.sh
  53. 11 5
      frameworks/Haskell/wai/bench/wai.hs
  54. 1 0
      frameworks/Haskell/wai/benchmark_config.json
  55. 2 0
      frameworks/Haskell/yesod/bench/bench.cabal
  56. 119 37
      frameworks/Haskell/yesod/bench/src/yesod.hs
  57. 3 0
      frameworks/Haskell/yesod/benchmark_config.json
  58. 32 6
      frameworks/Java/README.md
  59. 30 8
      frameworks/PHP/README.md
  60. 1 4
      frameworks/PHP/hhvm/once.php.inc
  61. 2 0
      frameworks/PHP/limonade/.gitignore
  62. 26 0
      frameworks/PHP/limonade/benchmark_config.json
  63. 7 0
      frameworks/PHP/limonade/composer.json
  64. 46 0
      frameworks/PHP/limonade/deploy/nginx.conf
  65. 105 0
      frameworks/PHP/limonade/index.php
  66. 11 0
      frameworks/PHP/limonade/install.sh
  67. 5 0
      frameworks/PHP/limonade/models/Fortune.php
  68. 5 0
      frameworks/PHP/limonade/models/World.php
  69. 12 0
      frameworks/PHP/limonade/setup.sh
  70. 19 0
      frameworks/PHP/limonade/views/fortune.php
  71. 1 0
      frameworks/PHP/php-phalcon/app/views/layouts/mongobench.volt
  72. 30 43
      frameworks/PHP/symfony2/README.md
  73. 30 0
      frameworks/Python/API-Hour/README.md
  74. 21 3
      frameworks/Python/README.md
  75. 25 21
      frameworks/Python/bottle/README.md
  76. 20 20
      frameworks/Python/django/README.md
  77. 27 9
      frameworks/Python/falcon/README.md
  78. 11 3
      frameworks/Python/flask/README.md
  79. 20 19
      frameworks/Python/pyramid/README.md
  80. 29 11
      frameworks/Python/tornado/README.md
  81. 40 0
      frameworks/Python/turbogears/README.md
  82. 93 0
      frameworks/Python/turbogears/app.py
  83. 27 0
      frameworks/Python/turbogears/benchmark_config.json
  84. 25 0
      frameworks/Python/turbogears/gunicorn_conf.py
  85. 19 0
      frameworks/Python/turbogears/install.sh
  86. 17 0
      frameworks/Python/turbogears/models/Fortune.py
  87. 17 0
      frameworks/Python/turbogears/models/World.py
  88. 0 0
      frameworks/Python/turbogears/models/__init__.py
  89. 11 0
      frameworks/Python/turbogears/requirements.txt
  90. 7 0
      frameworks/Python/turbogears/setup.sh
  91. 20 0
      frameworks/Python/turbogears/templates/fortunes.html
  92. 29 0
      frameworks/Python/uwsgi/README.md
  93. 20 10
      frameworks/Python/wsgi/README.md
  94. 52 7
      frameworks/Ruby/README.md
  95. 32 2
      frameworks/Ruby/grape/README.md
  96. 23 8
      frameworks/Ruby/ngx_mruby/README.md
  97. 46 0
      frameworks/Ruby/padrino/README.md
  98. 28 13
      frameworks/Ruby/rack/README.md
  99. 28 22
      frameworks/Ruby/rails-stripped/README.md
  100. 31 22
      frameworks/Ruby/rails/README.md

+ 4 - 0
.gitignore

@@ -3,6 +3,10 @@ installs
 *.log
 *.log
 node_modules/
 node_modules/
 
 
+# Added for pedestal framework test
+lib/
+.lein-deps-sum
+
 # eclipse
 # eclipse
 .classpath
 .classpath
 .project
 .project

+ 4 - 0
.travis.yml

@@ -33,10 +33,12 @@ env:
     - "TESTDIR=Clojure/compojure"
     - "TESTDIR=Clojure/compojure"
     - "TESTDIR=Clojure/http-kit"
     - "TESTDIR=Clojure/http-kit"
     - "TESTDIR=Clojure/luminus"
     - "TESTDIR=Clojure/luminus"
+    - "TESTDIR=Clojure/pedestal"
     - "TESTDIR=Dart/dart"
     - "TESTDIR=Dart/dart"
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-start"
     - "TESTDIR=Dart/dart-start"
     - "TESTDIR=Dart/dart-stream"
     - "TESTDIR=Dart/dart-stream"
+    - "TESTDIR=Elixir/phoenix"
     - "TESTDIR=Erlang/cowboy"
     - "TESTDIR=Erlang/cowboy"
     - "TESTDIR=Erlang/elli"
     - "TESTDIR=Erlang/elli"
     - "TESTDIR=Go/beego"
     - "TESTDIR=Go/beego"
@@ -100,6 +102,7 @@ env:
     - "TESTDIR=PHP/fuel"
     - "TESTDIR=PHP/fuel"
     - "TESTDIR=PHP/kohana"
     - "TESTDIR=PHP/kohana"
     - "TESTDIR=PHP/php-laravel"
     - "TESTDIR=PHP/php-laravel"
+    - "TESTDIR=PHP/limonade"
     - "TESTDIR=PHP/lithium"
     - "TESTDIR=PHP/lithium"
     - "TESTDIR=PHP/php-micromvc"
     - "TESTDIR=PHP/php-micromvc"
     - "TESTDIR=PHP/php-phalcon"
     - "TESTDIR=PHP/php-phalcon"
@@ -124,6 +127,7 @@ env:
     - "TESTDIR=Python/flask"
     - "TESTDIR=Python/flask"
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/tornado"
     - "TESTDIR=Python/tornado"
+    - "TESTDIR=Python/turbogears"
     - "TESTDIR=Python/uwsgi"
     - "TESTDIR=Python/uwsgi"
     - "TESTDIR=Python/web2py"
     - "TESTDIR=Python/web2py"
     - "TESTDIR=Python/wheezyweb"
     - "TESTDIR=Python/wheezyweb"

+ 1 - 0
config/php.ini

@@ -870,6 +870,7 @@ zend_extension=opcache.so
 extension=redis.so
 extension=redis.so
 extension=phalcon.so
 extension=phalcon.so
 extension=yaf.so
 extension=yaf.so
+extension=mongo.so
 ;extension=php_bz2.dll
 ;extension=php_bz2.dll
 ;extension=php_curl.dll
 ;extension=php_curl.dll
 ;extension=php_fileinfo.dll
 ;extension=php_fileinfo.dll

+ 46 - 14
frameworks/CSharp/README.md

@@ -1,26 +1,30 @@
-# Limited Travis-CI Verification 
+# C# (CSharp) Frameworks
 
 
-Because the verification system uses the linux-only Travis-CI
-service, verifying Windows-only tests has to be done manually
-and is very time consuming. 
+The information below contains information specific to C#. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
 
 
-Consider including an additional test, likely based on Mono and 
-FastCGI (e.g. xsp), that can run on Linux when submitting a new
-framework. This will drastically speed up our ability to merge
-in your pull request. 
+## Infrastructure Software Versions
 
 
-# Different Mono Versions
+* [Mono C# compiler latest version](http://www.mono-project.com/docs/about-mono/languages/csharp/)
+
+## Adding a New C# Framework
+
+### Different Mono Versions
 
 
 While we have not currently run into the need to have multiple 
 While we have not currently run into the need to have multiple 
 simultaneous Mono installations, it is [possible](http://www.mono-project.com/docs/compiling-mono/parallel-mono-environments/)
 simultaneous Mono installations, it is [possible](http://www.mono-project.com/docs/compiling-mono/parallel-mono-environments/)
 
 
-# Debugging Mono + NuGet
+### Debugging Mono + NuGet
 
 
-Mono understands an environment variable `MONO_LOG_LEVEL=debug` that is helpful for checking that 
+Mono understands an environment variable `MONO_LOG_LEVEL=debug` 
+that is helpful for checking that 
 mono is properly working e.g. loading necessary DLL's. 
 mono is properly working e.g. loading necessary DLL's. 
 
 
-Most NuGet commands understand a `-Verbosity` flag, which is great because the error messages can be completely
-mystifying when working with Mono too. Use this would enable all the debugging you can: 
+Most NuGet commands understand a `-Verbosity` flag, which is 
+great because the error messages can be completely
+mystifying when working with Mono too. Use this would enable 
+all the debugging you can: 
 
 
     $ MONO_LOG_LEVEL=debug mono NuGet2.exe update -Verbosity "detailed" -self
     $ MONO_LOG_LEVEL=debug mono NuGet2.exe update -Verbosity "detailed" -self
 
 
@@ -28,10 +32,38 @@ For example, aspnet was constantly failing with this message:
     
     
     Could not connect to the feed specified at 'https://www.nuget.org/api/v2/'. Please verify that the package source (located in the Package Manager Settings) is valid and ensure your network connectivity.`. 
     Could not connect to the feed specified at 'https://www.nuget.org/api/v2/'. Please verify that the package source (located in the Package Manager Settings) is valid and ensure your network connectivity.`. 
 
 
-Using `-Verbosity "detailed"` shows that the real error is actually a Mono library problem, as so: 
+Using `-Verbosity "detailed"` shows that the real error is 
+actually a Mono library problem, as so: 
 
 
     System.InvalidOperationException: Could not connect to the feed specified at 'https://www.nuget.org/api/v2/'. Please verify that the package source (located in the Package Manager Settings) is valid and ensure your network connectivity. ---> System.Net.WebException: libMonoPosixHelper.so ---> System.DllNotFoundException: libMonoPosixHelper.so
     System.InvalidOperationException: Could not connect to the feed specified at 'https://www.nuget.org/api/v2/'. Please verify that the package source (located in the Package Manager Settings) is valid and ensure your network connectivity. ---> System.Net.WebException: libMonoPosixHelper.so ---> System.DllNotFoundException: libMonoPosixHelper.so
       at (wrapper managed-to-native) System.IO.Compression.DeflateStreamNative:CreateZStream (System.IO.Compression.CompressionMode,bool,System.IO.Compression.DeflateStreamNative/UnmanagedReadOrWrite,intptr)
       at (wrapper managed-to-native) System.IO.Compression.DeflateStreamNative:CreateZStream (System.IO.Compression.CompressionMode,bool,System.IO.Compression.DeflateStreamNative/UnmanagedReadOrWrite,intptr)
       <snip>
       <snip>
 
 
 More helpful info is [here](http://www.mono-project.com/docs/advanced/pinvoke/dllnotfoundexception/), [here](http://docs.nuget.org/docs/reference/command-line-reference)
 More helpful info is [here](http://www.mono-project.com/docs/advanced/pinvoke/dllnotfoundexception/), [here](http://docs.nuget.org/docs/reference/command-line-reference)
+
+### Limited Travis-CI Verification 
+
+Because the verification system uses the linux-only Travis-CI
+service, verifying Windows-only tests has to be done manually
+and is very time consuming. 
+
+Consider including an additional test, likely based on Mono and 
+FastCGI (e.g. xsp), that can run on Linux when submitting a new
+framework. This will drastically speed up our ability to merge
+in your pull request. 
+
+## Get Help
+
+### C# Experts
+
+_There aren't any C# experts listed, yet. If you're an expert, add yourself!_
+
+### C# Community
+
+_We don't have any community links added. Add some to help further guide 
+future contirbutors._
+
+### Resources
+
+_If you stumble upon some helpful links or discussions, add them 
+for easy reference for future contributors._

+ 51 - 31
frameworks/CSharp/nancy/README.md

@@ -1,21 +1,54 @@
-# Nancy on Mono and Windows
+# Nancy on Mono and Windows Benchmarking Test
 
 
-## Tests
+The information below contains information specific to Nancy on Mono and Windows. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [CSharp README](../).
 
 
-### JSON
+This is the Nancy on Mono and Windows portion of a [benchmarking test suite](../../) 
+comparing a variety of web platforms.
 
 
-* `http://localhost:8080/json`
+## Infrastructure Software Versions
 
 
----
+**Language**
+
+* C# 5.0
+
+**Platforms**
+
+* .NET Framework 4.5 (Windows)
+* Mono 3.0.X (Linux)
+
+**Web Servers**
+
+* IIS 8 (Windows)
+* nginx 1.4.0 & XSP FastCGI (Linux)
+
+**Web Stack**
+
+* ASP.NET 4.5
+* Nancy 0.17.1 (custom build to address this issue: https://github.com/NancyFx/Nancy/pull/1100)
+
+**Databases**
+
+* MySQL Connector/Net
+
+**Developer Tools**
+
+* Visual Studio 2012
+
+## Paths & Source for Tests
+
+* [JSON Serialization](NancyModules/JsonModule.cs): "/json"
 
 
 ### Nancy - Dapper (ORM)
 ### Nancy - Dapper (ORM)
 
 
-**MySQL**
+* [Single Database Query](NancyModules/DbModule.cs): "/db"
+* [Multiple Database Queries](NancyModules/DbModule.cs): "/db/10"
 
 
-* `http://localhost:8080/db`
-* `http://localhost:8080/db/10`
+## Add a New Test for Nancy
 
 
-## Mono Installation
+### Mono Installation
 
 
     sudo apt-get install build-essential autoconf automake libtool zlib1g-dev git
     sudo apt-get install build-essential autoconf automake libtool zlib1g-dev git
 
 
@@ -36,31 +69,18 @@
     make
     make
     sudo make install
     sudo make install
 
 
-## Versions
-
-**Language**
-
-* C# 5.0
-
-**Platforms**
-
-* .NET Framework 4.5 (Windows)
-* Mono 3.0.X (Linux)
-
-**Web Servers**
-
-* IIS 8 (Windows)
-* nginx 1.4.0 & XSP FastCGI (Linux)
+## Get Help
 
 
-**Web Stack**
+### Experts
 
 
-* ASP.NET 4.5
-* Nancy 0.17.1 (custom build to address this issue: https://github.com/NancyFx/Nancy/pull/1100)
+_There aren't any experts listed, yet. If you're an expert, add yourself!_
 
 
-**Databases**
+### Community
 
 
-* MySQL Connector/Net
+* Chat in the [#NancyFX](https://jabbr.net/account/login?ReturnUrl=%2F#/rooms/nancyfx) room on JabbR.
+* #NancyFx on Twitter.
 
 
-**Developer Tools**
+### Resources
 
 
-* Visual Studio 2012
+* [Source Code](https://github.com/NancyFx/Nancy)
+* [Issue #877 - Discussion regarding Event2.dll and Global.asax thread configuration](https://github.com/TechEmpower/FrameworkBenchmarks/issues/877)

+ 5 - 0
frameworks/Clojure/pedestal/.gitignore

@@ -0,0 +1,5 @@
+target/
+tmp/
+logs/
+.lein-repl-history
+.nrepl-port

+ 22 - 0
frameworks/Clojure/pedestal/README.md

@@ -0,0 +1,22 @@
+# Pedestal Benchmarking Test
+
+This is the Pedestal portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+## Test URLs
+### JSON Encoding Test
+`http://localhost:8080/json`
+
+### Single Query Test
+`http://localhost:8080/db`
+
+### Multiple Query Test
+`http://localhost:8080/queries?queries=number`
+
+### Fortune Test
+`http://localhost:8080/fortunes`
+
+### Database Updates
+`http://localhost:8080/updates?queries=number`
+
+### Plaintext
+`http://localhost:8080/plaintext`

+ 28 - 0
frameworks/Clojure/pedestal/benchmark_config.json

@@ -0,0 +1,28 @@
+{
+  "framework": "pedestal",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "orm": "micro",
+      "framework": "pedestal",
+      "language": "Clojure",
+      "platform": "Servlet",
+      "webserver": "Jetty",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "pedestal",
+      "notes": "servlet"
+    }
+  }]
+}
+

+ 52 - 0
frameworks/Clojure/pedestal/config/logback.xml

@@ -0,0 +1,52 @@
+<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
+<configuration scan="true" scanPeriod="10 seconds">
+
+  <!-- Simple file output -->
+  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+    <!-- encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+
+    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+      <!-- rollover daily -->
+      <fileNamePattern>logs/pedestal-api-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+      <timeBasedFileNamingAndTriggeringPolicy
+          class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+        <!-- or whenever the file size reaches 64 MB -->
+        <maxFileSize>64 MB</maxFileSize>
+      </timeBasedFileNamingAndTriggeringPolicy>
+    </rollingPolicy>
+
+    <!-- Safely log to the same file from multiple JVMs. Degrades performance! -->
+    <prudent>true</prudent>
+  </appender>
+
+
+  <!-- Console output -->
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoder defaults to ch.qos.logback.classic.encoder.PatternLayoutEncoder -->
+    <encoder>
+      <pattern>%-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+    <!-- Only log level INFO and above -->
+    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+      <level>INFO</level>
+    </filter>
+  </appender>
+
+
+  <!-- Enable FILE and STDOUT appenders for all log messages.
+       By default, only log at level INFO and above. -->
+  <root level="INFO">
+    <appender-ref ref="FILE" />
+    <appender-ref ref="STDOUT" />
+  </root>
+
+  <!-- For loggers in the these namespaces, log at all levels. -->
+  <logger name="user" level="ALL" />
+  <!-- To log pedestal internals, enable this and change ThresholdFilter to DEBUG
+    <logger name="io.pedestal" level="ALL" />
+  -->
+
+</configuration>

+ 3 - 0
frameworks/Clojure/pedestal/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends leiningen java7

+ 25 - 0
frameworks/Clojure/pedestal/project.clj

@@ -0,0 +1,25 @@
+(defproject pedestal "0.1"
+  :description "A Clojure-Pedestal server for testing in the Framework Benchmarks"
+  :url "https://github.com/TechEmpower/FrameworkBenchmarks"
+  :license {:name "Eclipse Public License"
+            :url "http://www.eclipse.org/legal/epl-v10.html"}
+  :dependencies [[org.clojure/clojure "1.6.0"]
+                 [io.pedestal/pedestal.service "0.3.1"]
+                 [io.pedestal/pedestal.jetty "0.3.1"]
+                 [ch.qos.logback/logback-classic "1.1.2" :exclusions [org.slf4j/slf4j-api]]
+                 [org.slf4j/jul-to-slf4j "1.7.7"]
+                 [org.slf4j/jcl-over-slf4j "1.7.7"]
+                 [org.slf4j/log4j-over-slf4j "1.7.7"]
+                 [org.clojure/data.json "0.2.5"]
+                 [org.clojure/java.jdbc "0.3.6"]
+                 [korma "0.4.0"]
+                 [mysql/mysql-connector-java "5.1.6"]
+                 [hiccup "1.0.4"]]
+  :min-lein-version "2.0.0"
+  :resource-paths ["config", "resources"]
+  :profiles {:dev {:aliases {"run-dev" ["trampoline" "run" "-m" "pedestal.server/run-dev"]}
+                   :dependencies [[io.pedestal/pedestal.service-tools "0.3.1"]]}}
+  :auto-clean false
+  :main pedestal.server
+  :aot [pedestal.server]
+  :uberjar-name "pedestal-standalone.jar")

+ 14 - 0
frameworks/Clojure/pedestal/setup.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+source $IROOT/java7.installed
+
+source $IROOT/lein.installed
+
+lein clean
+
+rm -rf target
+# pack all dependencies into a single jar: target/pedestal-standalone.jar
+lein uberjar
+# -server is much faster
+# 'lein run' passes '-client -XX:+TieredCompilation -XX:TieredStopAtLevel=1' which make it starts fast, but runs slow
+java -server -jar target/pedestal-standalone.jar &

+ 36 - 0
frameworks/Clojure/pedestal/src/pedestal/server.clj

@@ -0,0 +1,36 @@
+(ns pedestal.server
+  (:gen-class)
+  (:require [io.pedestal.http :as server]
+            [pedestal.service :as service]))
+
+
+;; This is an adapted service map, that can be started and stopped
+;; From the REPL you can call server/start and server/stop on this service
+(defonce runnable-service (server/create-server service/service))
+
+
+(defn run-dev
+  "The entry-point for 'lein run-dev'"
+  [& args]
+  (println "\nCreating your [DEV] server...")
+  (-> service/service ;; start with production configuration
+      (merge {:env :dev
+              ;; do not block thread that starts web server
+              ::server/join? false
+              ;; Routes can be a function that resolve routes,
+              ;;  we can use this to set the routes to be reloadable
+              ::server/routes #(deref #'service/routes)
+              ;; all origins are allowed in dev mode
+              ::server/allowed-origins {:creds true :allowed-origins (constantly true)}})
+      ;; Wire up interceptor chains
+      server/default-interceptors
+      server/dev-interceptors
+      server/create-server
+      server/start))
+
+
+(defn -main
+  "The entry-point for 'lein run'"
+  [& args]
+  (println "\nCreating your server...")
+  (server/start runnable-service))

+ 180 - 0
frameworks/Clojure/pedestal/src/pedestal/service.clj

@@ -0,0 +1,180 @@
+(ns pedestal.service
+  (:import com.mchange.v2.c3p0.ComboPooledDataSource)
+  (:use korma.db
+        korma.core
+        hiccup.core
+        hiccup.util
+        hiccup.page)
+  (:require [io.pedestal.http :as bootstrap]
+            [io.pedestal.http.route :as route]
+            [io.pedestal.http.body-params :as body-params]
+            [io.pedestal.http.route.definition :refer [defroutes]]
+            [ring.util.response :as ring-resp]
+            [clojure.data.json :as json]
+            [clojure.java.jdbc :as jdbc]))
+
+
+(defn json-serialization
+  "Test 1: JSON serialization"
+  [request]
+  (bootstrap/json-response {:message "Hello, World!"}))
+
+
+;; MySQL connection
+(defdb mysql-db
+  (mysql {
+    :classname "com.mysql.jdbc.Driver"
+    :subprotocol "mysql"
+    :subname "//localhost:3306/hello_world"
+    :user "benchmarkdbuser"
+    :password "benchmarkdbpass"
+    ;;OPTIONAL KEYS
+    :delimiters "" ;; remove delimiters
+    :maximum-pool-size 256}))
+
+
+;; Set up entity World and the database representation
+(defentity world
+  (pk :id)
+  (table :world)
+  (entity-fields :id :randomNumber) ;; Default fields for select
+  (database mysql-db))
+
+
+(defn random-world []
+  "Query a random World record from the database"
+  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
+    (select world
+      (where {:id id }))))
+
+
+(defn run-queries
+  "Run query repeatedly -- Always returns an array"
+  [queries]
+  (flatten (take queries (repeatedly random-world))))
+
+
+(defn single-query-test
+  "Test 2: Single database query"
+  [request]
+  (bootstrap/json-response (first (run-queries 1))))
+
+
+(defn sanitizeQueriesParam
+  "Sanitizes the `queries` parameter. Caps the value between 1 and 500.
+Invalid (stringy) values become 1"
+  [request]
+  (let [queries (-> request :params :queries)]
+    (let [n
+      (if (= (re-find #"\A-?\d+" queries) nil)
+        1
+        (Integer/parseInt queries))]
+    (cond
+      (< n 1) 1
+      (> n 500) 500
+      :else n))))
+
+
+(defn multiple-query-test
+  "Test 3: Multiple database queries"
+  [request]
+  (-> request
+    (sanitizeQueriesParam)
+    (run-queries)
+    (bootstrap/json-response)))
+
+
+; Set up entity Fortune and the database representation
+(defentity fortune
+  (pk :id)
+  (table :fortune)
+  (entity-fields :id :message)
+  (database mysql-db))
+
+
+(defn get-all-fortunes []
+  "Query all Fortune records from the database."
+  (select fortune
+    (fields :id :message)))
+
+
+(defn get-fortunes []
+  "Fetch the full list of Fortunes from the database, sort them by the fortune
+message text, and then return the results."
+  (sort-by #(:message %)
+    (conj
+      (get-all-fortunes)
+      { :id 0 :message "Additional fortune added at request time." })))
+
+
+(defn fortunes-hiccup [fortunes]
+  "Render the given fortunes to simple HTML using Hiccup."
+  (html5
+   [:head
+    [:title "Fortunes"]]
+   [:body
+    [:table
+     [:tr
+      [:th "id"]
+      [:th "message"]]
+     (for [x fortunes]
+       [:tr
+        [:td (:id x)]
+        [:td (escape-html (:message x))]])
+     ]]))
+
+
+(defn fortune-test [request]
+  "Test 4: Fortunes"
+  (->
+    (get-fortunes)
+    (fortunes-hiccup)
+    (ring-resp/response)
+    (ring-resp/content-type "text/html")
+    (ring-resp/charset "utf-8")))         ;; Apply charset after content type
+
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+Persists the changes to sql then returns the updated entities"
+  [request]
+  (let [results (-> request (sanitizeQueriesParam) (run-queries))]
+    (for [w results]
+      (update-in w [:randomNumber (inc (rand-int 9999))]
+        (update world
+          (set-fields {:randomNumber (:randomNumber w)})
+          (where {:id [:id w]}))))
+  results))
+
+
+(defn db-updates
+  "Test 5: Database updates"
+  [request]
+  (-> request
+    (update-and-persist)
+    (bootstrap/json-response)))
+
+
+(defn plaintext
+  "Test 6: Plaintext"
+  [request]
+  (ring-resp/response "Hello, World!"))
+
+
+(defroutes routes
+  [[
+  [  "/json"      {:get json-serialization}]
+  [  "/db"        {:get single-query-test}]
+  [  "/queries"   {:get multiple-query-test}]
+  [  "/fortunes"  {:get fortune-test}]
+  [  "/updates"   {:get db-updates}]
+  [  "/plaintext" {:get plaintext}]]])
+
+
+(def service
+  "How the server will look, not the code to start it up"
+  { :env :prod
+    ::bootstrap/routes routes
+    ::bootstrap/resource-path "/public"
+    ::bootstrap/type :jetty
+    ::bootstrap/port 8080})

+ 20 - 0
frameworks/Clojure/pedestal/test/pedestal/service_test.clj

@@ -0,0 +1,20 @@
+(ns pedestal.service-test
+  (:require [clojure.test :refer :all]
+            [io.pedestal.test :refer :all]
+            [io.pedestal.http :as bootstrap]
+            [pedestal.service :as service]))
+
+(def service
+  (::bootstrap/service-fn (bootstrap/create-servlet service/service)))
+
+(deftest home-page-test
+  (is (=
+       (:body (response-for service :get "/json"))
+       "{\"hello\": \"world\""))
+  (is (=
+       (:headers (response-for service :get "/json"))
+       {"Content-Type" "text/html;charset=UTF-8"
+        "Strict-Transport-Security" "max-age=31536000; includeSubdomains"
+        "X-Frame-Options" "DENY"
+        "X-Content-Type-Options" "nosniff"
+        "X-XSS-Protection" "1; mode=block"})))

+ 4 - 0
frameworks/Elixir/phoenix/.gitignore

@@ -0,0 +1,4 @@
+/_build
+/deps
+erl_crash.dump
+*.ez

+ 8 - 0
frameworks/Elixir/phoenix/README.md

@@ -0,0 +1,8 @@
+# Hello
+
+To start your new Phoenix application:
+
+1. Install dependencies with `mix deps.get`
+2. Start Phoenix endpoint with `mix phoenix.server`
+
+Now you can visit `localhost:8080` from your browser.

+ 24 - 0
frameworks/Elixir/phoenix/benchmark_config.json

@@ -0,0 +1,24 @@
+{
+    "framework": "phoenix",
+    "tests": [{
+        "default": {
+            "setup_file": "setup",
+            "json_url": "/json",
+            "plaintext_url": "/plaintext",
+            "port": 8080,
+            "approach": "Realistic",
+            "classification": "Framework",
+            "database": "Postgres",
+            "framework": "Phoenix",
+            "language": "elixir",
+            "orm": "etco",
+            "platform": "Erlang/OTP",
+            "webserver": "cowboy",
+            "os": "Linux",
+            "database_os": "Linux",
+            "display_name": "phoenix",
+            "notes": "",
+            "versus": ""
+        }
+    }]
+}

+ 23 - 0
frameworks/Elixir/phoenix/config/config.exs

@@ -0,0 +1,23 @@
+# This file is responsible for configuring your application
+# and its dependencies with the aid of the Mix.Config module.
+#
+# This configuration file is loaded before any dependency and
+# is restricted to this project.
+use Mix.Config
+
+# Configures the endpoint
+config :hello, Hello.Endpoint,
+  url: [host: "localhost"],
+  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx",
+  debug_errors: false,
+  pubsub: [adapter: Phoenix.PubSub.PG2]
+
+
+# Configures Elixir's Logger
+config :logger, :console,
+  format: "$time $metadata[$level] $message\n",
+  metadata: [:request_id]
+
+# Import environment specific config. This must remain at the bottom
+# of this file so it overrides the configuration defined above.
+import_config "#{Mix.env}.exs"

+ 13 - 0
frameworks/Elixir/phoenix/config/dev.exs

@@ -0,0 +1,13 @@
+use Mix.Config
+
+config :hello, Hello.Endpoint,
+  url: [host: "localhost", port: 8080],
+  http: [port: System.get_env("PORT") || 8080],
+  debug_errors: true,
+  cache_static_lookup: false
+
+# Enables code reloading for development
+config :phoenix, :code_reloader, true
+
+# Do not include metadata nor timestamps in development logs
+config :logger, :console, format: "[$level] $message\n"

+ 3 - 0
frameworks/Elixir/phoenix/config/locales/en.exs

@@ -0,0 +1,3 @@
+[
+  hello: "Hello"
+]

+ 38 - 0
frameworks/Elixir/phoenix/config/prod.exs

@@ -0,0 +1,38 @@
+use Mix.Config
+
+config :hello, Hello.Endpoint,
+  url: [host: "localhost", port: 8080],
+  http: [port: 8080],
+  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx",
+  cache_static_lookup: false
+
+# ## SSL Support
+#
+# To get SSL working, you will need to add the `https` key
+# to the previous section:
+#
+#  config:hello, Hello.Endpoint,
+#    ...
+#    https: [port: 443,
+#            keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
+#            certfile: System.get_env("SOME_APP_SSL_CERT_PATH")]
+#
+# Where those two env variables point to a file on
+# disk for the key and cert.
+
+
+# Do not pring debug messages in production
+config :logger, level: :info
+
+# ## Using releases
+#
+# If you are doing OTP releases, you need to instruct Phoenix
+# to start the server for all endpoints:
+#
+#    config :phoenix, :serve_endpoints, true
+#
+# Alternatively, you can configure exactly which server to
+# start per endpoint:
+#
+#     config :hello, Hello.Endpoint, server: true
+#

+ 7 - 0
frameworks/Elixir/phoenix/config/test.exs

@@ -0,0 +1,7 @@
+use Mix.Config
+
+config :hello, Hello.Endpoint,
+  http: [port: System.get_env("PORT") || 4001]
+
+# Print only warnings and errors during test
+config :logger, level: :warn

+ 3 - 0
frameworks/Elixir/phoenix/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends elixir

+ 29 - 0
frameworks/Elixir/phoenix/lib/hello.ex

@@ -0,0 +1,29 @@
+defmodule Hello do
+  use Application
+
+  # See http://elixir-lang.org/docs/stable/elixir/Application.html
+  # for more information on OTP Applications
+  def start(_type, _args) do
+    import Supervisor.Spec, warn: false
+
+    children = [
+      # Start the endpoint when the application starts
+      supervisor(Hello.Endpoint, []),
+      # Here you could define other workers and supervisors as children
+      # worker(Hello.Worker, [arg1, arg2, arg3]),
+      # worker(Hello.Repo, [])
+    ]
+
+    # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html
+    # for other strategies and supported options
+    opts = [strategy: :one_for_one, name: Hello.Supervisor]
+    Supervisor.start_link(children, opts)
+  end
+
+  # Tell Phoenix to update the endpoint configuration
+  # whenever the application is updated.
+  def config_change(changed, _new, removed) do
+    Hello.Endpoint.config_change(changed, removed)
+    :ok
+  end
+end

+ 30 - 0
frameworks/Elixir/phoenix/lib/hello/endpoint.ex

@@ -0,0 +1,30 @@
+defmodule Hello.Endpoint do
+  use Phoenix.Endpoint, otp_app: :hello
+
+  # Serve at "/" the given assets from "priv/static" directory
+  plug Plug.Static,
+    at: "/", from: :hello,
+    only: ~w(css images js favicon.ico robots.txt)
+
+  plug Plug.Logger
+
+  # Code reloading will only work if the :code_reloader key of
+  # the :phoenix application is set to true in your config file.
+  plug Phoenix.CodeReloader
+
+  plug Plug.Parsers,
+    parsers: [:urlencoded, :multipart, :json],
+    pass: ["*/*"],
+    json_decoder: Poison
+
+  plug Plug.MethodOverride
+  plug Plug.Head
+
+  plug Plug.Session,
+    store: :cookie,
+    key: "_hello_key",
+    signing_salt: "DNlAnJ2o",
+    encryption_salt: "AOXxaZRq"
+
+  plug :router, Hello.Router
+end

+ 30 - 0
frameworks/Elixir/phoenix/mix.exs

@@ -0,0 +1,30 @@
+defmodule Hello.Mixfile do
+  use Mix.Project
+
+  def project do
+    [app: :hello,
+     version: "0.0.1",
+     elixir: "~> 1.0",
+     elixirc_paths: ["lib", "web"],
+     compilers: [:phoenix] ++ Mix.compilers,
+     deps: deps]
+  end
+
+  # Configuration for the OTP application
+  #
+  # Type `mix help compile.app` for more information
+  def application do
+    [mod: {Hello, []},
+     applications: [:phoenix, :cowboy, :logger, :postgrex, :ecto]]
+  end
+
+  # Specifies your project dependencies
+  #
+  # Type `mix help deps` for examples and options
+  defp deps do
+    [{:phoenix, "~> 0.9.0"},
+     {:cowboy, "~> 1.0"},
+     {:postgrex, "~> 0.6.0"},
+     {:ecto, "~> 0.2.5"}]
+  end
+end

File diff suppressed because it is too large
+ 6 - 0
frameworks/Elixir/phoenix/priv/static/css/phoenix.css


BIN
frameworks/Elixir/phoenix/priv/static/images/phoenix.png


+ 565 - 0
frameworks/Elixir/phoenix/priv/static/js/phoenix.js

@@ -0,0 +1,565 @@
+"use strict";
+
+var _prototypeProperties = function (child, staticProps, instanceProps) { if (staticProps) Object.defineProperties(child, staticProps); if (instanceProps) Object.defineProperties(child.prototype, instanceProps); };
+
+var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } };
+
+(function (root, factory) {
+  if (typeof define === "function" && define.amd) {
+    return define(["phoenix"], factory);
+  } else if (typeof exports === "object") {
+    return factory(exports);
+  } else {
+    root.Phoenix = {};
+    return factory.call(root, root.Phoenix);
+  }
+})(Function("return this")(), function (exports) {
+  var root = this;
+  var SOCKET_STATES = { connecting: 0, open: 1, closing: 2, closed: 3 };
+
+  exports.Channel = (function () {
+    function Channel(topic, message, callback, socket) {
+      _classCallCheck(this, Channel);
+
+      this.topic = topic;
+      this.message = message;
+      this.callback = callback;
+      this.socket = socket;
+      this.bindings = null;
+
+      this.reset();
+    }
+
+    _prototypeProperties(Channel, null, {
+      reset: {
+        value: function reset() {
+          this.bindings = [];
+        },
+        writable: true,
+        configurable: true
+      },
+      on: {
+        value: function on(event, callback) {
+          this.bindings.push({ event: event, callback: callback });
+        },
+        writable: true,
+        configurable: true
+      },
+      isMember: {
+        value: function isMember(topic) {
+          return this.topic === topic;
+        },
+        writable: true,
+        configurable: true
+      },
+      off: {
+        value: function off(event) {
+          this.bindings = this.bindings.filter(function (bind) {
+            return bind.event !== event;
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      trigger: {
+        value: function trigger(triggerEvent, msg) {
+          this.bindings.filter(function (bind) {
+            return bind.event === triggerEvent;
+          }).map(function (bind) {
+            return bind.callback(msg);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      send: {
+        value: function send(event, payload) {
+          this.socket.send({ topic: this.topic, event: event, payload: payload });
+        },
+        writable: true,
+        configurable: true
+      },
+      leave: {
+        value: function leave() {
+          var message = arguments[0] === undefined ? {} : arguments[0];
+          this.socket.leave(this.topic, message);
+          this.reset();
+        },
+        writable: true,
+        configurable: true
+      }
+    });
+
+    return Channel;
+  })();
+
+
+  exports.Socket = (function () {
+    // Initializes the Socket
+    //
+    // endPoint - The string WebSocket endpoint, ie, "ws://example.com/ws",
+    //                                               "wss://example.com"
+    //                                               "/ws" (inherited host & protocol)
+    // opts - Optional configuration
+    //   transport - The Websocket Transport, ie WebSocket, Phoenix.LongPoller.
+    //               Defaults to WebSocket with automatic LongPoller fallback.
+    //   heartbeatIntervalMs - The millisecond interval to send a heartbeat message
+    //   logger - The optional function for specialized logging, ie:
+    //            `logger: (msg) -> console.log(msg)`
+    //
+    function Socket(endPoint) {
+      var opts = arguments[1] === undefined ? {} : arguments[1];
+      _classCallCheck(this, Socket);
+
+      this.states = SOCKET_STATES;
+      this.stateChangeCallbacks = { open: [], close: [], error: [], message: [] };
+      this.flushEveryMs = 50;
+      this.reconnectTimer = null;
+      this.reconnectAfterMs = 5000;
+      this.heartbeatIntervalMs = 30000;
+      this.channels = [];
+      this.sendBuffer = [];
+
+      this.transport = opts.transport || root.WebSocket || exports.LongPoller;
+      this.heartbeatIntervalMs = opts.heartbeatIntervalMs || this.heartbeatIntervalMs;
+      this.logger = opts.logger || function () {}; // noop
+      this.endPoint = this.expandEndpoint(endPoint);
+      this.resetBufferTimer();
+      this.reconnect();
+    }
+
+    _prototypeProperties(Socket, null, {
+      protocol: {
+        value: function protocol() {
+          return location.protocol.match(/^https/) ? "wss" : "ws";
+        },
+        writable: true,
+        configurable: true
+      },
+      expandEndpoint: {
+        value: function expandEndpoint(endPoint) {
+          if (endPoint.charAt(0) !== "/") {
+            return endPoint;
+          }
+          if (endPoint.charAt(1) === "/") {
+            return "" + this.protocol() + ":" + endPoint;
+          }
+
+          return "" + this.protocol() + "://" + location.host + "" + endPoint;
+        },
+        writable: true,
+        configurable: true
+      },
+      close: {
+        value: function close(callback, code, reason) {
+          if (this.conn) {
+            this.conn.onclose = function () {}; // noop
+            if (code) {
+              this.conn.close(code, reason || "");
+            } else {
+              this.conn.close();
+            }
+            this.conn = null;
+          }
+          callback && callback();
+        },
+        writable: true,
+        configurable: true
+      },
+      reconnect: {
+        value: function reconnect() {
+          var _this = this;
+          this.close(function () {
+            _this.conn = new _this.transport(_this.endPoint);
+            _this.conn.onopen = function () {
+              return _this.onConnOpen();
+            };
+            _this.conn.onerror = function (error) {
+              return _this.onConnError(error);
+            };
+            _this.conn.onmessage = function (event) {
+              return _this.onConnMessage(event);
+            };
+            _this.conn.onclose = function (event) {
+              return _this.onConnClose(event);
+            };
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      resetBufferTimer: {
+        value: function resetBufferTimer() {
+          var _this = this;
+          clearTimeout(this.sendBufferTimer);
+          this.sendBufferTimer = setTimeout(function () {
+            return _this.flushSendBuffer();
+          }, this.flushEveryMs);
+        },
+        writable: true,
+        configurable: true
+      },
+      log: {
+
+        // Logs the message. Override `this.logger` for specialized logging. noops by default
+        value: function log(msg) {
+          this.logger(msg);
+        },
+        writable: true,
+        configurable: true
+      },
+      onOpen: {
+
+        // Registers callbacks for connection state change events
+        //
+        // Examples
+        //
+        //    socket.onError (error) -> alert("An error occurred")
+        //
+        value: function onOpen(callback) {
+          this.stateChangeCallbacks.open.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onClose: {
+        value: function onClose(callback) {
+          this.stateChangeCallbacks.close.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onError: {
+        value: function onError(callback) {
+          this.stateChangeCallbacks.error.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onMessage: {
+        value: function onMessage(callback) {
+          this.stateChangeCallbacks.message.push(callback);
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnOpen: {
+        value: function onConnOpen() {
+          var _this = this;
+          clearInterval(this.reconnectTimer);
+          if (!this.transport.skipHeartbeat) {
+            this.heartbeatTimer = setInterval(function () {
+              return _this.sendHeartbeat();
+            }, this.heartbeatIntervalMs);
+          }
+          this.rejoinAll();
+          this.stateChangeCallbacks.open.forEach(function (callback) {
+            return callback();
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnClose: {
+        value: function onConnClose(event) {
+          var _this = this;
+          this.log("WS close:");
+          this.log(event);
+          clearInterval(this.reconnectTimer);
+          clearInterval(this.heartbeatTimer);
+          this.reconnectTimer = setInterval(function () {
+            return _this.reconnect();
+          }, this.reconnectAfterMs);
+          this.stateChangeCallbacks.close.forEach(function (callback) {
+            return callback(event);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnError: {
+        value: function onConnError(error) {
+          this.log("WS error:");
+          this.log(error);
+          this.stateChangeCallbacks.error.forEach(function (callback) {
+            return callback(error);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      connectionState: {
+        value: function connectionState() {
+          switch (this.conn && this.conn.readyState) {
+            case this.states.connecting:
+              return "connecting";
+            case this.states.open:
+              return "open";
+            case this.states.closing:
+              return "closing";
+            default:
+              return "closed";
+          }
+        },
+        writable: true,
+        configurable: true
+      },
+      isConnected: {
+        value: function isConnected() {
+          return this.connectionState() === "open";
+        },
+        writable: true,
+        configurable: true
+      },
+      rejoinAll: {
+        value: function rejoinAll() {
+          var _this = this;
+          this.channels.forEach(function (chan) {
+            return _this.rejoin(chan);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      rejoin: {
+        value: function rejoin(chan) {
+          chan.reset();
+          this.send({ topic: chan.topic, event: "join", payload: chan.message });
+          chan.callback(chan);
+        },
+        writable: true,
+        configurable: true
+      },
+      join: {
+        value: function join(topic, message, callback) {
+          var chan = new exports.Channel(topic, message, callback, this);
+          this.channels.push(chan);
+          if (this.isConnected()) {
+            this.rejoin(chan);
+          }
+        },
+        writable: true,
+        configurable: true
+      },
+      leave: {
+        value: function leave(topic) {
+          var message = arguments[1] === undefined ? {} : arguments[1];
+          this.send({ topic: topic, event: "leave", payload: message });
+          this.channels = this.channels.filter(function (c) {
+            return !c.isMember(topic);
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      send: {
+        value: function send(data) {
+          var _this = this;
+          var callback = function () {
+            return _this.conn.send(root.JSON.stringify(data));
+          };
+          if (this.isConnected()) {
+            callback();
+          } else {
+            this.sendBuffer.push(callback);
+          }
+        },
+        writable: true,
+        configurable: true
+      },
+      sendHeartbeat: {
+        value: function sendHeartbeat() {
+          this.send({ topic: "phoenix", event: "heartbeat", payload: {} });
+        },
+        writable: true,
+        configurable: true
+      },
+      flushSendBuffer: {
+        value: function flushSendBuffer() {
+          if (this.isConnected() && this.sendBuffer.length > 0) {
+            this.sendBuffer.forEach(function (callback) {
+              return callback();
+            });
+            this.sendBuffer = [];
+          }
+          this.resetBufferTimer();
+        },
+        writable: true,
+        configurable: true
+      },
+      onConnMessage: {
+        value: function onConnMessage(rawMessage) {
+          this.log("message received:");
+          this.log(rawMessage);
+          var _root$JSON$parse = root.JSON.parse(rawMessage.data);
+
+          var topic = _root$JSON$parse.topic;
+          var event = _root$JSON$parse.event;
+          var payload = _root$JSON$parse.payload;
+          this.channels.filter(function (chan) {
+            return chan.isMember(topic);
+          }).forEach(function (chan) {
+            return chan.trigger(event, payload);
+          });
+          this.stateChangeCallbacks.message.forEach(function (callback) {
+            callback(topic, event, payload);
+          });
+        },
+        writable: true,
+        configurable: true
+      }
+    });
+
+    return Socket;
+  })();
+
+
+  exports.LongPoller = (function () {
+    function LongPoller(endPoint) {
+      _classCallCheck(this, LongPoller);
+
+      this.retryInMs = 5000;
+      this.endPoint = null;
+      this.token = null;
+      this.sig = null;
+      this.skipHeartbeat = true;
+      this.onopen = function () {}; // noop
+      this.onerror = function () {}; // noop
+      this.onmessage = function () {}; // noop
+      this.onclose = function () {}; // noop
+      this.states = SOCKET_STATES;
+      this.upgradeEndpoint = this.normalizeEndpoint(endPoint);
+      this.pollEndpoint = this.upgradeEndpoint + (/\/$/.test(endPoint) ? "poll" : "/poll");
+      this.readyState = this.states.connecting;
+
+      this.poll();
+    }
+
+    _prototypeProperties(LongPoller, null, {
+      normalizeEndpoint: {
+        value: function normalizeEndpoint(endPoint) {
+          return endPoint.replace("ws://", "http://").replace("wss://", "https://");
+        },
+        writable: true,
+        configurable: true
+      },
+      endpointURL: {
+        value: function endpointURL() {
+          return this.pollEndpoint + ("?token=" + encodeURIComponent(this.token) + "&sig=" + encodeURIComponent(this.sig));
+        },
+        writable: true,
+        configurable: true
+      },
+      closeAndRetry: {
+        value: function closeAndRetry() {
+          this.close();
+          this.readyState = this.states.connecting;
+        },
+        writable: true,
+        configurable: true
+      },
+      ontimeout: {
+        value: function ontimeout() {
+          this.onerror("timeout");
+          this.closeAndRetry();
+        },
+        writable: true,
+        configurable: true
+      },
+      poll: {
+        value: function poll() {
+          var _this = this;
+          if (!(this.readyState === this.states.open || this.readyState === this.states.connecting)) {
+            return;
+          }
+
+          exports.Ajax.request("GET", this.endpointURL(), "application/json", null, this.ontimeout.bind(this), function (status, resp) {
+            if (resp && resp !== "") {
+              var _root$JSON$parse = root.JSON.parse(resp);
+
+              var token = _root$JSON$parse.token;
+              var sig = _root$JSON$parse.sig;
+              var messages = _root$JSON$parse.messages;
+              _this.token = token;
+              _this.sig = sig;
+            }
+            switch (status) {
+              case 200:
+                messages.forEach(function (msg) {
+                  return _this.onmessage({ data: root.JSON.stringify(msg) });
+                });
+                _this.poll();
+                break;
+              case 204:
+                _this.poll();
+                break;
+              case 410:
+                _this.readyState = _this.states.open;
+                _this.onopen();
+                _this.poll();
+                break;
+              case 0:
+              case 500:
+                _this.onerror();
+                _this.closeAndRetry();
+                break;
+              default:
+                throw "unhandled poll status " + status;
+            }
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      send: {
+        value: function send(body) {
+          var _this = this;
+          exports.Ajax.request("POST", this.endpointURL(), "application/json", body, this.onerror.bind(this, "timeout"), function (status, resp) {
+            if (status !== 200) {
+              _this.onerror(status);
+            }
+          });
+        },
+        writable: true,
+        configurable: true
+      },
+      close: {
+        value: function close(code, reason) {
+          this.readyState = this.states.closed;
+          this.onclose();
+        },
+        writable: true,
+        configurable: true
+      }
+    });
+
+    return LongPoller;
+  })();
+
+
+  exports.Ajax = {
+
+    states: { complete: 4 },
+
+    request: function (method, endPoint, accept, body, ontimeout, callback) {
+      var _this = this;
+      var req = root.XMLHttpRequest ? new root.XMLHttpRequest() : // IE7+, Firefox, Chrome, Opera, Safari
+      new root.ActiveXObject("Microsoft.XMLHTTP"); // IE6, IE5
+      req.open(method, endPoint, true);
+      req.setRequestHeader("Content-type", accept);
+      req.onerror = function () {
+        callback && callback(500, null);
+      };
+      req.onreadystatechange = function () {
+        if (req.readyState === _this.states.complete && callback) {
+          callback(req.status, req.responseText);
+        }
+      };
+      if (ontimeout) {
+        req.ontimeout = ontimeout;
+      }
+
+      req.send(body);
+    }
+  };
+});

+ 15 - 0
frameworks/Elixir/phoenix/setup.sh

@@ -0,0 +1,15 @@
+#!/bin/bash
+
+source $IROOT/elixir.installed
+
+sed -i 's|db_host: "localhost",|db_host: "${DBHOST}",|g' config/config.exs
+
+rm -rf _build deps
+
+mix local.hex --force
+mix local.rebar --force
+mix deps.get --force
+
+MIX_ENV=prod mix compile.protocols --force
+MIX_ENV=prod elixir --detached -pa _build/$MIX_ENV/consolidated -S mix phoenix.server
+

+ 7 - 0
frameworks/Elixir/phoenix/test/hello_test.exs

@@ -0,0 +1,7 @@
+defmodule HelloTest do
+  use ExUnit.Case
+
+  test "the truth" do
+    assert 1 + 1 == 2
+  end
+end

+ 1 - 0
frameworks/Elixir/phoenix/test/test_helper.exs

@@ -0,0 +1 @@
+ExUnit.start

+ 40 - 0
frameworks/Elixir/phoenix/web/controllers/page_controller.ex

@@ -0,0 +1,40 @@
+defmodule Hello.PageController do
+  use Phoenix.Controller
+
+  plug :action
+
+  def index(conn, _params) do
+    json conn, %{
+      "TE Benchmarks\n" => "Started",
+      "DBHOST" => System.get_env("DBHOST"),
+      "DBPORT" => System.get_env("DBPORT"),
+    }
+  end
+
+  # avoid namespace collision
+  def _json(conn, _params) do
+    json conn, %{message: "Hello, world!"}
+  end
+
+  def db(conn, _params) do
+    :random.seed(:erlang.now)
+    id = :random.uniform(10000)
+    text conn, "TE Benchmarks\n"
+  end
+
+  def queries(conn, _params) do
+    text conn, "TE Benchmarks\n"
+  end
+
+  def fortunes(conn, _params) do
+    text conn, "TE Benchmarks\n"
+  end
+
+  def updates(conn, _params) do
+    text conn, "TE Benchmarks\n"
+  end
+
+  def plaintext(conn, _params) do
+    text conn, "Hello, world!"
+  end
+end

+ 11 - 0
frameworks/Elixir/phoenix/web/models/repo.exs

@@ -0,0 +1,11 @@
+defmodule Hello.Repo do
+  use Ecto.Repo, adapter: Ecto.Adapters.Postgres
+
+  def conf do
+    parse_url "ecto://username:password@host/database_name"
+  end
+
+  def priv do
+    app_dir(:hello, "priv/repo")
+  end
+end

+ 7 - 0
frameworks/Elixir/phoenix/web/models/world.exs

@@ -0,0 +1,7 @@
+defmodule Hello.User do
+  use Ecto.Model
+
+  schema "world" do
+    field :randomNumber, :integer
+  end
+end

+ 31 - 0
frameworks/Elixir/phoenix/web/router.ex

@@ -0,0 +1,31 @@
+defmodule Hello.Router do
+  use Phoenix.Router
+
+  pipeline :browser do
+    plug :accepts, ~w(html)
+    plug :fetch_session
+    plug :fetch_flash
+    plug :protect_from_forgery
+  end
+
+  pipeline :api do
+    plug :accepts, ~w(json)
+  end
+
+  scope "/", Hello do
+    pipe_through :browser # Use the default browser stack
+
+    get "/json", PageController, :_json
+    get "/db", PageController, :db
+    get "/queries", PageController, :queries
+    get "/fortunes", PageController, :fortunes
+    get "/updates", PageController, :updates
+    get "/plaintext", PageController, :plaintext
+    get "/", PageController, :index
+  end
+
+  # Other scopes may use custom stacks.
+  # scope "/api", Hello do
+  #   pipe_through :api
+  # end
+end

+ 31 - 0
frameworks/Elixir/phoenix/web/templates/layout/application.html.eex

@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="description" content="">
+    <meta name="author" content="">
+
+    <title>Hello Phoenix!</title>
+    <link rel="stylesheet" href="/css/phoenix.css">
+  </head>
+
+  <body>
+    <div class="container">
+      <div class="header">
+        <ul class="nav nav-pills pull-right">
+          <li><a href="http://www.phoenixframework.org/docs">Get Started</a></li>
+        </ul>
+        <span class="logo"></span>
+      </div>
+
+      <%= @inner %>
+
+      <div class="footer">
+        <p><a href="http://phoenixframework.org">phoenixframework.org</a></p>
+      </div>
+
+    </div> <!-- /container -->
+  </body>
+</html>

+ 1 - 0
frameworks/Elixir/phoenix/web/templates/page/error.html.eex

@@ -0,0 +1 @@
+Something went wrong

+ 34 - 0
frameworks/Elixir/phoenix/web/templates/page/index.html.eex

@@ -0,0 +1,34 @@
+<div class="jumbotron">
+  <h2>Welcome to Phoenix!</h2>
+  <p class="lead">Phoenix is an Elixir Web Framework targeting full-featured, fault tolerant applications with realtime functionality.</p>
+</div>
+
+<div class="row marketing">
+  <div class="col-lg-6">
+    <h4>Resources</h4>
+    <ul>
+      <li>
+        <a href="http://hexdocs.pm/phoenix">Docs</a>
+      </li>
+      <li>
+        <a href="https://github.com/phoenixframework/phoenix">Source</a>
+      </li>
+    </ul>
+  </div>
+
+  <div class="col-lg-6">
+    <h4>Help</h4>
+    <ul>
+      <li>
+        <a href="https://github.com/phoenixframework/phoenix/issues?state=open">Issues</a>
+      </li>
+      <li>
+        <a href="irc://irc.freenode.net/elixir-lang">#elixir-lang on freenode IRC</a>
+      </li>
+      <li>
+        <a href="https://twitter.com/chris_mccord">@chris_mccord</a>
+      </li>
+    </ul>
+  </div>
+</div>
+

+ 1 - 0
frameworks/Elixir/phoenix/web/templates/page/not_found.html.eex

@@ -0,0 +1 @@
+The page you are looking for does not exist

+ 17 - 0
frameworks/Elixir/phoenix/web/view.ex

@@ -0,0 +1,17 @@
+defmodule Hello.View do
+  use Phoenix.View, root: "web/templates"
+
+  # The quoted expression returned by this block is applied
+  # to this module and all other views that use this module.
+  using do
+    quote do
+      # Import common functionality
+      import Hello.Router.Helpers
+
+      # Use Phoenix.HTML to import all HTML functions (forms, tags, etc)
+      use Phoenix.HTML
+    end
+  end
+
+  # Functions defined here are available to all other views/templates
+end

+ 16 - 0
frameworks/Elixir/phoenix/web/views/error_view.ex

@@ -0,0 +1,16 @@
+defmodule Hello.ErrorView do
+  use Hello.View
+
+  def render("404.html", _assigns) do
+    "Page not found - 404"
+  end
+
+  def render("500.html", _assigns) do
+    "Server internal error - 500"
+  end
+
+  # Render all other templates as 500
+  def render(_, assigns) do
+    render "500.html", assigns
+  end
+end

+ 3 - 0
frameworks/Elixir/phoenix/web/views/layout_view.ex

@@ -0,0 +1,3 @@
+defmodule Hello.LayoutView do
+  use Hello.View
+end

+ 3 - 0
frameworks/Elixir/phoenix/web/views/page_view.ex

@@ -0,0 +1,3 @@
+defmodule Hello.PageView do
+  use Hello.View
+end

+ 1 - 2
frameworks/Erlang/cowboy/.gitignore

@@ -1,5 +1,4 @@
 erl_crash.dump
 erl_crash.dump
-__init__.py
 deps
 deps
 ebin
 ebin
-*.deb
+.rebar

+ 1 - 1
frameworks/Erlang/cowboy/benchmark_config.json

@@ -2,7 +2,7 @@
   "framework": "cowboy",
   "framework": "cowboy",
   "tests": [{
   "tests": [{
     "default": {
     "default": {
-      "setup_file": "setup_erlang",
+      "setup_file": "setup",
       "json_url": "/json",
       "json_url": "/json",
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/query?queries=",
       "query_url": "/query?queries=",

+ 1 - 1
frameworks/Erlang/cowboy/setup_erlang.sh → frameworks/Erlang/cowboy/setup.sh

@@ -7,4 +7,4 @@ fw_depends erlang rebar
 rm -rf deps/*
 rm -rf deps/*
 rebar get-deps
 rebar get-deps
 rebar compile
 rebar compile
-erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached
+erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached

+ 1 - 2
frameworks/Erlang/elli/.gitignore

@@ -1,5 +1,4 @@
 erl_crash.dump
 erl_crash.dump
-__init__.py
 deps
 deps
 ebin
 ebin
-*.deb
+.rebar

+ 1 - 1
frameworks/Erlang/elli/benchmark_config.json

@@ -2,7 +2,7 @@
   "framework": "elli",
   "framework": "elli",
   "tests": [{
   "tests": [{
     "default": {
     "default": {
-      "setup_file": "setup_erlang",
+      "setup_file": "setup",
       "json_url": "/json",
       "json_url": "/json",
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/query?queries=",
       "query_url": "/query?queries=",

+ 2 - 2
frameworks/Erlang/elli/rebar.config

@@ -1,6 +1,6 @@
 {deps,
 {deps,
  [
  [
-  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.8.5"}}},
+  {jiffy, ".*", {git, "https://github.com/davisp/jiffy.git", {tag, "0.13.3"}}},
   {emysql, ".*", {git, "https://github.com/Eonblast/Emysql.git"}},
   {emysql, ".*", {git, "https://github.com/Eonblast/Emysql.git"}},
-  {elli, "", {git, "git://github.com/knutin/elli.git"}}
+  {elli, "", {git, "git://github.com/knutin/elli.git", {tag, "v1.0.3"}}}
  ]}.
  ]}.

+ 1 - 0
frameworks/Erlang/elli/setup_erlang.sh → frameworks/Erlang/elli/setup.sh

@@ -7,4 +7,5 @@ fw_depends erlang rebar
 rm -rf deps/*
 rm -rf deps/*
 rebar get-deps
 rebar get-deps
 rebar compile
 rebar compile
+
 erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached
 erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached

+ 11 - 5
frameworks/Haskell/wai/bench/wai.hs

@@ -5,8 +5,8 @@ import Control.Concurrent (runInUnboundThread)
 import Data.Aeson ((.=), object, encode)
 import Data.Aeson ((.=), object, encode)
 import qualified Data.ByteString.Lazy as L
 import qualified Data.ByteString.Lazy as L
 import Data.Text (Text)
 import Data.Text (Text)
-import Network.HTTP.Types (status200)
-import Network.Wai (responseBuilder)
+import Network.HTTP.Types (status200, status404)
+import Network.Wai (responseBuilder, rawPathInfo)
 import qualified Network.Wai.Handler.Warp as W
 import qualified Network.Wai.Handler.Warp as W
 
 
 main :: IO ()
 main :: IO ()
@@ -15,10 +15,16 @@ main =
   where
   where
     settings = W.setPort 8000
     settings = W.setPort 8000
              $ W.setOnException (\_ _ -> return ()) W.defaultSettings
              $ W.setOnException (\_ _ -> return ()) W.defaultSettings
-    app _ respond = respond response
-    !response = responseBuilder status200 ct json
-    ct = [("Content-Type", "application/json")]
+    app request respond = case rawPathInfo request of
+        "/json" -> respond responseJson
+        "/plaintext" -> respond responsePlaintext
+        _ -> respond $ responseBuilder status404 [] ""
+    !responseJson = responseBuilder status200 ctJson json
+    ctJson = [("Content-Type", "application/json")]
     !json = copyByteString
     !json = copyByteString
           $ L.toStrict
           $ L.toStrict
           $ encode
           $ encode
           $ object ["message" .= ("Hello, World!" :: Text)]
           $ object ["message" .= ("Hello, World!" :: Text)]
+    !responsePlaintext = responseBuilder status200 ctPlaintext plaintext
+    ctPlaintext = [("Content-type", "text/plain")]
+    plaintext = "Hello, World!"

+ 1 - 0
frameworks/Haskell/wai/benchmark_config.json

@@ -4,6 +4,7 @@
     "default": {
     "default": {
       "setup_file": "setup",
       "setup_file": "setup",
       "json_url": "/json",
       "json_url": "/json",
+      "plaintext_url": "/plaintext",
       "port": 8000,
       "port": 8000,
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Platform",
       "classification": "Platform",

+ 2 - 0
frameworks/Haskell/yesod/bench/bench.cabal

@@ -37,6 +37,8 @@ executable         bench
                  , http-types
                  , http-types
                  , aeson
                  , aeson
                  , blaze-builder
                  , blaze-builder
+                 , blaze-html
                  , bytestring                    >= 0.10
                  , bytestring                    >= 0.10
                  , resource-pool
                  , resource-pool
                  , resourcet
                  , resourcet
+                 , shakespeare

+ 119 - 37
frameworks/Haskell/yesod/bench/src/yesod.hs

@@ -14,34 +14,39 @@
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 module Main (main, resourcesApp, Widget, WorldId) where
 module Main (main, resourcesApp, Widget, WorldId) where
 import           Blaze.ByteString.Builder
 import           Blaze.ByteString.Builder
-import           Control.Concurrent           (runInUnboundThread)
-import           Control.Monad                (replicateM)
-import           Control.Monad.Logger         (runNoLoggingT)
-import           Control.Monad.Primitive      (PrimState)
-import           Control.Monad.Reader         (ReaderT)
-import           Control.Monad.Trans.Resource (InternalState)
-import           Data.Aeson                   (encode)
-import qualified Data.ByteString.Lazy         as L
-import           Data.Conduit.Pool            (Pool, createPool)
-import           Data.Int                     (Int64)
-import           Data.IORef                   (newIORef)
-import           Data.Pool                    (withResource)
-import           Data.Text                    (Text)
-import           Database.MongoDB             (Field ((:=)), (=:))
-import qualified Database.MongoDB             as Mongo
-import           Database.Persist             (Key, PersistEntity,
-                                               PersistEntityBackend,
-                                               PersistStore, get)
-import qualified Database.Persist.MySQL       as My
-import           Database.Persist.TH          (mkPersist, mpsGeneric,
-                                               persistLowerCase, sqlSettings)
-import           Network                      (PortID (PortNumber))
+import           Control.Applicative           (liftA2)
+import           Control.Concurrent            (runInUnboundThread)
+import           Control.Monad                 (replicateM)
+import           Control.Monad.Logger          (runNoLoggingT)
+import           Control.Monad.Primitive       (PrimState)
+import           Control.Monad.Reader          (ReaderT)
+import           Control.Monad.Trans.Resource  (InternalState)
+import           Data.Aeson                    (encode)
+import qualified Data.ByteString.Lazy          as L
+import           Data.Conduit.Pool             (Pool, createPool)
+import           Data.Int                      (Int64)
+import           Data.IORef                    (newIORef)
+import           Data.Function                 (on)
+import           Data.List                     (sortBy)
+import           Data.Pool                     (withResource)
+import           Data.Text                     (Text)
+import           Database.MongoDB              (Field ((:=)), (=:))
+import qualified Database.MongoDB              as Mongo
+import           Database.Persist              (Key, PersistEntity,
+                                                PersistEntityBackend,
+                                                PersistStore, get, update,
+                                                (=.))
+import qualified Database.Persist.MySQL        as My
+import           Database.Persist.TH           (mkPersist, mpsGeneric,
+                                                persistLowerCase, sqlSettings)
+import           Network                       (PortID (PortNumber))
 import           Network.HTTP.Types
 import           Network.HTTP.Types
 import           Network.Wai
 import           Network.Wai
-import qualified Network.Wai.Handler.Warp     as Warp
-import           System.Environment           (getArgs)
-import           System.IO.Unsafe             (unsafePerformIO)
-import qualified System.Random.MWC            as R
+import qualified Network.Wai.Handler.Warp      as Warp
+import           System.Environment            (getArgs)
+import           System.IO.Unsafe              (unsafePerformIO)
+import qualified System.Random.MWC             as R
+import           Text.Blaze.Html.Renderer.Utf8 (renderHtmlBuilder)
 import           Yesod.Core
 import           Yesod.Core
 
 
 mkPersist sqlSettings { mpsGeneric = True } [persistLowerCase|
 mkPersist sqlSettings { mpsGeneric = True } [persistLowerCase|
@@ -49,6 +54,11 @@ World sql=World
     randomNumber Int sql=randomNumber
     randomNumber Int sql=randomNumber
 |]
 |]
 
 
+mkPersist sqlSettings { mpsGeneric = True } [persistLowerCase|
+Fortune sql=Fortune
+    message Text sql=message
+|]
+
 data App = App
 data App = App
     { appGen      :: !(R.Gen (PrimState IO))
     { appGen      :: !(R.Gen (PrimState IO))
     , mySqlPool   :: !(Pool My.SqlBackend)
     , mySqlPool   :: !(Pool My.SqlBackend)
@@ -62,11 +72,18 @@ mkYesod "App" [parseRoutes|
 
 
 /db                 DbR       GET
 /db                 DbR       GET
 /dbs/#Int           DbsR      GET
 /dbs/#Int           DbsR      GET
-!/dbs/#Text         DbsRdefault  GET
+!/dbs/#Text         DbsDefaultR  GET
 
 
 /mongo/raw/db       MongoRawDbR  GET
 /mongo/raw/db       MongoRawDbR  GET
 /mongo/raw/dbs/#Int MongoRawDbsR GET
 /mongo/raw/dbs/#Int MongoRawDbsR GET
-!/mongo/raw/dbs/#Text MongoRawDbsRdefault GET
+!/mongo/raw/dbs/#Text MongoRawDbsDefaultR GET
+
+/updates/#Int       UpdatesR     GET
+!/updates/#Text     UpdatesDefaultR GET
+
+/fortunes           FortunesR    GET
+
+/plaintext          PlaintextR   GET
 |]
 |]
 
 
 fakeInternalState :: InternalState
 fakeInternalState :: InternalState
@@ -107,28 +124,42 @@ getMongoRawDbR = getDb rawMongoIntQuery
 getDbsR :: Int -> Handler Value
 getDbsR :: Int -> Handler Value
 getDbsR cnt = do
 getDbsR cnt = do
     App {..} <- getYesod
     App {..} <- getYesod
-    multiRandomHandler (intQuery runMySQL My.toSqlKey) cnt'
+    multiRandomHandler randomNumber (intQuery runMySQL My.toSqlKey) cnt'
   where
   where
     cnt' | cnt < 1 = 1
     cnt' | cnt < 1 = 1
          | cnt > 500 = 500
          | cnt > 500 = 500
          | otherwise = cnt
          | otherwise = cnt
 
 
-getDbsRdefault :: Text -> Handler Value
-getDbsRdefault _ = getDbsR 1
+getDbsDefaultR :: Text -> Handler Value
+getDbsDefaultR _ = getDbsR 1
 
 
 getMongoRawDbsR :: Int -> Handler Value
 getMongoRawDbsR :: Int -> Handler Value
-getMongoRawDbsR cnt = multiRandomHandler rawMongoIntQuery cnt'
+getMongoRawDbsR cnt = multiRandomHandler randomNumber rawMongoIntQuery cnt'
   where
   where
     cnt' | cnt < 1 = 1
     cnt' | cnt < 1 = 1
          | cnt > 500 = 500
          | cnt > 500 = 500
          | otherwise = cnt
          | otherwise = cnt
 
 
-getMongoRawDbsRdefault :: Text -> Handler Value
-getMongoRawDbsRdefault _ = getMongoRawDbsR 1
+getMongoRawDbsDefaultR :: Text -> Handler Value
+getMongoRawDbsDefaultR _ = getMongoRawDbsR 1
+
+getUpdatesR :: Int -> Handler Value
+getUpdatesR cnt = multiRandomHandler randomPair go cnt'
+  where
+    cnt' | cnt < 1 = 1
+         | cnt > 500 = 500
+         | otherwise = cnt
+    go = uncurry (intUpdate runMySQL My.toSqlKey)
+
+getUpdatesDefaultR :: Text -> Handler Value
+getUpdatesDefaultR _ = getUpdatesR 1
 
 
 randomNumber :: R.Gen (PrimState IO) -> IO Int64
 randomNumber :: R.Gen (PrimState IO) -> IO Int64
 randomNumber appGen = R.uniformR (1, 10000) appGen
 randomNumber appGen = R.uniformR (1, 10000) appGen
 
 
+randomPair :: R.Gen (PrimState IO) -> IO (Int64, Int64)
+randomPair appGen = liftA2 (,) (randomNumber appGen) (randomNumber appGen)
+
 getDb :: (Int64 -> Handler Value) -> Handler Value
 getDb :: (Int64 -> Handler Value) -> Handler Value
 getDb query = do
 getDb query = do
     app <- getYesod
     app <- getYesod
@@ -172,13 +203,28 @@ rawMongoIntQuery i = do
     Just x <- runMongoDB $ Mongo.findOne (Mongo.select ["id" =: i] "World")
     Just x <- runMongoDB $ Mongo.findOne (Mongo.select ["id" =: i] "World")
     return $ documentToJson x
     return $ documentToJson x
 
 
+intUpdate :: (Functor m, Monad m, MonadIO m
+             , PersistStore backend) =>
+             (ReaderT backend m (Maybe (WorldGeneric backend))
+                -> m (Maybe (WorldGeneric backend)))
+             -> (Int64 -> Key (WorldGeneric backend))
+             -> Int64 -> Int64 -> m Value
+intUpdate db toKey i v = do
+    Just x <- db $ get k
+    _ <- db $ fmap (const Nothing) $
+             update k [WorldRandomNumber =. fromIntegral v]
+    return $ object ["id" .= i, "randomNumber" .= v]
+  where
+    k = toKey i
+
 multiRandomHandler :: ToJSON a
 multiRandomHandler :: ToJSON a
-                   => (Int64 -> Handler a)
+                   => (R.Gen (PrimState IO) -> IO b)
+                   -> (b -> Handler a)
                    -> Int
                    -> Int
                    -> Handler Value
                    -> Handler Value
-multiRandomHandler operation cnt = do
+multiRandomHandler rand operation cnt = do
     App {..} <- getYesod
     App {..} <- getYesod
-    nums <- liftIO $ replicateM cnt (randomNumber appGen)
+    nums <- liftIO $ replicateM cnt (rand appGen)
     return . array =<< mapM operation nums
     return . array =<< mapM operation nums
 
 
 documentToJson :: [Field] -> Value
 documentToJson :: [Field] -> Value
@@ -195,6 +241,42 @@ instance ToJSON Mongo.Value where
   toJSON (Mongo.Doc d)   = documentToJson d
   toJSON (Mongo.Doc d)   = documentToJson d
   toJSON s = error $ "no convert for: " ++ show s
   toJSON s = error $ "no convert for: " ++ show s
 
 
+getFortunesR :: Handler ()
+getFortunesR = do
+    es <- runMySQL $ My.selectList [] []
+    sendWaiResponse
+        $ responseBuilder status200 [("Content-type", typeHtml)]
+        $ fortuneTemplate (messages es)
+  where
+    messages es = sortBy (compare `on` snd)
+        ((0, "Additional fortune added at request time.") : map stripEntity es)
+    stripEntity e =
+        (My.fromSqlKey (My.entityKey e), fortuneMessage . My.entityVal $ e)
+
+getPlaintextR :: Handler ()
+getPlaintextR = sendWaiResponse
+              $ responseBuilder
+                status200
+                [("Content-Type", typePlain)]
+              $ copyByteString "Hello, World!"
+
+fortuneTemplate :: [(Int64, Text)] -> Builder
+fortuneTemplate messages = renderHtmlBuilder $ [shamlet|
+$doctype 5
+<html>
+    <head>
+        <title>Fortunes
+    <body>
+        <table>
+            <tr>
+                <th>id
+                <th>message
+            $forall message <- messages
+                <tr>
+                    <td>#{fst message}
+                    <td>#{snd message}
+|]
+
 
 
 
 
 main :: IO ()
 main :: IO ()

+ 3 - 0
frameworks/Haskell/yesod/benchmark_config.json

@@ -6,6 +6,9 @@
       "json_url": "/json",
       "json_url": "/json",
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/dbs/",
       "query_url": "/dbs/",
+      "update_url": "/updates/",
+      "fortune_url": "/fortunes",
+      "plaintext_url": "/plaintext",
       "port": 8000,
       "port": 8000,
       "approach": "Realistic",
       "approach": "Realistic",
       "classification": "Fullstack",
       "classification": "Fullstack",

+ 32 - 6
frameworks/Java/README.md

@@ -1,7 +1,20 @@
-# Installation and Bash Configuration
+# Java Frameworks
 
 
-In order to declare that your framework requires Java, you should have an `install.sh`
-that contains at least
+The information below contains information specific to Java. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
+
+## Infrastructure Software Versions
+
+* Java 7
+* Java 8
+
+## Adding a New Java Framework
+
+### Installation and Bash Configuration
+
+In order to declare that your framework requires Java, you 
+should have an `install.sh` that contains at least
 
 
     #!/bin/bash
     #!/bin/bash
 
 
@@ -9,7 +22,20 @@ that contains at least
 
 
 This installs the OpenJDK 7 JVM.
 This installs the OpenJDK 7 JVM.
 
 
-Frameworks can also choose to install Oracle Java 8 JVM by declaring a dependency on "java8"
-instead of java. In order to use Java 8 JVM frameworks need to add the following line in their "setup.sh" file:
+Frameworks can also choose to install Oracle Java 8 JVM by 
+declaring a dependency on "java8" instead of java. In order 
+to use Java 8 JVM frameworks need to add the following line 
+in their "setup.sh" file:
+
+    export JAVA_HOME=/opt/java8
+
+## Get Help
+
+### Java Experts
+
+_There aren't any experts listed, yet. If you're an expert, 
+add yourself!_
+
+### Interesting Links
 
 
-export JAVA_HOME=/opt/java8
+* [Surprise! Java is fastest for server-side Web apps](http://www.infoworld.com/article/2609675/java/surprise--java-is-fastest-for-server-side-web-apps.html)

+ 30 - 8
frameworks/PHP/README.md

@@ -1,10 +1,20 @@
-# PHP Version
+# PHP Frameworks
+
+The information below contains information specific to PHP. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
+
+## Infrastructre Software Versions
+
+### PHP Version
 
 
 [Currently this toolset runs PHP 5.5.17](https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/toolset/setup/linux/languages/php.sh). At the moment all PHP-based frameworks use the 
 [Currently this toolset runs PHP 5.5.17](https://github.com/TechEmpower/FrameworkBenchmarks/blob/master/toolset/setup/linux/languages/php.sh). At the moment all PHP-based frameworks use the 
 same PHP version, but we are open to receiving a pull request
 same PHP version, but we are open to receiving a pull request
 that enables supporting multiple versions. 
 that enables supporting multiple versions. 
 
 
-# PHP Acceleration and Caching
+## Adding New PHP-based Frameworks
+
+### PHP Acceleration and Caching
 
 
 Caching the output of the PHP bytecode compiler is expressly 
 Caching the output of the PHP bytecode compiler is expressly 
 allowed by this benchmark. As we use PHP 5.5, which comes 
 allowed by this benchmark. As we use PHP 5.5, which comes 
@@ -43,7 +53,7 @@ easier to use systems such as APCu.
 
 
 Ask if you are not certain.
 Ask if you are not certain.
 
 
-# Adding New PHP-based Frameworks
+## Install.sh and Setup.sh Files
 
 
 Most PHP frameworks use `fw_depends php nginx composer` in their `install.sh` file, 
 Most PHP frameworks use `fw_depends php nginx composer` in their `install.sh` file, 
 which installs PHP, Nginx, and Composer automatically. They then create a `setup.sh`
 which installs PHP, Nginx, and Composer automatically. They then create a `setup.sh`
@@ -75,7 +85,7 @@ When using `php`, `php-fpm`, or other binaries, always use the full path
 to the binary, e.g. instead of `php <command>`, 
 to the binary, e.g. instead of `php <command>`, 
 use `/home/foo/FrameworkBenchmarks/installs/php-5.5.17/bin/php <your command>`. 
 use `/home/foo/FrameworkBenchmarks/installs/php-5.5.17/bin/php <your command>`. 
 
 
-# Dependency Management Using Composer
+### Dependency Management Using Composer
 
 
 Many PHP apps use [Composer](https://getcomposer.org/) for dependency management, 
 Many PHP apps use [Composer](https://getcomposer.org/) for dependency management, 
 which greatly simplifies downloading the framework, loading the framework, and 
 which greatly simplifies downloading the framework, loading the framework, and 
@@ -90,7 +100,7 @@ The lock file is a fully-defined file generated by composer 1) reading your JSON
 dependencies 3) downloading a lot of data from Github. Without this lock file, composer takes 2-3x 
 dependencies 3) downloading a lot of data from Github. Without this lock file, composer takes 2-3x 
 longer to run, and it can even halt and require user input
 longer to run, and it can even halt and require user input
 
 
-## Setting up Composer
+#### Setting up Composer
 
 
 Add a `composer.json` file to your framework's root folder, e.g. `php-fuel/composer.json`. 
 Add a `composer.json` file to your framework's root folder, e.g. `php-fuel/composer.json`. 
 Ensure your `install.sh` lists composer as a dependency, and uses `composer.phar` to 
 Ensure your `install.sh` lists composer as a dependency, and uses `composer.phar` to 
@@ -109,7 +119,7 @@ e.g. `php-fuel/vendor` that contains all dependencies. Update your PHP scripts
 to either directly reference files inside of vendor, or use the `vendor/autoload.php`
 to either directly reference files inside of vendor, or use the `vendor/autoload.php`
 file. 
 file. 
 
 
-## Generating composer.lock file
+#### Generating composer.lock file
 
 
 Composer uses Github *a lot*, enough so that it is common for it to exceed the 
 Composer uses Github *a lot*, enough so that it is common for it to exceed the 
 API limit and cause infinite hangs or installation failures. To avoid this, it 
 API limit and cause infinite hangs or installation failures. To avoid this, it 
@@ -145,7 +155,7 @@ queries as they are shown. Use these steps
     # Add the lock file to this repository
     # Add the lock file to this repository
     git add -f composer.lock
     git add -f composer.lock
 
 
-## Updating Composer setup
+#### Updating Composer setup
 
 
 If you update `composer.json`, you need to regenerate the lock
 If you update `composer.json`, you need to regenerate the lock
 file. If you forget to do this, you will see this error message 
 file. If you forget to do this, you will see this error message 
@@ -153,8 +163,20 @@ when running:
 
 
     Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
     Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
 
 
-# Debugging PHP Frameworks
+### Debugging PHP Frameworks
 
 
 The first stop for HTTP 500 errors is to enable stack traces. 
 The first stop for HTTP 500 errors is to enable stack traces. 
 Update `config/php-fpm.conf` to include `php_flag[display_errors] = on`. 
 Update `config/php-fpm.conf` to include `php_flag[display_errors] = on`. 
 If you don't use php-fpm, update the `config/php.ini`
 If you don't use php-fpm, update the `config/php.ini`
+
+## Get Help
+
+### PHP Experts
+
+_There aren't any PHP experts listed, yet. If you're an expert, 
+add yourself!_
+
+### Resources & Interesting Links
+
+_If you find some interesting links related to the PHP tests, 
+add them here._

+ 1 - 4
frameworks/PHP/hhvm/once.php.inc

@@ -5,7 +5,7 @@ class Benchmark {
 
 
     public function setup_db($need_utf8 = true)
     public function setup_db($need_utf8 = true)
     {
     {
-        $attrs     = array(PDO::ATTR_PERSISTENT => true);
+        $attrs     = array(PDO::ATTR_PERSISTENT => false);
         // hhvm doesn't support charset=utf8 in the DSN yet
         // hhvm doesn't support charset=utf8 in the DSN yet
         // See https://github.com/facebook/hhvm/issues/1309
         // See https://github.com/facebook/hhvm/issues/1309
         if ($need_utf8) {
         if ($need_utf8) {
@@ -30,8 +30,6 @@ class Benchmark {
     {
     {
         $this->setup_db();
         $this->setup_db();
 
 
-        // Create an array with the response string.
-        $arr = array();
         $id = mt_rand(1, 10000);
         $id = mt_rand(1, 10000);
 
 
         // Define query
         // Define query
@@ -41,7 +39,6 @@ class Benchmark {
 
 
         // Store result in array.
         // Store result in array.
         $arr = array('id' => $id, 'randomNumber' => $statement->fetchColumn());
         $arr = array('id' => $id, 'randomNumber' => $statement->fetchColumn());
-        $id = mt_rand(1, 10000);
 
 
         // Send the required parameters
         // Send the required parameters
         header('Content-Type: application/json');
         header('Content-Type: application/json');

+ 2 - 0
frameworks/PHP/limonade/.gitignore

@@ -0,0 +1,2 @@
+vendor
+deploy/php-fpm.pid

+ 26 - 0
frameworks/PHP/limonade/benchmark_config.json

@@ -0,0 +1,26 @@
+{
+  "framework": "limonade",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "query_url": "/queries/",
+      "fortune_url": "/fortune",
+      "update_url": "/updates/",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "Limonade",
+      "language": "PHP",
+      "orm": "Full",
+      "platform": "PHP-FPM",
+      "webserver": "nginx",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Limonade"
+    }
+  }]
+}

+ 7 - 0
frameworks/PHP/limonade/composer.json

@@ -0,0 +1,7 @@
+{
+   "require": {
+   	"sofadesign/limonade" : "dev-master",
+   	"php-activerecord/php-activerecord" : "1.1.2"
+   }
+}
+

+ 46 - 0
frameworks/PHP/limonade/deploy/nginx.conf

@@ -0,0 +1,46 @@
+worker_processes  8;
+
+error_log stderr error;
+
+events {
+    worker_connections  1024;
+}
+
+http {
+    include       /usr/local/nginx/conf/mime.types;
+    default_type  application/octet-stream;
+    access_log off;
+    sendfile        on;
+    keepalive_timeout  65;
+
+    upstream fastcgi_backend {
+        server 127.0.0.1:9001;
+        keepalive 32;
+    }
+
+    server {
+        listen       8080;
+        server_name  localhost;
+
+        root /home/ubuntu/FrameworkBenchmarks/limonade/;
+        index  index.php;
+
+        location / {
+            try_files $uri $uri/ @rewrite;
+        }
+
+        location @rewrite {
+            rewrite ^/(.*)$ /index.php?u=$1&$args;
+        }
+
+        location ~ \.php$ {
+            try_files $uri =404;
+            fastcgi_pass   fastcgi_backend;
+            fastcgi_keep_conn on;
+            fastcgi_index  index.php;
+            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
+            include        /usr/local/nginx/conf/fastcgi_params;
+        }
+
+    }
+}

+ 105 - 0
frameworks/PHP/limonade/index.php

@@ -0,0 +1,105 @@
+<?php
+require_once "vendor/sofadesign/limonade/lib/limonade.php";
+require_once "vendor/php-activerecord/php-activerecord/ActiveRecord.php";
+
+function configure() {
+	$cfg = ActiveRecord\Config::instance();
+	$cfg->set_model_directory("models");
+	$cfg->set_connections(array(
+		"development" => "mysql://benchmarkdbuser:benchmarkdbpass@localhost/hello_world?charset=utf8"));
+
+option("bas_url", "/");
+}
+
+dispatch("/plaintext", "plaintext");
+function plaintext() {
+	header('Content-Type: text/plain; charset=utf-8');
+	return txt("Hello, World!");
+}
+
+dispatch("/json", "jsonHandler");
+function jsonHandler() {
+	header('Content-Type: application/json; charset=utf-8');
+	$arr = array("message" => "Hello, World!");
+	return json($arr);
+}
+
+dispatch("/db", "db");
+function db() {
+	$id = mt_rand(1, 10000);
+	$test = World::find($id);
+	return json($test->to_array());
+}
+
+dispatch("/queries/:queries", "queries");
+function queries() {
+	header('Content-Type: application/json; charset=utf-8');
+	$query_count = params("queries");
+	if ($query_count < 1) {
+		$query_count = 1;
+	}
+	if ($query_count > 500) {
+		$query_count = 500;
+	}
+	
+	$worlds = array();
+
+	for ($i = 0; $i < $query_count; $i++) {
+		$id = mt_rand(1, 10000);
+		$world = World::find($id);
+		$worlds[] = $world->to_array();
+	}
+
+	return json($worlds);
+
+}
+
+function update_world(&$world, $key) {
+	$world["randomnumber"] = mt_rand(1, 10000);
+}
+
+dispatch("/updates/:queries", "updates");
+function updates() {
+	header('Content-Type: application/json; charset=utf-8');
+	$query_count = params("queries");
+	if ($query_count < 1) {
+		$query_count = 1;
+	}
+	if ($query_count > 500) {
+		$query_count = 500;
+	}
+
+	$worlds = array();
+
+	for ($i = 0; $i < $query_count; $i++) {
+		$id = mt_rand(1, 10000);
+		$world = World::find($id);
+		$worlds[] = $world->to_array();
+	}
+
+	array_walk($worlds, "update_world");
+
+	return json($worlds);
+}
+
+function fortune_to_array(&$fortune, $key) {
+	$fortune->message = htmlspecialchars($fortune->message);
+	$fortune = $fortune->to_array();
+}
+
+function compare_fortunes($f1, $f2) {
+	return strcmp($f1["message"], $f2["message"]);
+}
+
+dispatch("/fortune", "fortune");
+function fortune() {
+	header('Content-Type: text/html; charset=utf-8');
+	$fortunes = Fortune::all();
+	array_walk($fortunes, "fortune_to_array");
+	$fortunes[] = array("id"=>0, "message"=> "Additional fortune added at request time.");
+	usort($fortunes, "compare_fortunes");
+	return render("fortune.php", null, array("fortunes" => $fortunes));
+}
+
+run();
+?>

+ 11 - 0
frameworks/PHP/limonade/install.sh

@@ -0,0 +1,11 @@
+#!/bin/bash
+export PHP_HOME=${IROOT}/php-5.5.17
+export COMPOSER_HOME=${IROOT}/php-composer
+export PHP_FPM=$PHP_HOME/sbin/php-fpm
+export NGINX_HOME=${IROOT}/nginx
+
+fw_depends php nginx composer
+
+${PHP_HOME}/bin/php ${COMPOSER_HOME}/composer.phar install \
+  --no-interaction --working-dir $TROOT \
+  --no-progress --optimize-autoloader 

+ 5 - 0
frameworks/PHP/limonade/models/Fortune.php

@@ -0,0 +1,5 @@
+<?php
+class Fortune extends ActiveRecord\Model {
+	static $table_name = "Fortune";
+}
+?>

+ 5 - 0
frameworks/PHP/limonade/models/World.php

@@ -0,0 +1,5 @@
+<?php
+class World extends ActiveRecord\Model {
+	static $table_name = "World";
+}
+?>

+ 12 - 0
frameworks/PHP/limonade/setup.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+export PHP_HOME=${IROOT}/php-5.5.17
+export COMPOSER_HOME=${IROOT}/php-composer
+export PHP_FPM=${PHP_HOME}/sbin/php-fpm
+export NGINX_HOME=${IROOT}/nginx
+
+sed -i 's|localhost|'"${DBHOST}"'|g' index.php
+sed -i 's|root .*/FrameworkBenchmarks/limonade|root '"${TROOT}"'|g' deploy/nginx.conf
+sed -i 's|/usr/local/nginx/|'"${IROOT}"'/nginx/|g' deploy/nginx.conf
+
+$PHP_FPM --fpm-config $FWROOT/config/php-fpm.conf -g $TROOT/deploy/php-fpm.pid
+$NGINX_HOME/sbin/nginx -c $TROOT/deploy/nginx.conf

+ 19 - 0
frameworks/PHP/limonade/views/fortune.php

@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+<?php
+foreach($fortunes as $f) {
+	echo ("<tr><td>" . $f["id"] . "</td><td>" . $f["message"] . "</td></tr>");
+}
+?>
+</table>
+</body>
+</html>

+ 1 - 0
frameworks/PHP/php-phalcon/app/views/layouts/mongobench.volt

@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><title>Fortunes</title></head><body>{{ content() }}</body></html>

+ 30 - 43
frameworks/PHP/symfony2/README.md

@@ -1,36 +1,14 @@
 # Symfony 2 Benchmarking Test
 # Symfony 2 Benchmarking Test
 
 
-This is the Symfony 2 PHP portion of a benchmarking test suite comparing a variety of web development platforms.
+The information below contains information specific to Symfony2. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [PHP README](../).
 
 
-This implementation is the direct result of installing the 
-[Standard Edition of Symfony 2](https://github.com/symfony/symfony-standard) using [Composer](https://getcomposer.org/), and making 
-the minimum modifications necessary to support 
-running the benchmark. Specifically, unnecessary bundles 
-have *not* been removed from the kernel to properly 
-reflect "out of the box" performance. If you're interested
-in tuned performance, see the symfony-stripped test, which
-removes and unnecessary components. 
-
-Note: `app/bootstrap.php.cache` is generated by Composer
-when you first run `composer.phar install`
-
-### JSON Encoding Test
-Uses the PHP standard [JSON encoder](http://www.php.net/manual/en/function.json-encode.php).
-
-* [JSON test controller](src/Skamander/BenchmarkBundle/Controller/BenchController.php)
-
-### Data-Store/Database Mapping Test
-Uses the Symfony 2/Doctrine 2 Entity functionality.
-
-* [DB test controller](src/Skamander/BenchmarkBundle/Controller/BenchController.php)
-* [DB test model](src/Skamander/BenchmarkBundle/Entity/World.php)
-
-### Template Test
-Uses Symfony's template engine 'Twig'
-
-* [Template test controller](src/Skamander/BenchmarkBundle/Controller/BenchController.php)
+This is the Symfony 2 PHP portion of a [benchmarking test suite](../../) comparing a variety of web development platforms.
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
+
 The tests were run with:
 The tests were run with:
 
 
 * [Symfony Version 2.2.1](http://symfony.com/)
 * [Symfony Version 2.2.1](http://symfony.com/)
@@ -38,25 +16,34 @@ The tests were run with:
 * [nginx 1.4.0](http://nginx.org/)
 * [nginx 1.4.0](http://nginx.org/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 
-## Test URLs
-### JSON Encoding Test
-
-http://localhost/json
-
-### Data-Store/Database Mapping Test
+## Paths & Source for Tests
 
 
-http://localhost/db
+* [JSON Serialization](src/Skamander/BenchmarkBundle/Controller/BenchController.php)
+: "/json" _Note: Uses the PHP standard 
+[JSON encoder](http://www.php.net/manual/en/function.json-encode.php)._
+* [Single Database Query](src/Skamander/BenchmarkBundle/Controller/BenchController.php) ([Model](src/Skamander/BenchmarkBundle/Entity/World.php))
+: "/db" _Note: Uses the Symfony 2/Doctrine 2 Entity functionality._
+* [Multiple Database Queries](src/Skamander/BenchmarkBundle/Controller/BenchController.php) ([Model](src/Skamander/BenchmarkBundle/Entity/World.php))
+: "/db?queries=" _Note: Uses the Symfony 2/Doctrine 2 Entity functionality._
+* [Fortunes Template Test](src/Skamander/BenchmarkBundle/Controller/BenchController.php)
+: "/fortunes" _Note: Uses Symfony's template engine 'Twig'_
 
 
-### Variable Query Test
-    
-http://localhost/db?queries=2
+## Advice for Adding Symfony2 Tests
 
 
-### Templating Test
+This implementation is the direct result of installing the 
+[Standard Edition of Symfony 2](https://github.com/symfony/symfony-standard) using [Composer](https://getcomposer.org/), and making 
+the minimum modifications necessary to support 
+running the benchmark. Specifically, unnecessary bundles 
+have *not* been removed from the kernel to properly 
+reflect "out of the box" performance. If you're interested
+in tuned performance, see the symfony-stripped test, which
+removes and unnecessary components. 
 
 
-http://localhost/fortunes
+Note: `app/bootstrap.php.cache` is generated by Composer
+when you first run `composer.phar install`
 
 
 # Interesting Links
 # Interesting Links
 
 
-[Discussion on APC vs Zend Optimizer, PHP 5.4](http://www.ricardclau.com/2013/03/apc-vs-zend-optimizer-benchmarks-with-symfony2/)
-
-[Symphony2 Performance Tuning](http://symfony.com/doc/current/book/performance.html)
+* [Discussion on APC vs Zend Optimizer, PHP 5.4](http://www.ricardclau.com/2013/03/apc-vs-zend-optimizer-benchmarks-with-symfony2/)
+* [Symfony2 Performance Tuning](http://symfony.com/doc/current/book/performance.html)
+* [Why is Symfony2 performing so bad in benchmarks and does it matter?](http://stackoverflow.com/questions/16696763/why-is-symfony2-performing-so-bad-in-benchmarks-and-does-it-matter)

+ 30 - 0
frameworks/Python/API-Hour/README.md

@@ -0,0 +1,30 @@
+# API-Hour Benchmark Test
+
+This is the API-Hour portion of a [benchmarking tests suite](../../) 
+comparing a variety of web development platforms.
+
+The information below is specific to API-Hour. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information provided in 
+the [Python README](../).
+
+## Test Paths & Sources
+
+* [JSON Serialization](hello/endpoints/world.py): "/json"
+* [Single Database Query](hello/services/world.py): "/db"
+* [Multiple Database Queries](hello/services/world.py): "/queries?queries=#"*
+* [Fortunes](hello/services/world.py): "/fortunes"
+* [Database Updates](hello/services/world.py): "/updates?queries=#"*
+* [Plaintext](hello/endpoints/world.py): "/plaintext"
+
+*Replace # with an actual number.
+
+## Get Help
+
+### Community
+
+* [API-Hour Google Group](https://groups.google.com/forum/#!forum/api-hour)
+
+### Resources
+
+* [API-Hour Source Code](https://github.com/Eyepea/API-Hour)

+ 21 - 3
frameworks/Python/README.md

@@ -1,9 +1,26 @@
 # Python frameworks
 # Python frameworks
 
 
-## Experts
+The information below contains information specific to Python. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
+
+## Infrastructure Software Versions
+
+* [python2 2.7.9](https://www.python.org/)
+* [python3 3.4.2](https://www.python.org/)
+* [pypy 2.4.0](http://pypy.org/)
+* [nginx 1.4.1](http://nginx.org/)
+
+## Get Help
+
+### Python Experts
 
 
 * INADA Naoki (@methane) -- Expert of Python and Python's MySQL driver.
 * INADA Naoki (@methane) -- Expert of Python and Python's MySQL driver.
 
 
+### [Python Community](https://www.python.org/community/)
+
+* `#python` IRC Channel ([irc.freenode.net](http://freenode.net/))
+* `#python-dev` IRC Channel ([irc.freenode.net](http://freenode.net/))
 
 
 ## Python interpreters
 ## Python interpreters
 
 
@@ -27,7 +44,6 @@ PyPy is the fastest Python implementation with JIT.
 There is PyPy's Python 3 implementation (PyPy3), but it is not so tuned like PyPy2.
 There is PyPy's Python 3 implementation (PyPy3), but it is not so tuned like PyPy2.
 So we don't use it for now.
 So we don't use it for now.
 
 
-
 ## WSGI Servers
 ## WSGI Servers
 
 
 ### Nginx + uWSGI
 ### Nginx + uWSGI
@@ -99,8 +115,10 @@ You can see Flask's files to know how to write new test.
 virtualenv is installed on Python 2 and PyPy.  Use `$IROOT/py3/bin/python3 -m venv $TROOT/py3`
 virtualenv is installed on Python 2 and PyPy.  Use `$IROOT/py3/bin/python3 -m venv $TROOT/py3`
 for Python 3.
 for Python 3.
 
 
+You can set environment variables within `install.sh` or within `setup.sh`.
+
 `bechmark_config` is json file to define test.
 `bechmark_config` is json file to define test.
-See [here](https://github.com/TechEmpower/FrameworkBenchmarks#the-benchmark_configjson-file)
+See [here](http://frameworkbenchmarks.readthedocs.org/en/latest/Codebase/Framework-Files/#benchmark-config-file).
 
 
 `setup_py2.sh` is used to run test on Python 2.  `gunicorn_conf.py` is configuration for gunicorn.
 `setup_py2.sh` is used to run test on Python 2.  `gunicorn_conf.py` is configuration for gunicorn.
 `setup_py2.sh` and `gunicorn_conf.py` are written as generic as possible.
 `setup_py2.sh` and `gunicorn_conf.py` are written as generic as possible.

+ 25 - 21
frameworks/Python/bottle/README.md

@@ -1,34 +1,38 @@
-# Bottle Benchmark Test
+# [Bottle](http://bottlepy.org/docs/dev/index.html) Benchmark Test
 
 
-Single file test, [app.py](app.py)
+This is the Python Bottle portion of a [benchmarking tests suite](../../) 
+comparing a variety of frameworks.
 
 
+The information below is specific to Bottle. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information that's provided in 
+the [Python README](../).
 
 
-## Test URLs
-### JSON Encoding 
+## Test Paths and Sources
 
 
-http://localhost:8080/json
-
-### Single Row Random Query
+All tests are implemented in a single file ([app.py](app.py)).
 
 
 With ORM:
 With ORM:
-    http://localhost:8080/dbs
-
-Without ORM (raw):
-    http://localhost:8080/dbsraw
-
-### Variable Row Query Test 
 
 
-With ORM:
-    http://localhost:8080/db?queries=2
+* [JSON Serialization](app.py): "/json"
+* [Single Database Query](app.py): "/dbs"
+* [Multiple Database Queries](app.py): "/db?queries=#"*
+* [Fortunes](app.py): "/fortunes"
+* [Database Updates](app.py): "/updates?queries=#"*
+* [Plaintext](app.py): "/plaintext"
 
 
 Without ORM (raw):
 Without ORM (raw):
-    http://localhost:8080/dbraw?queries=2
 
 
-### Fortune Test
+* [Single Database Query](app.py): "/raw-db"
+* [Multiple Database Queries](app.py): "/raw-queries?=#"*
+* [Fortune](app.py): "/raw-fortune"
+* [Database Updates](app.py): "/raw-updates?queries=#"*
 
 
-With ORM:
-    http://localhost:8080/fortune
+*Replace # with an actual number.
 
 
-Without ORM (raw):
-    http://localhost:8080/fortuneraw
+## Get Help
+
+### Community
 
 
+* [bottlepy Google Group](https://groups.google.com/forum/#!forum/bottlepy)
+* `#bottlepy` IRC Channel ([irc.freenode.net](https://freenode.net/))

+ 20 - 20
frameworks/Python/django/README.md

@@ -1,30 +1,30 @@
-# Django Benchmarking Test
+# [Django](https://www.djangoproject.com/) Benchmarking Test
 
 
-This is the Django portion of a benchmarking test suite comparing a variety of web development platforms.
+This is the Django portion of a [benchmarking tests suite](../../) 
+comparing a variety of web development platforms.
 
 
-### JSON Encoding Test
+The information below is specific to Django. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information provided in 
+the [Python README](../).
 
 
-* [JSON test source](hello/world/views.py)
+## Test Paths & Sources
 
 
+* [JSON Serialization](hello/world/views.py): "/json"
+* [Single Database Query](hello/world/views.py): "/db", [World Model](hello/world/models.py)
+* [Multiple Database Queries](hello/world/views.py): "/dbs?queries=#"*, [World Model](hello/world/models.py)
+* [Fortunes](hello/world/views.py): "/fortunes", [Fortune Model](hello/world/models.py)
+* [Database Updates](hello/world/views.py): "/update?queries=#"*, [World Model](hello/world/models.py)
+* _Plaintext: N/A_
 
 
-### Data-Store/Database Mapping Test
+*Replace # with an actual number.
 
 
-* [DB test controller](hello/world/views.py)
-* [DB test model](hello/world/models.py)
+## Get Help
 
 
+### [Community](https://www.djangoproject.com/community/)
 
 
-## Resources
-* https://docs.djangoproject.com/en/dev/intro/tutorial01/
+* `#django` IRC Channel ([irc.freenode.net](https://freenode.net/))
 
 
-## Test URLs
-### JSON Encoding Test
+### Resources
 
 
-http://localhost:8080/json
-
-### Data-Store/Database Mapping Test
-
-http://localhost:8080/db
-
-### Variable Query Test
-
-http://localhost:8080/db?queries=2
+* [Writing your first Django app](https://docs.djangoproject.com/en/dev/intro/tutorial01/)

+ 27 - 9
frameworks/Python/falcon/README.md

@@ -1,25 +1,43 @@
 # Falcon Benchmark Test (ported from Flask example)
 # Falcon Benchmark Test (ported from Flask example)
 
 
-Single file test, [app.py](app.py)
+This is the Falcon portion of a [benchmarking tests suite](../../) 
+comparing a variety of web development platforms.
+
+The information below is specific to Falcon. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information provided in 
+the [Python README](../).
 
 
 ## Description
 ## Description
 
 
 Falcon API framework (http://falconframework.org)
 Falcon API framework (http://falconframework.org)
 
 
-### Database
-
-(none at the moment)
+## Infrastructure Software
 
 
 ### Server
 ### Server
 
 
 * gunicorn+meinheld on CPython
 * gunicorn+meinheld on CPython
 * Tornado on PyPy
 * Tornado on PyPy
 
 
-## Test URLs
-### JSON Encoding
+## Test Paths & Sources
+
+All of the test implementations are located within a single file ([app.py](app.py)).
+
+* [JSON Serialization](app.py): "/json"
+* _Single Database Query: N/A_
+* _Multiple Database Queries: N/A_
+* _Fortunes: N/A_
+* _Database Updates: N/A_
+* [Plaintext](app.py): "/plaintext"
+
+## Get Help
+
+### Resources
 
 
-http://localhost:8080/json
+* [Falcon Source Code](https://github.com/falconry/falcon)
 
 
-### Plaintext
+### [Community](http://falcon.readthedocs.org/en/0.2.0/community/index.html)
 
 
-http://localhost:8080/plaintext
+* `#falconframework` IRC Channel ([irc.freenode.net](https://freenode.net/))
+* Subscribe to email list by emailing falcon[at]librelist.com and 
+following the instructions in the reply.

+ 11 - 3
frameworks/Python/flask/README.md

@@ -1,6 +1,15 @@
-# Flask Benchmark Test
+# [Flask](http://flask.pocoo.org/) Benchmark Test
 
 
-Single file test, [app.py](app.py)
+The information below is specific to Flask. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information that's provided in 
+the [Python README](../).
+
+This is the Python Flask portion of a [benchmarking tests suite](../../) 
+comparing a variety of frameworks.
+
+All test implementations are located within a single file 
+([app.py](app.py)).
 
 
 ## Description
 ## Description
 
 
@@ -20,7 +29,6 @@ MySQL (MySQL-python on CPython, PyMySQL on PyPy)
 * gunicorn+meinheld on CPython
 * gunicorn+meinheld on CPython
 * Tornado on PyPy
 * Tornado on PyPy
 
 
-
 ## Test URLs
 ## Test URLs
 ### JSON Encoding 
 ### JSON Encoding 
 
 

+ 20 - 19
frameworks/Python/pyramid/README.md

@@ -1,31 +1,32 @@
 # Pyramid benchmark test
 # Pyramid benchmark test
 
 
+This is the Python Pyramid portion of a [benchmarking tests suite](../../) 
+comparing a variety of frameworks.
+
+The information below is specific to Pyramid. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information that's provided in 
+the [Python README](../).
+
 [Pyramid](http://www.pylonsproject.org/) is a flexible Python 2/3 framework.
 [Pyramid](http://www.pylonsproject.org/) is a flexible Python 2/3 framework.
 This test uses [SQLAlchemy](http://www.sqlalchemy.org/) as its ORM, the default
 This test uses [SQLAlchemy](http://www.sqlalchemy.org/) as its ORM, the default
 [Chameleon](http://www.pylonsproject.org/) for its templating, and
 [Chameleon](http://www.pylonsproject.org/) for its templating, and
 [Gunicorn](https://github.com/benoitc/gunicorn) for the application server.
 [Gunicorn](https://github.com/benoitc/gunicorn) for the application server.
 
 
-## Test URLs
-
-### JSON Encoding
-
-http://localhost:6543/json
-
-### Single Row Random Query
-
-http://localhost:6543/db
-
-### Variable Row Query Test
-
-http://localhost:6543/queries?queries=10
+## Test Paths & Source
 
 
-### Fortune Test
+* [JSON Serialization](frameworkbenchmarks/tests.py): "/json"
+* [Single Database Query](frameworkbenchmarks/tests.py): "/db", [World Model](frameworkbenchmarks/models.py)
+* [Multiple Database Queries](frameworkbenchmarks/tests.py): "queries?queries=#"*, [World Model](frameworkbenchmarks/models.py)
+* [Fortunes](frameworkbenchmarks/tests.py): "/fortunes", [Fortune Model](frameworkbenchmarks/models.py)
+* [Database Updates](frameworkbenchmarks/tests.py): "updates?queries=#"*, [World Model](frameworkbenchmarks/models.py)
+* [Plaintext](frameworkbenchmarks/tests.py): "/plaintext"
 
 
-http://localhost:6543/fortunes
+*Replace # with an actual number.
 
 
-### Updates
-http://localhost:6543/updates?queries=10
+## Get Help
 
 
-### Plaintext
+### Community
 
 
-http://localhost:6543/plaintext
+* `#pyramid` IRC Channel ([irc.freenode.net](https://freenode.net/))
+* [Pyramid (pylons-discuss) Google Group](https://groups.google.com/forum/#!forum/pylons-discuss)

+ 29 - 11
frameworks/Python/tornado/README.md

@@ -1,16 +1,12 @@
 # Tornado Benchmarking Test
 # Tornado Benchmarking Test
 
 
-This is the Tornado portion of a benchmarking test suite comparing a variety of web development platforms.
-
-### JSON Encoding Test
-
-* [JSON test source](server.py)
-
-
-### Data-Store/Database Mapping Test
-
-* [Database teste source Raw](server.py)
+This is the Tornado portion of a [benchmarking tests suite](../../) 
+comparing a variety of web development platforms.
 
 
+The information below is specific to Tornado. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information that's provided in 
+the [Python README](../).
 
 
 ## Infrastructure Software
 ## Infrastructure Software
 
 
@@ -19,6 +15,28 @@ This is the Tornado portion of a benchmarking test suite comparing a variety of
 * [Mongodb](https://www.mongodb.org/) with [motor](http://motor.readthedocs.org/en/stable/)
 * [Mongodb](https://www.mongodb.org/) with [motor](http://motor.readthedocs.org/en/stable/)
 * [PostgreSQL](http://www.postgresql.org/) with [momoko](http://momoko.61924.nl/en/latest/)
 * [PostgreSQL](http://www.postgresql.org/) with [momoko](http://momoko.61924.nl/en/latest/)
 
 
+## Test Paths & Sources
+
+### Raw Database Tests
+
+* [Single Database Query](server.py): "/dbraw"
+* [Multiple Database Queries](server.py): "/queriesraw?queries=#"*
+
+### Tests
+
+* [JSON Serialization](server.py): "/json"
+* [Single Database Query](server.py): "/db"
+* [Multiple Database Queries](server.py): "/queries?queries=#"*
+* [Plaintext](server.py): "/plaintext"
+
+*Replace # with an actual number.
+
+## Get Help
+
+### Community
+
+* [python-tornado Google Group](https://groups.google.com/forum/#!forum/python-tornado)
+
+### Resources
 
 
-## Resources
 * http://www.tornadoweb.org/en/stable/documentation.html
 * http://www.tornadoweb.org/en/stable/documentation.html

+ 40 - 0
frameworks/Python/turbogears/README.md

@@ -0,0 +1,40 @@
+# TurboGears Benchmark Test 
+
+Single file test, [app.py](app.py)
+
+## Description
+
+TurboGears framework (http://turbogears.org)
+
+### Database
+
+MySQL
+
+### Server
+
+* Gunicorn + Meinheld
+
+## Test URLs
+### JSON Encoding
+
+http://localhost:8080/json
+
+### Plaintext
+
+http://localhost:8080/plaintext
+
+### DB
+
+http://localhost:8080/db
+
+### Query
+
+http://localhost:8080/queries?queries=2
+
+### Update
+
+http://localhost:8080/updates?queries=2
+
+### Fortune
+
+http://localhost:8080/fortune

+ 93 - 0
frameworks/Python/turbogears/app.py

@@ -0,0 +1,93 @@
+import os
+import sys
+import json
+from functools import partial
+from operator import attrgetter
+from random import randint
+
+import bleach
+
+from tg import expose, TGController, AppConfig
+
+from jinja2 import Environment, PackageLoader
+
+from sqlalchemy.orm import scoped_session, sessionmaker
+from sqlalchemy import create_engine
+
+from models.Fortune import Fortune
+from models.World import World
+
+DBDRIVER = 'mysql'
+DBHOSTNAME = os.environ.get('DBHOST', 'localhost')
+DATABASE_URI = '%s://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world?charset=utf8' % (DBDRIVER, DBHOSTNAME)
+
+db_engine = create_engine(DATABASE_URI)
+Session = sessionmaker(bind=db_engine)
+db_session = Session()
+
+env = Environment(loader=PackageLoader("app", "templates"))
+
+def getQueryNum(queryString):
+    try:
+        num_queries = int(queryString)
+        if num_queries < 1:
+            return 1
+        if num_queries > 500:
+            return 500
+        return num_queries
+    except ValueError:
+         return 1
+
+class RootController(TGController):
+
+    @expose(content_type="text/plain")
+    def plaintext(self):
+        return "Hello, World!"
+
+    @expose("json")
+    def json(self):
+        return {"message": "Hello, World!"}
+
+    @expose("json")
+    def db(self):
+        wid = randint(1, 10000)
+        world = db_session.query(World).get(wid).serialize()
+        return world
+
+    @expose("json")
+    def updates(self, queries=1):
+        num_queries = getQueryNum(queries)
+        worlds = []
+        rp = partial(randint, 1, 10000)
+        ids = [rp() for _ in xrange(num_queries)]
+        ids.sort()
+        for id in ids:
+            world = db_session.query(World).get(id)
+            world.randomNumber = rp()
+            worlds.append(world.serialize())
+        return json.dumps(worlds)
+
+    @expose("json")
+    def queries(self, queries=1):
+        num_queries = getQueryNum(queries)
+        rp = partial(randint, 1, 10000)
+        get = db_session.query(World).get
+        worlds = [get(rp()).serialize() for _ in xrange(num_queries)]
+        return json.dumps(worlds)
+
+
+    @expose()
+    def fortune(self):
+        fortunes = db_session.query(Fortune).all()
+        fortunes.append(Fortune(id=0, message="Additional fortune added at request time."))
+        fortunes.sort(key=attrgetter("message"))
+        for f in fortunes:
+            f.message = bleach.clean(f.message)
+            template = env.get_template("fortunes.html")
+        return template.render(fortunes=fortunes)
+
+config = AppConfig(minimal=True, root_controller=RootController())
+config.renderers.append("jinja")
+
+app = config.make_wsgi_app()
+

+ 27 - 0
frameworks/Python/turbogears/benchmark_config.json

@@ -0,0 +1,27 @@
+{
+  "framework": "turbogears",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "TurboGears",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "Meinheld",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "TurboGears",
+      "notes": "CPython 2.7"
+    }
+  }]
+}

+ 25 - 0
frameworks/Python/turbogears/gunicorn_conf.py

@@ -0,0 +1,25 @@
+import multiprocessing
+import os
+import sys
+
+_is_pypy = hasattr(sys, 'pypy_version_info')
+_is_travis = os.environ.get('TRAVIS') == 'true'
+
+workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
+bind = "0.0.0.0:8080"
+keepalive = 120
+errorlog = '-'
+pidfile = 'gunicorn.pid'
+
+if _is_pypy:
+    worker_class = "tornado"
+else:
+    worker_class = "meinheld.gmeinheld.MeinheldWorker"
+
+    def post_fork(server, worker):
+        # Disalbe access log
+        import meinheld.server
+        meinheld.server.set_access_logger(None)

+ 19 - 0
frameworks/Python/turbogears/install.sh

@@ -0,0 +1,19 @@
+#!/bin/bash
+
+export PY2_ROOT=$IROOT/py2
+export PY2=$PY2_ROOT/bin/python
+export PY2_PIP=$PY2_ROOT/bin/pip
+
+export PY3_ROOT=$IROOT/py3
+export PY3=$PY3_ROOT/bin/python3
+export PY3_PIP=$PY3_ROOT/bin/pip3
+
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
+
+fw_depends python2 python3
+
+$PY2_PIP install --install-option="--prefix=${PY2_ROOT}" -r $TROOT/requirements.txt
+
+$PY3_PIP install --install-option="--prefix=${PY3_ROOT}" -r $TROOT/requirements.txt
+

+ 17 - 0
frameworks/Python/turbogears/models/Fortune.py

@@ -0,0 +1,17 @@
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column
+from sqlalchemy.types import String, Integer
+
+Base = declarative_base()
+
+class Fortune(Base):
+    __tablename__ = "fortune"
+
+    id = Column(Integer, primary_key = True)
+    message = Column(String)
+
+    def serialize(self):
+        return {
+            'id' : int(self.id),
+            'message' : self.message
+        }

+ 17 - 0
frameworks/Python/turbogears/models/World.py

@@ -0,0 +1,17 @@
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import Column
+from sqlalchemy.types import String, Integer
+
+Base = declarative_base()
+
+class World(Base):
+    __tablename__ = "world"
+
+    id = Column(Integer, primary_key = True)
+    randomNumber = Column(Integer)
+
+    def serialize(self):
+        return {
+            'id' : int(self.id),
+            'randomNumber' : int(self.randomNumber)
+        }

+ 0 - 0
frameworks/Python/turbogears/models/__init__.py


+ 11 - 0
frameworks/Python/turbogears/requirements.txt

@@ -0,0 +1,11 @@
+tg.devtools==2.3.4
+
+bleach==1.4.1
+
+SQLAlchemy==0.9.9
+zope.sqlalchemy==0.7.6
+mysqlclient==1.3.6
+jinja2==2.7.3
+
+gunicorn==19.3.0
+meinheld==0.5.7

+ 7 - 0
frameworks/Python/turbogears/setup.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+export PY2_ROOT=$IROOT/py2
+export PY2=$PY2_ROOT/bin/python
+export PY2_GUNICORN=$PY2_ROOT/bin/gunicorn
+
+$PY2_GUNICORN app:app -c gunicorn_conf.py &

+ 20 - 0
frameworks/Python/turbogears/templates/fortunes.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Fortunes</title>
+    </head>
+    <body>
+        <table>
+            <tr>
+                <th>id</th>
+                <th>message</th>
+            </tr>
+            {%for fortune in fortunes %}
+                <tr>
+                    <td>{{ fortune.id }}</td>
+                    <td>{{ fortune.message }}</td>
+                </tr>
+            {% endfor %}
+        </table>
+    </body>
+</html>

+ 29 - 0
frameworks/Python/uwsgi/README.md

@@ -0,0 +1,29 @@
+# UWSGI Benchmarking Test
+
+This is the UWSGI portion of a [benchmarking tests suite](../../) 
+comparing a variety of web development platforms.
+
+The information below is specific to UWSGI. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information provided in 
+the [Python README](../).
+
+## Test Paths & Sources
+
+* [JSON Serialization](hello.py): "/json"
+* _Single Database Query: N/A_
+* _Multiple Database Queries: N/A_
+* _Fortunes: N/A_
+* _Database Updates: N/A_
+* _Plaintext: N/A_
+
+## Get Help
+
+### Community
+
+* `#uwsgi` IRC Channel ([irc.freenode.net](https://freenode.net/))
+
+### References
+
+* [UWSGI Source Code](https://github.com/unbit/uwsgi)
+* [UWSGI Docs](https://uwsgi-docs.readthedocs.org/en/latest/)

+ 20 - 10
frameworks/Python/wsgi/README.md

@@ -1,22 +1,32 @@
 # WSGI Benchmarking Test
 # WSGI Benchmarking Test
 
 
-This is the WSGI portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+This is the WSGI portion of a [benchmarking tests suite](../../) 
+comparing a variety of web development platforms.
 
 
-### JSON Encoding Test
-
-
-* [JSON test controller/view](hello.py)
+The information below is specific to WSGI. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information provided in 
+the [Python README](../).
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
+
 The tests were run with:
 The tests were run with:
+
 * [Python 2.7.3](http://www.python.org/)
 * [Python 2.7.3](http://www.python.org/)
 * [Gunicorn 0.17.2](http://gunicorn.org/)
 * [Gunicorn 0.17.2](http://gunicorn.org/)
 
 
+## Test Paths & Sources
+
+* [JSON Serialization](hello.py): "/json"
+* Single Database Query: N/A_
+* Multiple Database Queries: N/A_
+* Fortunes: N/A_
+* Database Updates: N/A_
+* [Plaintext](hello.py): "/plaintext"
 
 
-## References
-http://docs.gunicorn.org/en/latest/run.html
+## Get Help
 
 
-## Test URLs
-### JSON Encoding Test
+### References
 
 
-http://localhost:8080/json
+* [WSGI Docs](http://wsgi.readthedocs.org/en/latest/)
+* [Gunicorn Docs](http://docs.gunicorn.org/en/latest/run.html)

+ 52 - 7
frameworks/Ruby/README.md

@@ -1,24 +1,69 @@
-# Using RVM to setup your environment
+# Ruby Frameworks
+
+The information below contains information specific to Ruby. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
+
+## Infrastructure Software Versions
+
+* [RVM 2.2.1](https://rvm.io/) (Unless tests are run in Travis-CI)
+
+## Adding a New Ruby Framework
+
+### Installation
 
 
 TFB uses rvm wherever possible to help ruby-based or
 TFB uses rvm wherever possible to help ruby-based or
 jruby-based frameworks setup their environment. 
 jruby-based frameworks setup their environment. 
-In your framework's `install.sh`, put this prior to other statements: 
+
+When verifying the tests in Travis-CI we rely on Travis-CI's 
+RVM installation (and $HOME isn't /home/travis while running 
+Travis-CI), so we have certain specific caveats to keep 
+Travis-CI happy.
+
+#### Install RVM
+
+Most install.sh files will at least have this:
 
 
     #!/bin/bash
     #!/bin/bash
-    
+
+    fw_depends rvm # This installs RVM
+
+    if [ "$TRAVIS" = "true" ]
+    then
+      rvmsudo rvm install ruby-2.0.0-p0
+    else
+      rvm install ruby-2.0.0-p0
+    fi
+
+### Set Up with RVM
+
+At the top of your framework's `setup.sh`, put this (if 
+you're using RVM): 
+
+    #!/bin/bash
+
     # Assume single-user installation
     # Assume single-user installation
-    source $HOME/.rvm/scripts/rvm
+    if [ "$TRAVIS" = "true" ]
+    then
+      source /home/travis/.rvm/scripts/rvm
+    else
+      source $HOME/.rvm/scripts/rvm
+    fi
 
 
 Because TFB uses Python's `subprocess` module, which runs 
 Because TFB uses Python's `subprocess` module, which runs 
 all shell processes in a non-login mode, you must source the 
 all shell processes in a non-login mode, you must source the 
-`rvm` script before using `rvm` anywhere. Placing the `source`
-call in your `install.sh` before other commands ensures that it 
-will be called before installation and before running `setup.py`
+`rvm` script before using `rvm` anywhere. 
 
 
 For compatibility with how the framework rounds are executed, 
 For compatibility with how the framework rounds are executed, 
 you must use a single-user installation if you wish to run 
 you must use a single-user installation if you wish to run 
 ruby-based TFB tests.
 ruby-based TFB tests.
 
 
+## Get Help
+
+### Ruby Experts
 
 
+_No experts listed, yet. If you're an expert, add yourself!_
 
 
+### [Ruby Community](https://www.ruby-lang.org/en/community/)
 
 
+* `#ruby-lang` on IRC ([irc.freenode.net](https://freenode.net/))

+ 32 - 2
frameworks/Ruby/grape/README.md

@@ -1,15 +1,45 @@
-# Ruby Grape Benchmarking Test
+# Grape Micro-Framework
 
 
-This is the Ruby Grape portion of a [benchmarking test suite](../) comparing a variety of web servers along with JRuby/MRI.
+The information below contains information specific to Grape. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [Ruby README](../).
+
+This is the Ruby Grape portion of a [benchmarking test suite](../../) 
+comparing a variety of web servers along with JRuby/MRI.
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
 The tests were run with:
 The tests were run with:
 
 
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [JRuby 1.7.8](http://jruby.org/)
 * [JRuby 1.7.8](http://jruby.org/)
+* [Rubinius 2.2.10](http://rubini.us/)
 * [Grape 0.8.0](http://intridea.github.io/grape/)
 * [Grape 0.8.0](http://intridea.github.io/grape/)
 * [Rack 1.5.2](http://rack.github.com/)
 * [Rack 1.5.2](http://rack.github.com/)
 * [Unicorn 4.8.3](http://unicorn.bogomips.org/)
 * [Unicorn 4.8.3](http://unicorn.bogomips.org/)
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
 * [Puma 2.9.0](http://puma.io/)
 * [Puma 2.9.0](http://puma.io/)
 * [Thin 1.6.2](http://code.macournoyer.com/thin/)
 * [Thin 1.6.2](http://code.macournoyer.com/thin/)
+
+## Paths & Source for Tests
+
+* [JSON Serialization](config.ru): "/json"
+* [Single Database Query](config.ru): "/db"
+* [Multiple Database Queries](config.ru): "/query?queries={#}"
+* _Fortunes: N/A_
+* [Database Updates](config.ru): "/updates?queries={#}"
+* [Plaintext](config.ru): "/plaintext"
+
+## Get Help
+
+### Experts
+
+_No experts listed, yet. If you're an expert, add yourself!_
+
+### Community
+
+* [Grape Google Group](https://groups.google.com/forum/?fromgroups#!forum/ruby-grape)
+
+### Resources
+
+* [Grape Micro-framework Source Code](https://github.com/intridea/grape)

+ 23 - 8
frameworks/Ruby/ngx_mruby/README.md

@@ -1,21 +1,36 @@
 # [nginx + mruby](https://github.com/matsumoto-r/ngx_mruby) Benchmark Test
 # [nginx + mruby](https://github.com/matsumoto-r/ngx_mruby) Benchmark Test
 
 
+The information below contains information specific to nginx + mruby. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [Ruby README](../).
+
+This is the nginx + mruby portion of a [benchmarking test suite](../../) 
+comparing a variety of web platforms.
+
+---
+
 The nginx app is distributes across a few files. most of it is in [nginx.conf](nginx.conf)
 The nginx app is distributes across a few files. most of it is in [nginx.conf](nginx.conf)
 The nginx conf is inside [nginx.conf](nginx.conf)
 The nginx conf is inside [nginx.conf](nginx.conf)
 Requires a nginx compiled with ngx_mruby module. It has been called nginx_mruby for lack of a better name
 Requires a nginx compiled with ngx_mruby module. It has been called nginx_mruby for lack of a better name
 
 
+## Infrastructure Software Versions
 
 
-## Test URLs
-### JSON Encoding
+The tests were run with:
 
 
-http://localhost:8080/json
+* [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 
 
-### Single Row Random Query
+## Paths & Source for Tests
 
 
-http://localhost:8080/db
+* [JSON Serialization](nginx.conf): "/json"
+* [Single Database Query](db.rb): "/db"
+* [Multiple Database Query](queries.rb): "/queries?queries={#}"
+* _Fortunes: N/A_
+* _Database Updates: N/A_
+* [Plaintext](nginx.conf): "/plaintext"
 
 
-### Variable Row Query Test
+## Get Help
 
 
-http://localhost:8080/db?queries=2
+### Experts
 
 
-Based upon the [openresty](../../Lua/openresty/) implementation.
+_No experts listed, yet. If you're an expert, add yourself!_

+ 46 - 0
frameworks/Ruby/padrino/README.md

@@ -0,0 +1,46 @@
+# Padrino Framework
+
+The information below contains information specific to Padrino. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [Ruby README](../).
+
+This is the Ruby Padrino portion of a [benchmarking test suite](../../) 
+comparing a variety of web servers.
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
+* [JRuby 1.7.8](http://jruby.org/)
+* [Rubinius 2.2.10](http://rubini.us/)
+* [Padrino 0.12.3](http://www.padrinorb.com/)
+* [Rack 1.5.2](http://rack.github.com/)
+* [Unicorn 4.8.3](http://unicorn.bogomips.org/)
+* [TorqBox 0.1.7](http://torquebox.org/torqbox/)
+* [Puma 2.9.0](http://puma.io/)
+* [Thin 1.6.2](http://code.macournoyer.com/thin/)
+
+## Paths & Source for Tests
+
+* [JSON Serialization](app/controllers.rb): "/json"
+* [Single Database Query](app/controllers.rb): "/db", [World Model](models/world.rb)
+* [Multiple Database Queries](app/controllers.rb): "/query?queries={#}", [World Model](models/world.rb)
+* [Fortunes](app/controllers.rb): "/fortunes", [Fortunes Model](models/fortune.rb)
+* [Database Updates](app/controllers.rb): "/updates?queries={#}", [World Model](models/world.rb)
+* [Plaintext](app/controllers.rb): "/plaintext"
+
+## Get Help
+
+### Experts
+
+_No experts listed, yet. If you're an expert, add yourself!_
+
+### [Community](http://www.padrinorb.com/pages/contribute)
+
+* [Padrino Google Group](https://groups.google.com/forum/#!forum/padrino)
+* `#padrino` IRC Channel([irc.freenode.net](http://freenode.net/))
+
+### Resources
+
+* [Padrino framework Source Code](https://github.com/padrino/padrino-framework)

+ 28 - 13
frameworks/Ruby/rack/README.md

@@ -1,31 +1,46 @@
-# Ruby Rack Benchmarking Test
+# Ruby [Rack](http://rack.github.io/) Benchmarking Test
 
 
-This is the Ruby Rack portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
-
-### JSON Encoding Test
-* [JSON test source](config.ru)
+The information below contains information specific to Rack. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [Ruby README](../).
 
 
+This is the Ruby Rack portion of a [benchmarking test suite](../../) 
+comparing a variety of web servers.
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
 The tests were run with:
 The tests were run with:
 
 
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [JRuby 1.7.8](http://jruby.org/)
 * [JRuby 1.7.8](http://jruby.org/)
+* [Rubinius 2.2.10](http://rubini.us/)
 * [Rack 1.5.2](http://rack.github.com/)
 * [Rack 1.5.2](http://rack.github.com/)
 * [Unicorn 4.8.3](http://unicorn.bogomips.org/)
 * [Unicorn 4.8.3](http://unicorn.bogomips.org/)
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
 * [Puma 2.9.0](http://puma.io/)
 * [Puma 2.9.0](http://puma.io/)
 * [Thin 1.6.2](http://code.macournoyer.com/thin/)
 * [Thin 1.6.2](http://code.macournoyer.com/thin/)
 
 
-## References
-* https://github.com/FooBarWidget/passenger/pull/71
+## Paths & Source for Tests
+
+* [JSON Serialization](app/ruby_impl.rb) [[jruby version](app/jruby_impl.rb)]: "/json"
+* [Single Database Query](app/ruby_impl.rb) [[jruby version](app/jruby_impl.rb)]: "/db", [World Model](models/world.rb)
+* [Multiple Database Queries](app/ruby_impl.rb) [[jruby version](app/jruby_impl.rb)]: "/query?queries={#}", [World Model](models/world.rb)
+* _Fortunes: N/A_
+* [Database Updates](app/ruby_impl.rb) [[jruby version](app/jruby_impl.rb)]: "/updates?queries={#}", [World Model](models/world.rb)
+* [Plaintext](app/ruby_impl.rb) [[jruby version](app/jruby_impl.rb)]: "/plaintext"
+
+## Get Help
+
+### Experts
+
+_No experts listed, yet. If you're an expert, add yourself!_
 
 
-## Test URLs
-### JSON Encoding Test
+### Community
 
 
-Ruby:
-localhost:8080
+* `#rack` IRC Channel ([irc.freenode.net](http://freenode.net/))
+* [Rack Google Group](https://groups.google.com/forum/#!forum/rack-devel)
 
 
-JRuby:
-localhost:8080
+### Resources
 
 
+* [Rack Source Code](https://github.com/rack/rack)
+* [PR: passenger-install-apache2-module doesn't work on ruby 2.0](https://github.com/FooBarWidget/passenger/pull/71)

+ 28 - 22
frameworks/Ruby/rails-stripped/README.md

@@ -1,17 +1,17 @@
-# Ruby on Rails Benchmarking Test
+# [Ruby on Rails](http://rubyonrails.org/) 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)
+The information below contains information specific to Ruby on Rails. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [Ruby README](../).
 
 
+This is the Ruby on Rails portion of a [benchmarking test suite](../../) 
+comparing a variety of web platforms.
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
+
 The tests were run with:
 The tests were run with:
+
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [Ruby 2.0.0-p0](http://www.ruby-lang.org/)
 * [JRuby 1.7.8](http://jruby.org/)
 * [JRuby 1.7.8](http://jruby.org/)
 * [Rails 3.2.18](http://rubyonrails.org/)
 * [Rails 3.2.18](http://rubyonrails.org/)
@@ -19,22 +19,28 @@ The tests were run with:
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 
-## References
-* https://github.com/FooBarWidget/passenger/pull/71
+## Paths & Source for Tests
+
+* [JSON Serialization](app/controllers/hello_world_controller.rb): "/json"
+* [Single Database Query](app/controllers/hello_world_controller.rb): "/db", [World Model](app/models/world.rb)
+* [Multiple Database Queries](app/controllers/hello_world_controller.rb): "/db?queries={#}", [World Model](app/models/world.rb)
+* _Fortunes: N/A_
+* _Database Updates: N/A_
+* _Plaintext: N/A_
+
+## Get Help
 
 
-## Test URLs
-### JSON Encoding Test
+### Experts
 
 
-Ruby:
-localhost:8080/hello_world/json
+_No experts listed, yet. If you're an expert, add yourself!_
 
 
-JRuby:
-localhost:8080/hello_world/json
+### Community
 
 
-### Data-Store/Database Mapping Test
+* `#rubyonrails` IRC Channel ([irc.freenode.net](http://freenode.net/))
+* [Ruby on Rails Twitter](https://twitter.com/rails)
+* [Ruby on Rails Google Group](https://groups.google.com/forum/#!forum/rubyonrails-talk)
 
 
-Ruby:
-localhost:8080/hello_world/db?queries=5
+### Resources
 
 
-JRuby:
-localhost:8080/hello_world/db?queries=5
+* [Ruby on Rails Source Code](https://github.com/rails/rails)
+* [PR: passenger-install-apache2-module doesn't work on ruby 2.0](https://github.com/FooBarWidget/passenger/pull/71)

+ 31 - 22
frameworks/Ruby/rails/README.md

@@ -1,40 +1,49 @@
-# Ruby on Rails Benchmarking Test
+# [Ruby on Rails](http://rubyonrails.org/) 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)
+The information below contains information specific to Ruby on Rails. 
+For further guidance, review the 
+[documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note the additional information provided in the [Ruby README](../).
 
 
+This is the Ruby on Rails portion of a [benchmarking test suite](../../) 
+comparing a variety of web platforms.
 
 
 ## Infrastructure Software Versions
 ## Infrastructure Software Versions
+
 The tests were run with:
 The tests were run with:
+
 * [Ruby 2.1.2](http://www.ruby-lang.org/)
 * [Ruby 2.1.2](http://www.ruby-lang.org/)
 * [JRuby 1.7.13](http://jruby.org/)
 * [JRuby 1.7.13](http://jruby.org/)
+* [Rubinius 2.2.10](http://rubini.us/)
 * [Rails 4.1.4](http://rubyonrails.org/)
 * [Rails 4.1.4](http://rubyonrails.org/)
 * [Unicorn 4.8.3](http://unicorn.bogomips.org/)
 * [Unicorn 4.8.3](http://unicorn.bogomips.org/)
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
 * [TorqBox 0.1.7](http://torquebox.org/torqbox/)
+* [Puma 2.9.0](http://puma.io/)
+* [Thin 1.6.2](http://code.macournoyer.com/thin/)
 * [MySQL 5.5](https://dev.mysql.com/)
 * [MySQL 5.5](https://dev.mysql.com/)
 
 
-## References
-* https://github.com/FooBarWidget/passenger/pull/71
+## Paths & Source for Tests
+
+* [JSON Serialization](app/controllers/hello_world_controller.rb): "/json"
+* [Single Database Query](app/controllers/hello_world_controller.rb): "/db", [World Model](app/models/world.rb)
+* [Multiple Database Queries](app/controllers/hello_world_controller.rb): "/db?queries={#}", [World Model](app/models/world.rb)
+* [Fortunes](app/controllers/hello_world_controller.rb): "/fortune" , [Fortunes Model](app/models/fortune.rb)
+* [Database Updates](app/controllers/hello_world_controller.rb): "/update?queries={#}", [World Model](app/models/world.rb)
+* [Plaintext](app/controllers/hello_world_controller.rb): "/plaintext"
+
+## Get Help
 
 
-## Test URLs
-### JSON Encoding Test
+### Experts
 
 
-Ruby:
-localhost:8080/hello_world/json
+_No experts listed, yet. If you're an expert, add yourself!_
 
 
-JRuby:
-localhost:8080/hello_world/json
+### Community
 
 
-### Data-Store/Database Mapping Test
+* `#rubyonrails` IRC Channel ([irc.freenode.net](http://freenode.net/))
+* [Ruby on Rails Twitter](https://twitter.com/rails)
+* [Ruby on Rails Google Group](https://groups.google.com/forum/#!forum/rubyonrails-talk)
 
 
-Ruby:
-localhost:8080/hello_world/db?queries=5
+### Resources
 
 
-JRuby:
-localhost:8080/hello_world/db?queries=5
+* [Ruby on Rails Source Code](https://github.com/rails/rails)
+* [PR: passenger-install-apache2-module doesn't work on ruby 2.0](https://github.com/FooBarWidget/passenger/pull/71)

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