Browse Source

Merge branch 'master' of te.github.com:TechEmpower/FrameworkBenchmarks

Patrick Falls 12 years ago
parent
commit
be843a976e

+ 13 - 1
installer.py

@@ -54,7 +54,7 @@ class Installer:
     # Java
     #
     
-    self.__run_command("sudo apt-get install openjdk-7-jdk=", True)
+    self.__run_command("sudo apt-get install openjdk-7-jdk", True)
     self.__run_command("sudo apt-get remove --purge openjdk-6-jre openjdk-6-jre-headless", True)
     
     #
@@ -94,6 +94,12 @@ class Installer:
     self.__run_command("sudo cp ../config/php-fpm.conf /usr/local/lib/php-fpm.conf")
     self.__run_command("rm php-5.4.13.tar.gz")
 
+    #
+    # Haskell
+    #
+
+    self.__run_command("sudo apt-get install ghc cabal-install", True)
+
     #######################################
     # Webservers
     #######################################
@@ -218,6 +224,12 @@ class Installer:
     ##############################
     self.__run_command("go/bin/go get github.com/hoisie/web")
 
+    ##############################
+    # Yesod
+    ##############################
+    self.__run_command("cabal update")
+    self.__run_command("cabal install yesod persistent-mysql")
+
     ##############################################################
     #
     # System Tools

+ 24 - 0
yesod/README.md

@@ -0,0 +1,24 @@
+# Yesod Benchmarking Test
+
+This is the Yesod portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+* [Controllers](bench/Application.hs)
+* [Model](bench/config/models)
+
+## Infrastructure Software Versions
+The tests were run with:
+* GHC 7.4.1
+* Yesod 1.1.9.2
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:3000/json
+
+### Data-Store/Database Mapping Test
+
+http://localhost:3000/db
+
+### Variable Query Test
+
+http://localhost:3000/db2/2

+ 0 - 0
yesod/__init__.py


+ 8 - 0
yesod/bench/.gitignore

@@ -0,0 +1,8 @@
+dist*
+static/tmp/
+config/client_session_key.aes
+*.hi
+*.o
+*.sqlite3
+.hsenv*
+yesod-devel/

+ 52 - 0
yesod/bench/Application.hs

@@ -0,0 +1,52 @@
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+module Application
+    ( makeApplication
+    , makeFoundation
+    ) where
+
+import Import
+import Control.Monad
+import System.Random
+
+import qualified Database.Persist.Store
+import Database.Persist.Store (PersistValue (..))
+import Network.HTTP.Conduit (newManager, def)
+import Yesod.Default.Config
+
+
+import Settings
+
+getJsonR :: Handler RepJson
+getJsonR = jsonToRepJson $ object ["message" .= ("Hello, World!" :: Text)]
+
+getDBR :: Handler RepJson
+getDBR = do
+    (i, _) <- liftIO $ randomR (1, 10000) <$> newStdGen
+    liftIO $ print i
+    Just o <- runDB $ get $ Key $ PersistInt64 i
+    jsonToRepJson $ object ["id" .= i, "randomNumber" .= worldRandomNumber o]
+
+getDB2R :: Int -> Handler RepJson
+getDB2R n = do
+    os <- runDB $ replicateM n $ do
+        (i, _) <- liftIO $ randomR (1, 10000) <$> newStdGen
+        Just o <- get $ Key $ PersistInt64 i
+        return $ object ["id" .= i, "randomNumber" .= worldRandomNumber o]
+
+    jsonToRepJson $ array os
+
+mkYesodDispatch "App" resourcesApp
+
+makeApplication :: AppConfig DefaultEnv Extra -> IO Application
+makeApplication conf = makeFoundation conf >>= toWaiAppPlain
+
+makeFoundation :: AppConfig DefaultEnv Extra -> IO App
+makeFoundation conf = do
+    manager <- newManager def
+    dbconf <- withYamlEnvironment "config/mysql.yml" (appEnv conf)
+              Database.Persist.Store.loadConfig >>=
+              Database.Persist.Store.applyEnv
+    p <- Database.Persist.Store.createPoolConfig (dbconf :: Settings.PersistConfig)
+    let foundation = App conf p manager dbconf
+
+    return foundation

+ 36 - 0
yesod/bench/Foundation.hs

