Browse Source

Merge remote-tracking branch 'origin/master' into upgrade-clojure-frameworks

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

+ 4 - 0
.travis.yml

@@ -38,6 +38,7 @@ env:
     - "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"
@@ -81,6 +82,7 @@ env:
     - "TESTDIR=Java/wildfly-ee7"
     - "TESTDIR=Java/wildfly-ee7"
     - "TESTDIR=JavaScript/express"
     - "TESTDIR=JavaScript/express"
     - "TESTDIR=JavaScript/hapi"
     - "TESTDIR=JavaScript/hapi"
+    - "TESTDIR=JavaScript/koa"
     - "TESTDIR=JavaScript/nodejs"
     - "TESTDIR=JavaScript/nodejs"
     - "TESTDIR=JavaScript/ringojs"
     - "TESTDIR=JavaScript/ringojs"
     - "TESTDIR=JavaScript/ringojs-convenient"
     - "TESTDIR=JavaScript/ringojs-convenient"
@@ -101,6 +103,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"
@@ -125,6 +128,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)

+ 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=",

+ 5 - 3
frameworks/Erlang/cowboy/setup_erlang.sh → frameworks/Erlang/cowboy/setup.sh

@@ -1,9 +1,11 @@
 #!/bin/bash
 #!/bin/bash
-export REBAR_HOME=$IROOT/rebar
+
+source $IROOT/erlang.installed
+source $IROOT/rebar.installed
 
 
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/hello_world_app.erl
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/hello_world_app.erl
 
 
-rm -rf deps/*
+rm -rf deps/* ebin/*
 $REBAR_HOME/rebar get-deps
 $REBAR_HOME/rebar get-deps
 $REBAR_HOME/rebar compile
 $REBAR_HOME/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"}}}
  ]}.
  ]}.

+ 5 - 3
frameworks/Erlang/elli/setup_erlang.sh → frameworks/Erlang/elli/setup.sh

@@ -1,9 +1,11 @@
 #!/bin/bash
 #!/bin/bash
-export REBAR_HOME=$IROOT/rebar
+
+source $IROOT/erlang.installed
+source $IROOT/rebar.installed
 
 
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/elli_bench_sup.erl
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/elli_bench_sup.erl
 
 
-rm -rf deps/*
+rm -rf deps/* ebin/*
 $REBAR_HOME/rebar get-deps
 $REBAR_HOME/rebar get-deps
 $REBAR_HOME/rebar compile
 $REBAR_HOME/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)

+ 1 - 1
frameworks/JavaScript/express/app.js

@@ -1,3 +1,3 @@
 #!/bin/bash
 #!/bin/bash
 
 
-fw_depends nodejs
+fw_depends nvm

+ 12 - 14
frameworks/JavaScript/express/setup.sh

@@ -1,20 +1,18 @@
 #!/bin/bash
 #!/bin/bash
-export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
-
 sed -i 's|mongodb://.*/hello_world|mongodb://'"${DBHOST}"'/hello_world|g' app.js
 sed -i 's|mongodb://.*/hello_world|mongodb://'"${DBHOST}"'/hello_world|g' app.js
 sed -i 's|localhost|'"${DBHOST}"'|g' app.js
 sed -i 's|localhost|'"${DBHOST}"'|g' app.js
 
 
-export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
-export PATH=$PATH:$NODE_HOME/bin
+export NODE_ENV=production
+export NVM_HOME=${IROOT}/nvm
+# Used to avoid nvm's return 2 error.
+# Sourcing this functions if 0 is returned.
+source $NVM_HOME/nvm.sh || 0
+nvm install 0.10.8
+nvm use 0.10.8
 
 
-${NODE_HOME}/bin/npm install
-${NODE_HOME}/bin/node app &
+# update npm before app init
+npm install -g npm
 
 
-# !DO NOT REMOVE!
-#
-# It takes `node app` a few seconds to turn on and 
-# then fork. If you remove this sleep, the parent shell 
-# executing this script will be terminated before the 
-# application has time to awaken and be forked, and 
-# express will fail to be started
-sleep 5
+# run app
+npm install
+node app &

+ 1 - 1
frameworks/JavaScript/hapi/app.js

@@ -1,3 +1,3 @@
 #!/bin/bash
 #!/bin/bash
 
 
-fw_depends nodejs
+fw_depends nvm

