Browse Source

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

Masahiro Nagano 11 years ago
parent
commit
a359ef617e

+ 1 - 1
config/benchmark_profile

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

+ 1 - 1
evhttp-sharp/setup.py

@@ -14,7 +14,7 @@ def start(args, logfile, errfile):
     # build
     subprocess.check_call("rm -rf bin obj", shell=True, cwd=app, stdout=logfile, stderr=errfile)
     subprocess.check_call("xbuild /p:Configuration=Release", shell=True, cwd=app, stdout=logfile, stderr=errfile)
-    
+    os.environ['MONO_GC_PARAMS']="nursery-size=64m"
     subprocess.Popen("mono -O=all bin/Release/EvHttpSharpBenchmark.exe 127.0.0.1 8085 " + str(args.max_threads) + " &", shell=True, cwd=app, stdout=logfile, stderr=errfile)
     return 0
   except subprocess.CalledProcessError:

+ 4 - 3
evhttp-sharp/src/Program.cs

@@ -15,8 +15,9 @@ namespace EvHttpSharpBenchmark
 
 		static void Main (string[] args)
 		{
-			var host = new EventHttpListener(Handler);
-			host.Start(args[0], ushort.Parse(args[1]), int.Parse(args[2]));
+            LibLocator.Init();
+		    var host = new EventHttpMultiworkerListener(Handler, int.Parse(args[2]));
+		    host.Start(args[0], ushort.Parse(args[1]));
 		}
 
 		private static void Handler(EventHttpRequest req)
@@ -27,7 +28,7 @@ namespace EvHttpSharpBenchmark
 			if (!req.Uri.Contains("plaintext"))
 			{
 				var sw = new StringWriter();
-				Serializer.Serialize(sw, new {message = "Hello, world"});
+				Serializer.Serialize(sw, new {message = "Hello, World!"});
 				resp = sw.ToString();
 				headers["Content-Type"] = "application/json";
 			}

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


+ 5 - 3
express/app.js

@@ -10,7 +10,7 @@ var cluster = require('cluster')
   , mongoose = require('mongoose')
   , async = require('async')
   , conn = mongoose.connect('mongodb://localhost/hello_world')
-  , connMap = { user: 'benchmarkdbuser', password: 'benchmarkdbpass', database: 'hello_world', host: 'localhost' };
+  , connMap = { user: 'benchmarkdbuser', password: 'benchmarkdbpass', database: 'hello_world', host: 'localhost', charset: 'utf8' };
 
 var Schema = mongoose.Schema
   , ObjectId = Schema.ObjectId;