@@ -0,0 +1,36 @@
+module Foundation where
+
+import Prelude
+import Yesod
+import Yesod.Default.Config
+import Network.HTTP.Conduit (Manager)
+import qualified Settings
+import qualified Database.Persist.Store
+import Database.Persist.GenericSql
+import Settings (Extra (..))
+
+data App = App
+    { settings :: AppConfig DefaultEnv Extra
+    , connPool :: Database.Persist.Store.PersistConfigPool Settings.PersistConfig -- ^ Database connection pool.
+    , httpManager :: Manager
+    , persistConfig :: Settings.PersistConfig
+    }
+
+mkYesodData "App" $(parseRoutesFile "config/routes")
+
+type Form x = Html -> MForm App App (FormResult x, Widget)
+
+instance Yesod App where
+    approot = ApprootMaster $ appRoot . settings
+
+instance YesodPersist App where
+    type YesodPersistBackend App = SqlPersist
+    runDB f = do
+        master <- getYesod
+        Database.Persist.Store.runPool
+            (persistConfig master)
+            f
+            (connPool master)
+
+getExtra :: Handler Extra
+getExtra = fmap (appExtra . settings) getYesod

+ 27 - 0
yesod/bench/Import.hs

@@ -0,0 +1,27 @@
+module Import
+    ( module Import
+    ) where
+
+import           Prelude              as Import hiding (head, init, last,
+                                                 readFile, tail, writeFile)
+import           Yesod                as Import hiding (Route (..))
+
+import           Control.Applicative  as Import (pure, (<$>), (<*>))
+import           Data.Text            as Import (Text)
+
+import           Foundation           as Import
+import           Model                as Import
+import           Settings             as Import
+
+#if __GLASGOW_HASKELL__ >= 704
+import           Data.Monoid          as Import
+                                                 (Monoid (mappend, mempty, mconcat),
+                                                 (<>))
+#else
+import           Data.Monoid          as Import
+                                                 (Monoid (mappend, mempty, mconcat))
+
+infixr 5 <>
+(<>) :: Monoid m => m -> m -> m
+(<>) = mappend
+#endif

+ 12 - 0
yesod/bench/Model.hs

@@ -0,0 +1,12 @@
+module Model where
+
+import Prelude
+import Yesod
+import Database.Persist.Quasi
+
+-- You can define all of your database entities in the entities file.
+-- You can find more information on persistent and how to declare entities
+-- at:
+-- http://www.yesodweb.com/book/persistent/
+share [mkPersist sqlOnlySettings, mkMigrate "migrateAll"]
+    $(persistFileWith lowerCaseSettings "config/models")

+ 21 - 0
yesod/bench/Settings.hs

@@ -0,0 +1,21 @@
+-- | Settings are centralized, as much as possible, into this file. This
+-- includes database connection settings, static file locations, etc.
+-- In addition, you can configure a number of different aspects of Yesod
+-- by overriding methods in the Yesod typeclass. That instance is
+-- declared in the Foundation.hs file.
+module Settings where
+
+import Prelude
+import Database.Persist.MySQL (MySQLConf)
+import Yesod.Default.Config
+import Yesod.Default.Util
+import Data.Yaml
+
+type PersistConfig = MySQLConf
+
+data Extra = Extra
+    { 
+    } deriving Show
+
+parseExtra :: DefaultEnv -> Object -> Parser Extra
+parseExtra _ o = return Extra

+ 8 - 0
yesod/bench/app/main.hs

@@ -0,0 +1,8 @@
+import Prelude              (IO)
+import Yesod.Default.Config (fromArgs)
+import Yesod.Default.Main   (defaultMain)
+import Settings             (parseExtra)
+import Application          (makeApplication)
+
+main :: IO ()
+main = defaultMain (fromArgs parseExtra) makeApplication

+ 89 - 0
yesod/bench/bench.cabal