+ 11 - 14
frameworks/JavaScript/hapi/setup.sh

@@ -1,20 +1,17 @@
 #!/bin/bash
 #!/bin/bash
-export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
-
 sed -i 's|localhost|'"${DBHOST}"'|g' app.js
 sed -i 's|localhost|'"${DBHOST}"'|g' app.js
 
 
 export NODE_ENV=production
 export NODE_ENV=production
-export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
-export PATH=$PATH:$NODE_HOME/bin
+export NVM_HOME=${IROOT}/nvm
+# Used to avoid nvm's return 2 error.
+# Sourcing this functions if 0 is returned.
+source $NVM_HOME/nvm.sh || 0
+nvm install 0.10.8
+nvm use 0.10.8
 
 
-${NODE_HOME}/bin/npm install
-${NODE_HOME}/bin/node app &
+# update npm before app init
+npm install -g npm
 
 
-# !DO NOT REMOVE!
-#
-# It takes `node app` a few seconds to turn on and 
-# then fork. If you remove this sleep, the parent shell 
-# executing this script will be terminated before the 
-# application has time to awaken and be forked, and 
-# express will fail to be started
-sleep 5
+# run app
+npm install
+node app &

+ 0 - 0
frameworks/JavaScript/koa/README.md


+ 128 - 0
frameworks/JavaScript/koa/app.js

@@ -0,0 +1,128 @@
+var cluster = require('cluster')
+  , numCPUs = require('os').cpus().length;
+
+// Koa Deps
+var koa = require('koa')
+  , route = require('koa-route')
+  , handlebars = require('koa-handlebars')
+  , bodyParser = require('koa-bodyparser')
+  , override = require('koa-override');
+
+// Monk MongoDB Driver Deps
+var monk = require('monk')
+  , wrap = require('co-monk')
+  , db = monk('mongodb://localhost/hello_world')
+  , worlds = wrap(db.get('world'))
+  , fortunes = wrap(db.get('fortune'));
+
+if (cluster.isMaster) {
+  // Fork workers.
+  for (var i = 0; i < numCPUs; i++) {
+    cluster.fork();
+  }
+
+  cluster.on('exit', function(worker, code, signal) {
+    console.log('worker ' + worker.process.pid + ' died');
+  });
+} else {
+  var app = module.exports = koa();
+  app.use(bodyParser());
+  app.use(override());
+  app.use(handlebars({
+    // needed, otherwise missing dir err
+    partialsDir: "views"
+  }));
+
+  // routes
+  app.use(route.get('/json', jsonHandler));
+  app.use(route.get('/db', dbHandler));
+  app.use(route.get('/queries', queriesHandler));
+  app.use(route.get('/fortunes', fortuneHandler));
+  app.use(route.get('/updates', updateHandler));
+  app.use(route.get('/plaintext', textHandler));
+
+  // Helpers
+  function getRandomNumber() {
+    return Math.floor(Math.random()*10000) + 1;
+  };
+
+  function validateParam(param) {
+    var numOfQueries = isNaN(param) ? 1 : param;
+    if (numOfQueries > 500) {
+      numOfQueries = 500;
+    } else if (numOfQueries < 1) {
+      numOfQueries = 1;
+    }
+    return numOfQueries;
+  }
+
+  // Query Helpers
+  function *worldUpdateQuery() {
+    var randomId = getRandomNumber();
+    var randomNumber = getRandomNumber();
+    var result = yield worlds.update(
+      {id: randomId}, 
+      {$set: {randomNumber: randomNumber}}
+    );
+    return {
+      id: randomId,
+      randomNumber: randomNumber
+    }
+  }
+
+  function *worldQuery() {
+    return yield worlds.findOne({id: getRandomNumber()}, '-_id');
+  }
+
+  function *fortunesQuery() {
+    return yield fortunes.find({}, '-_id');
+  }
+
+  // Route handlers
+  function *jsonHandler() {
+    this.body = {
+      message: "Hello, world!"
+    }
+  }
+
+  function *dbHandler() {
+    this.body = yield worldQuery;
+  }
+
+  function *queriesHandler() {
+    var numOfQueries = validateParam(this.query.queries);
+    var queries = [];
+    for (var i = 0; i < numOfQueries; i++) {
+      queries.push(worldQuery);
+    }
+    this.body = yield queries;
+  }
+
+  function *fortuneHandler() {
+    this.set('Server', 'Koa');
+    var fortunes = yield fortunesQuery;
+    fortunes.push({
+      id: 0,
+      message: 'Additional fortune added at request time.'
+    });
+    fortunes.sort(function(a, b) {
+      return a.message < b.message ? -1 : 1;
+    });
+    yield this.render("fortunes", {fortunes: fortunes});
+  }
+
+  function *updateHandler() {
+    var numOfUpdates = validateParam(this.query.queries);
+    var queries = [];
+    for (var i = 0; i < numOfUpdates; i++) {
+      queries.push(worldUpdateQuery);
+    }
+    this.body = yield queries;
+  }
+
+  function *textHandler() {
+    this.body = 'Hello, world!';
+  }
+
+  app.listen(8080);
+}