@@ -89,10 +89,12 @@ if (cluster.isMaster) {
   app.get('/mysql-orm', function(req, res) {
     if (windows) return res.send(501, 'Not supported on windows');
     
-    var queries = req.query.queries || 1
+    var queries = isNaN(req.query.queries) ? 1 : parseInt(req.query.queries, 10)
       , worlds  = []
       , queryFunctions = [];
 
+    queries = Math.min(Math.max(queries, 1), 500);
+
     for (var i = 1; i <= queries; i++ ) {
       queryFunctions.push(function(callback) {
         World.findById(Math.floor(Math.random()*10000) + 1, function (err, world) {
@@ -103,7 +105,7 @@ if (cluster.isMaster) {
     }
 
     async.parallel(queryFunctions, function(err, results) {
-      if (queries == 1) {
+      if (!req.query.queries) {
         worlds = worlds[0];
       }
       res.send(worlds);

+ 1 - 5
grails/README.md

@@ -4,11 +4,7 @@ This is the Grails portion of a [benchmarking test suite](../) comparing a varie
 
 ## Infrastructure Software Versions
 The tests were run with:
-* [Grails 2.3.6](http://grails.org/)
-* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
-* [Resin 4.0.34](http://www.caucho.com/)
-* [MySQL 5.5.29](https://dev.mysql.com/)
-
+* [Grails 2.4.1](http://grails.org/)
 
 ## Test URLs
 

+ 1 - 1
grails/hello/application.properties

@@ -1,6 +1,6 @@
 #Grails Metadata file
 #Tue Feb 25 10:29:09 EET 2014
-app.grails.version=2.3.6
+app.grails.version=2.4.1
 app.name=hello
 app.servlet.version=2.5
 app.version=0.1

+ 2 - 2
grails/hello/grails-app/conf/BuildConfig.groovy

@@ -63,7 +63,7 @@ grails.project.dependency.resolution = {
     }
 
     plugins {
-        runtime ":hibernate:3.6.10.8"
+        runtime ":hibernate:3.6.10.16"
         //runtime ":jquery:1.10.2"
         //runtime ":resources:1.2.1"
 
@@ -72,6 +72,6 @@ grails.project.dependency.resolution = {
         //runtime ":cached-resources:1.0"
         //runtime ":yui-minify-resources:0.1.4"
 
-        build ":tomcat:7.0.50.1"
+        build ":tomcat:7.0.54"
     }
 }

+ 1 - 0
grails/hello/grails-app/conf/DataSource.groovy

@@ -27,6 +27,7 @@ dataSource {
         validationInterval=15000
         jdbcInterceptors="ConnectionState;StatementCache"
         defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_UNCOMMITTED
+        defaultAutoCommit=true
         dbProperties = this.loadProperties("classpath:mysql-connection.properties")
     }
 }

+ 11 - 9
grails/hello/grails-app/controllers/hello/HelloController.groovy

@@ -7,7 +7,8 @@ import groovy.transform.TypeCheckingMode;
 
 import java.util.concurrent.ThreadLocalRandom
 
-import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Propagation;
+import org.hibernate.Session;
 
 @CompileStatic
 class HelloController {
@@ -28,7 +29,6 @@ class HelloController {
     }
 
     // Test type 2: Single database query
-    @Transactional(readOnly=true)
     def db() {
         def random = ThreadLocalRandom.current()
         def world = World.read(random.nextInt(10000) + 1)
@@ -36,7 +36,6 @@ class HelloController {
     }
     
     // Test type 3: Multiple database queries
-    @Transactional(readOnly=true)
     def queries(int queries) {
         def worlds = fetchRandomWorlds(queries, false)
         render worlds as JSON
@@ -55,10 +54,15 @@ class HelloController {
         List<World> worlds = new ArrayList<World>(queries)
         if (updateAlso) {
             Arrays.sort(worldIds)
-            for (int id : worldIds) {
-                World world = World.lock(id)
-                world.randomNumber = random.nextInt(10000) + 1
-                worlds.add(world)
+            World.withSession { Session session ->
+                for (int id : worldIds) {
+                    World world = World.get(id)
+                    world.randomNumber = random.nextInt(10000) + 1
+                    worlds.add(world)
+                    // flush changes
+                    session.flush()
+                    session.clear()
+                }
             }
         } else {
             for (int id : worldIds) {
@@ -69,7 +73,6 @@ class HelloController {
     }
     
     // Test type 4: Fortunes
-    @Transactional(readOnly=true)
     def fortunes() {
         def fortunes = Fortune.getAll()
         fortunes << new Fortune(id: 0, message: 'Additional fortune added at request time.')
@@ -83,7 +86,6 @@ class HelloController {
         render worlds as JSON
     }
 
-    @Transactional(isolation=Isolation.READ_COMMITTED)
     private List updateWorlds(int queries) {
         fetchRandomWorlds(queries, true)
     }

+ 0 - 3
grails/hello/web-app/WEB-INF/applicationContext.xml

@@ -6,7 +6,6 @@
 	<bean id="grailsApplication" class="org.codehaus.groovy.grails.commons.GrailsApplicationFactoryBean">
 		<description>Grails application factory bean</description>
 		<property name="grailsDescriptor" value="/WEB-INF/grails.xml" />
-		<property name="grailsResourceLoader" ref="grailsResourceLoader" />
 	</bean>
 
 	<bean id="pluginManager" class="org.codehaus.groovy.grails.plugins.GrailsPluginManagerFactoryBean">
@@ -22,8 +21,6 @@
 		<property name="pluginManager" ref="pluginManager" />
 	</bean>
 
-	<bean id="grailsResourceLoader" class="org.codehaus.groovy.grails.commons.GrailsResourceLoaderFactoryBean" />
-
 	<bean id="characterEncodingFilter" class="org.springframework.web.filter.CharacterEncodingFilter">
 		<property name="encoding">
 			<value>utf-8</value>

+ 7 - 5
luminus/hello/project.clj

@@ -3,15 +3,16 @@
   "luminus"
   :dependencies
   [[org.clojure/clojure "1.5.1"]
-   [lib-noir "0.7.9"]
+   [lib-noir "0.8.2"]
    [compojure "1.1.6"]
    [ring-server "0.3.1"]
    [selmer "0.5.7"]
    [com.taoensso/timbre "2.7.1"]
    [com.postspectacular/rotor "0.1.0"]
-   [com.taoensso/tower "1.5.1"]
+   [com.taoensso/tower "2.0.2"]
    [mysql/mysql-connector-java "5.1.28"]
-   [korma "0.3.0-RC5"]
+   [korma "0.3.0-RC6"]
+   [c3p0/c3p0 "0.9.1.2"]
    [log4j
     "1.2.17"
     :exclusions
@@ -24,11 +25,12 @@
    :init hello.handler/init,
    :destroy hello.handler/destroy}
   :profiles
-  {:production
+  {:uberjar {:aot :all}
+   :production
    {:ring
     {:open-browser? false, :stacktraces? false, :auto-reload? false}},
    :dev
-   {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.1"]]}}
+   {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]]}}
   :url
   "http://example.com/FIXME"
   :plugins

+ 3 - 3
luminus/hello/src/hello/handler.clj

@@ -4,7 +4,7 @@
   (:require [noir.util.middleware :as middleware]
             [compojure.route :as route]
             [taoensso.timbre :as timbre]
-            [com.postspectacular.rotor :as rotor]))
+            [taoensso.timbre.appenders.rotor :as rotor]))
 
 (defroutes app-routes
   (route/resources "/")
@@ -25,11 +25,11 @@
      :enabled? true
      :async? false ; should be always false for rotor
      :max-message-per-msecs nil
-     :fn rotor/append})
+     :fn rotor/appender-fn})
 
   (timbre/set-config!
     [:shared-appender-config :rotor]
-    {:path "hello.log" :max-size 10000 :backlog 10})
+    {:path "{{sanitized}}.log" :max-size (* 512 1024) :backlog 10})
 
   (timbre/info "hello started successfully"))
 

+ 1 - 1
phreeze/benchmark_config

@@ -5,7 +5,7 @@
       "setup_file": "setup",
       "json_url": "/index.php?json",
       "db_url": "/index.php?db",
-      "query_url": "/index.php?db&queries=",
+      "query_url": "/index.php?query&queries=",
       "fortune_url": "/index.php?fortunes",
       "update_url": "/index.php?updates&queries=",
       "plaintext_url": "/index.php?plaintext",

+ 3 - 0
phreeze/index.php

@@ -23,6 +23,7 @@ $route_map = array(
 		'GET:' => array('route' => 'Test.JSON'),
 		'GET:json' => array('route' => 'Test.JSON'),
 		'GET:db' => array('route' => 'Test.DB'),
+		'GET:query' => array('route' => 'Test.Query'),
 		'GET:fortunes' => array('route' => 'Test.Fortunes'),
 		'GET:updates' => array('route' => 'Test.Updates'),
 		'GET:plaintext' => array('route' => 'Test.PlainText')
@@ -30,6 +31,8 @@ $route_map = array(
 
 $router = new SimpleRouter('/','Test.JSON',$route_map);
 
+Dispatcher::$FAST_LOOKUP = true;
+
 Dispatcher::Dispatch(
 	$phreezer,
 	null,

+ 34 - 14
phreeze/libs/Controller/TestController.php

@@ -40,24 +40,44 @@ class TestController extends Controller
 	public function DB()
 	{
 		require_once("Model/World.php");
-		
-		// Read number of queries to run from URL parameter
+
+		$id = mt_rand(1, 10000);
+		$world = $this->Phreezer->Get("World",$id);
+		$this->RenderJSON($world,'',true);
+	}
+	
+	
+	/**
+	 * Test route that connects to the database and outputs
+	 * the number of rows specified in the querystring argument "queries"
+	 */
+	public function Query()
+	{
+		require_once("Model/World.php");
+	
+		// Read number of queries to run from URL parameter
 		$query_count = RequestUtil::Get('queries',1);
-
-		$arr = array();
-		
-		for ($i = 0; $i < $query_count; $i++) {
 		
-			$id = mt_rand(1, 10000);
-			
-			$world = $this->Phreezer->Get("World",$id);
-			
-			// convert the Phreezable object into a simple structure for output
-			$arr[] = array('id'=>$world->Id,'randomNumber'=>$world->Randomnumber);
+		// make sure the query count paramter is in range
+		if (!is_numeric($query_count)) {
+			$query_count = 1;
 		}
-		
-		$this->RenderJSON($arr);
+		else {
+			$query_count = max(1,min($query_count,500));
+		}
+		
+		$arr = array();
+			
+		for ($i = 0; $i < $query_count; $i++) {
+				
+			$id = mt_rand(1, 10000);
 
+			// convert the Phreezable object into a simple structure for output
+			$arr[] = $this->Phreezer->Get("World",$id)->ToObject();
+		}
+			
+		$this->RenderJSON($arr);
+	
 	}
 	
 	/**

+ 10 - 1
phreeze/libs/Model/World.php

@@ -39,11 +39,20 @@ class World extends WorldDAO
 		// the controller create/update methods validate before saving.  this will be a
 		// redundant validation check, however it will ensure data integrity at the model
 		// level based on validation rules.  comment this line out if this is not desired
-		if (!$this->Validate()) throw new Exception('Unable to Save World: ' .  implode(', ', $this->GetValidationErrors()));
+		// if (!$this->Validate()) throw new Exception('Unable to Save World: ' .  implode(', ', $this->GetValidationErrors()));
 
 		// OnSave must return true or eles Phreeze will cancel the save operation
 		return true;
 	}
+	
+	/**
+	 * @return multitype:NULL boolean
+	 */
+	public function ToObject($options = null)
+	{
+		$obj = array('id'=>$this->Id,'randomNumber'=>$this->Randomnumber);
+		return $obj;
+	}
 
 }
 

+ 25 - 5
phreeze/libs/verysimple/Phreeze/Dispatcher.php

@@ -12,7 +12,7 @@ require_once("verysimple/Util/ExceptionThrower.php");
  * @author     VerySimple Inc.
  * @copyright  1997-2007 VerySimple, Inc.
  * @license    http://www.gnu.org/licenses/lgpl.html  LGPL
- * @version    2.6
+ * @version    2.7
  */
 class Dispatcher
 {
@@ -21,6 +21,14 @@ class Dispatcher
 	 * @var boolean default = true
 	 */
 	static $IGNORE_DEPRECATED = true;
+	
+	/**
+	 * FAST_LOOKUP mode instructs the dispatcher to assume that the controller and method
+	 * supplied by the router are valid and not do any checking for the existance of
+	 * the controller file or the method before trying to call it
+	 * @var boolean use fast lookup mode if true 
+	 */
+	static $FAST_LOOKUP = false;
 
 	/**
 	 * This is a case-insensitive version of file_exists
@@ -59,16 +67,28 @@ class Dispatcher
 	 */
 	static function Dispatch($phreezer,$renderEngine,$action='',$context=null,$router=null)
 	{
-		if ($router == null)
-		{
+		if ($router == null) {
 			require_once('GenericRouter.php');
 			$router = new GenericRouter();
 		}
 
+		// get the route and normalize the controller name
 		list($controller_param,$method_param) = $router->GetRoute( $action );
-
-		// normalize the input
 		$controller_class = $controller_param."Controller";
+	
+		if (self::$FAST_LOOKUP) {
+
+			if (!class_exists($controller_class)) {
+				$controller_file = "Controller/$controller_class.php";
+				include_once $controller_file;
+			}
+			
+			$controller = new $controller_class($phreezer,$renderEngine,$context,$router);
+			$controller->$method_param();
+			
+			return true;
+		}
+		
 		
 		// if the controller was in a sub-directory, get rid of the directory path
 		$slashPos = strpos($controller_class,'/');

+ 3 - 8
phreeze/templates/TestFortunes.php

@@ -1,16 +1,11 @@
 <!DOCTYPE html>
 <html>
-<head>
-<title>Fortunes</title>
-</head>
+<head><title>Fortunes</title></head>
 <body>
 <table>
-<tr>
-<th>id</th>
-<th>message</th>
-</tr>
+<tr><th>id</th><th>message</th></tr>
 <?php foreach ($model['fortunes'] as $fortune) {
-	echo '<tr><td>' . $fortune->Id . '</td><td>' . htmlspecialchars($fortune->Message) . '</td></tr>' . "\n";
+	echo '<tr><td>' . $fortune->Id . '</td><td>' . htmlspecialchars($fortune->Message, ENT_QUOTES | ENT_HTML5) . '</td></tr>';
 } ?>
 </table>
 </body>

+ 3 - 3
play-slick/app/controllers/Application.scala

@@ -5,7 +5,7 @@ import play.api.mvc._
 import play.api.libs.json.Json
 import java.util.concurrent._
 import scala.concurrent._
-import models.{Worlds, World, Fortunes, Fortune}
+import models.{Worlds, World, Fortunes, Fortune, WorldsTableQuery, FortunesTableQuery}
 import utils._
 import scala.concurrent.Future
 
@@ -29,8 +29,8 @@ object Application extends Controller {
     new NamedThreadFactory("dbEc"))
   private val dbEc = ExecutionContext.fromExecutorService(tpe)
 
-  private val worldsTable = new Worlds
-  private val fortunesTable = new Fortunes
+  private val worldsTable = new WorldsTableQuery
+  private val fortunesTable = new FortunesTableQuery
 
   // A predicate for checking our ability to service database requests is determined by ensuring that the request
   // queue doesn't fill up beyond a certain threshold. For convenience we use the max number of connections * the max

+ 7 - 6
play-slick/app/models/Fortune.scala

@@ -5,15 +5,16 @@ import play.api.db.slick.Config.driver.simple._
 import play.api.db.slick.DB
 
 
-class Fortunes extends Table[Fortune]("Fortune") {
+class Fortunes(tag: Tag) extends Table[Fortune](tag, "Fortune") {
   def id = column[Long]("id", O.PrimaryKey)
   def message = column[String]("message")
-  def * = id ~ message <> (Fortune.apply _, Fortune.unapply _)
-
-  val byId = createFinderBy(_.id)
-
+  def * = (id, message) <> (Fortune.tupled, Fortune.unapply _)
+}
+class FortunesTableQuery extends TableQuery(new Fortunes(_)){
+  val byId = this.findBy(_.id)
+  val all = Compiled{this:Query[Fortunes,Fortune]}
   def getAll(): List[Fortune] = DB.withSession { implicit session =>
-    Query(this).list
+    all.list
   }
 }
 

+ 8 - 7
play-slick/app/models/World.scala

@@ -6,23 +6,24 @@ import play.api.db.slick.DB
 import play.api.libs.json._
 import play.api.libs.functional.syntax._
 
-class Worlds extends Table[World]("World") {
+class Worlds(tag: Tag) extends Table[World](tag, "World") {
   def id = column[Int]("id", O.PrimaryKey)
   def randomNumber = column[Long]("randomNumber")
-  def * = id ~ randomNumber <> (World.apply _, World.unapply _)
-
-  val byId = createFinderBy(_.id)
+  def * = (id, randomNumber) <> ((World.apply _).tupled, World.unapply _)
+}
+class WorldsTableQuery extends TableQuery(new Worlds(_)){
+  val byId = this.findBy(_.id)
 
   def findById(id: Int): Option[World] = DB.withSession { implicit session =>
       byId(id).firstOption
   }
 
+  val updateQuery = Compiled{ (id: Column[Int]) => this.where(_.id === id) }
   def updateRandom(world: World) {
     DB.withSession { implicit session: Session =>
-      this.where(_.id === world.id.bind).update(world)
+      updateQuery(world.id).update(world)
     }
-  }
-
+  }  
 }
 
 case class World(id: Int, randomNumber: Long)

+ 1 - 1
play-slick/project/Build.scala

@@ -11,7 +11,7 @@ object ApplicationBuild extends Build {
     jdbc,
     anorm,
     "mysql" % "mysql-connector-java" % "5.1.22",
-    "com.typesafe.play" %% "play-slick" % "0.5.0.8" 
+    "com.typesafe.play" %% "play-slick" % "0.6.0.1"
   )
 
   val main = play.Project(appName, appVersion, appDependencies).settings(

+ 2 - 2
toolset/setup/linux/installer.py

@@ -295,8 +295,8 @@ class Installer:
     #
     # Grails
     #
-    self.__download("http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.3.6.zip")
-    self.__run_command("unzip -o grails-2.3.6.zip")
+    self.__download("http://dist.springframework.org.s3.amazonaws.com/release/GRAILS/grails-2.4.1.zip")
+    self.__run_command("unzip -o grails-2.4.1.zip")
 
     #
     # Play 2