@@ -0,0 +1,89 @@
+name:              bench
+version:           0.0.0
+cabal-version:     >= 1.8
+build-type:        Simple
+
+Flag dev
+    Description:   Turn on development settings, like auto-reload templates.
+    Default:       False
+
+Flag library-only
+    Description:   Build for use with "yesod devel"
+    Default:       False
+
+library
+    exposed-modules: Application
+                     Foundation
+                     Import
+                     Model
+                     Settings
+
+    if flag(dev) || flag(library-only)
+        cpp-options:   -DDEVELOPMENT
+        ghc-options:   -Wall -O0
+    else
+        ghc-options:   -Wall -O2
+
+    extensions: TemplateHaskell
+                QuasiQuotes
+                OverloadedStrings
+                NoImplicitPrelude
+                CPP
+                MultiParamTypeClasses
+                TypeFamilies
+                GADTs
+                GeneralizedNewtypeDeriving
+                FlexibleContexts
+                EmptyDataDecls
+                NoMonomorphismRestriction
+
+    build-depends: base                          >= 4          && < 5
+                 -- , yesod-platform                >= 1.1        && < 1.2
+                 , yesod                         >= 1.1.5      && < 1.2
+                 , yesod-core                    >= 1.1.7      && < 1.2
+                 , yesod-default                 >= 1.1        && < 1.2
+                 , text                          >= 0.11       && < 0.12
+                 , persistent                    >= 1.1        && < 1.2
+                 , persistent-mysql              >= 1.1        && < 1.2
+                 , persistent-template           >= 1.1.1      && < 1.2
+                 , template-haskell
+                 , monad-control                 >= 0.3        && < 0.4
+                 , wai-extra                     >= 1.3        && < 1.4
+                 , yaml                          >= 0.8        && < 0.9
+                 , http-conduit                  >= 1.8        && < 1.10
+                 , directory                     >= 1.1        && < 1.3
+                 , warp                          >= 1.3        && < 1.4
+                 , data-default
+                 , aeson
+                 , conduit                       >= 1.0
+                 , monad-logger                  >= 0.3
+                 , fast-logger                   >= 0.3
+                 , random                        >= 1.0
+
+executable         bench
+    if flag(library-only)
+        Buildable: False
+
+    main-is:           main.hs
+    hs-source-dirs:    app
+    build-depends:     base
+                     , bench
+                     , yesod-default
+
+    ghc-options:       -threaded -O2 -rtsopts
+
+test-suite test
+    type:              exitcode-stdio-1.0
+    main-is:           main.hs
+    hs-source-dirs:    tests
+    ghc-options:       -Wall
+
+    build-depends: base
+                 , bench
+                 , yesod-test >= 0.3 && < 0.4
+                 , yesod-default
+                 , yesod-core
+                 , persistent
+                 , persistent-mysql
+                 , resourcet
+                 , monad-logger

+ 2 - 0
yesod/bench/config/models

@@ -0,0 +1,2 @@
+World
+    randomNumber Int sql=randomNumber

+ 21 - 0
yesod/bench/config/mysql.yml

@@ -0,0 +1,21 @@
+Default: &defaults
+  user: benchmarkdbuser
+  password: benchmarkdbpass
+  host: 127.0.0.1
+  port: 3306
+  database: hello_world
+  poolsize: 10
+
+Development:
+  <<: *defaults
+
+Testing:
+  <<: *defaults
+
+Staging:
+  poolsize: 100
+  <<: *defaults
+
+Production:
+  poolsize: 100
+  <<: *defaults

+ 3 - 0
yesod/bench/config/routes

@@ -0,0 +1,3 @@
+/json           JsonR   GET
+/db             DBR     GET
+/db2/#Int       DB2R    GET

+ 18 - 0
yesod/bench/config/settings.yml

@@ -0,0 +1,18 @@
+Default: &defaults
+  host: "*4" # any IPv4 host
+  port: 3000
+  approot: "http://localhost:3000"
+  #analytics: UA-YOURCODE
+
+Development:
+  <<: *defaults
+
+Testing:
+  <<: *defaults
+
+Staging:
+  <<: *defaults
+
+Production:
+  #approot: "http://www.example.com"
+  <<: *defaults

+ 13 - 0
yesod/benchmark_config

@@ -0,0 +1,13 @@
+{
+  "framework": "yesod",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/db2/",
+      "port": 3000,
+      "sort": 37
+    }
+  }]
+}

+ 28 - 0
yesod/setup.py

@@ -0,0 +1,28 @@
+
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args):
+  setup_util.replace_text("yesod/bench/config/mysql.yml", "host: .*", "host: " + args.database_host)
+  
+  subprocess.check_call("cabal configure", shell=True, cwd="yesod/bench")
+  subprocess.check_call("cabal build", shell=True, cwd="yesod/bench")
+
+  heap = args.max_threads
+  subprocess.Popen("dist/build/bench/bench Production +RTS -A"+str(heap)+"m -N" + str(args.max_threads) + " > /dev/null", shell=True, cwd="yesod/bench")
+  return 0
+
+def stop():
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'bench' in line:
+      try:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+      except OSError:
+        pass
+
+  return 0