+ 28 - 0
frameworks/JavaScript/koa/benchmark_config.json

@@ -0,0 +1,28 @@
+{
+  "framework": "koa",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "koa",
+      "language": "JavaScript",
+      "orm": "Raw",
+      "platform": "nodejs",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "koa",
+      "notes": "",
+      "versus": "node"
+    }
+  }]
+}

+ 3 - 0
frameworks/JavaScript/koa/install.sh

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

+ 17 - 0
frameworks/JavaScript/koa/package.json

@@ -0,0 +1,17 @@
+{
+  "name": "koa-tfb",
+  "version": "0.0.1",
+  "description": "Koa tests for TechEmpower Framework Benchmarks.",
+  "main": "app.js",
+  "private": true,
+  "dependencies": {
+    "co-monk": "1.0.0",
+    "koa": "0.18.1",
+    "koa-bodyparser": "1.4.1",
+    "koa-handlebars": "0.5.2",
+    "koa-mongo": "0.3.0",
+    "koa-override": "1.0.0",
+    "koa-route": "2.4.0",
+    "monk": "1.0.1"
+  }
+}

+ 17 - 0
frameworks/JavaScript/koa/setup.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+
+sed -i 's|mongodb://.*/hello_world|mongodb://'"${DBHOST}"'/hello_world|g' app.js
+
+export NVM_HOME=${IROOT}/nvm
+# Used to avoid nvm's return 2 error.
+# Sourcing this functions if 0 is returned.
+source $NVM_HOME/nvm.sh || 0
+nvm install 0.11.16
+nvm use 0.11.16
+
+# update npm before app init
+npm install -g npm
+
+# run app
+npm install
+node --harmony app &

+ 0 - 0
frameworks/JavaScript/koa/source_code


+ 21 - 0
frameworks/JavaScript/koa/views/fortunes.hbs

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

+ 1 - 3
frameworks/JavaScript/nodejs/hello.js

@@ -1,5 +1,3 @@
 #!/bin/bash
 #!/bin/bash
 
 
-export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
-
-fw_depends nodejs
+fw_depends nvm

+ 11 - 15
frameworks/JavaScript/nodejs/setup.sh

@@ -1,21 +1,17 @@
 #!/bin/bash
 #!/bin/bash
-export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
-
 sed -i 's|localhost|'"${DBHOST}"'|g' hello.js
 sed -i 's|localhost|'"${DBHOST}"'|g' hello.js
-sed -i 's|mongodb//.*/hello_world|mongodb//'"${DBHOST}"'/hello_world|g' hello.js
+sed -i 's|mongodb://.*/hello_world|mongodb://'"${DBHOST}"'/hello_world|g' hello.js
 
 
 export NODE_ENV=production
 export NODE_ENV=production
-export NODE_HOME=${IROOT}/node-v0.10.8-linux-x64
-export PATH=$PATH:$NODE_HOME/bin
+export NVM_HOME=${IROOT}/nvm
+# Used to avoid nvm's return 2 error.
+# Sourcing this functions if 0 is returned.
+source $NVM_HOME/nvm.sh || 0
+nvm install 0.10.8
+nvm use 0.10.8
 
 
-${NODE_HOME}/bin/npm install
-${NODE_HOME}/bin/node hello.js &
+# update npm before app init
+npm install -g npm
 
 
-# !DO NOT REMOVE!
-#
-# It takes `node app` a few seconds to turn on and 
-# then fork. If you remove this sleep, the parent shell 
-# executing this script will be terminated before the 
-# application has time to awaken and be forked, and 
-# express will fail to be started
-sleep 5
+npm install
+node hello.js &

+ 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)

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