Browse Source

Merge branch 'master' of github.com:TechEmpower/FrameworkBenchmarks into add-restexpress

Todd Fredrich 12 years ago
parent
commit
3d11a48f9a

+ 42 - 0
README.md

@@ -121,6 +121,48 @@ Assuming this finished without error, we're ready to start the test suite:
 
 This will run the full set of tests. Results of all the tests will output to ~/FrameworkBenchmarks/results/unique-machine-name/*timestamp*.
 
+### Windows Instructions
+Generously provided by @pdonald
+
+Note: The following tests are the only known tests to run on Windows
+* aspnet
+* aspnet-mysql-raw
+* aspnet-postgresql-raw
+* aspnet-mongodb-raw
+* aspnet-mysql-entityframework
+* aspnet-postgres-entityframework
+* nodejs
+* nodejs-mongodb
+* nodejs-mongodb-raw
+* express
+* express-mongodb
+* kohana
+* kohana-raw
+* codeigniter
+* codeigniter-raw
+
+Server installation scripts for Windows Server 2012 R2 on Amazon EC2.
+
+Instructions:
+
+* Create an instance from the Microsoft Windows Server 2012 Base image on Amazon EC2
+* Connect to it via Remote Desktop
+* Copy installer-bootstrap.ps1 from this repo to the server (for files CTRL-C + CTRL-V works alright)
+* Copy your client private key too while you're at it
+* Right click on the installer script and select Run with PowerShell
+* It will ask something, just hit enter
+* It will install git and then launch installer.ps1 from the repo which will install everything else
+* Installation shouldn't take more than 5 to 10 minutes
+* Then you have a working console: try python, git, ssh, curl, node etc. everything works + PowerShell goodies
+
+The client/database machine is still assumed to be a Linux box, you can install just the client software via
+  python run-tests.py -s server-ip -c client-ip -i "C:\Users\Administrator\Desktop\client.key" --install-software --install client --list-tests
+
+Now you can run tests:
+
+  python run-tests.py -s server-ip -c client-ip -i "C:\Users\Administrator\Desktop\client.key" --max-threads 2 --duration 30 --sleep 5 --name win --test aspnet --type all
+
+
 ## Result Files
 
 After a test run, the directory ~/FrameworkBenchmarks/results/machine-name/timestamp will contains all the result files. In this folder are four files: three CSV files, one for each of the test types (json, db, query), and a single results.json file that contains all the results as well as some additional information. The results.json file is what we use to drive our blog post, and may or may not be useful to you. There are three subdirectories: one for each of the test types (json, db, query), each of these directories contain the raw weighttp results for each framework.

+ 3 - 3
go/src/hello/hello.go

@@ -31,7 +31,7 @@ type Fortune struct {
 const (
 	ConnectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world?charset=utf8"
 	WorldSelect        = "SELECT id, randomNumber FROM World where id = ?"
-	WorldUpdate				 = "UPDATE World SET randomNumber = ? where id = ?"
+	WorldUpdate        = "UPDATE World SET randomNumber = ? where id = ?"
 	FortuneSelect      = "SELECT id, message FROM Fortune;"
 	WorldRowCount      = 10000
 	MaxConnectionCount = 100
@@ -40,9 +40,9 @@ const (
 var (
 	tmpl = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
 
-	worldStatement    *sql.Stmt
+	worldStatement   *sql.Stmt
 	fortuneStatement *sql.Stmt
-	updateStatement		*sql.Stmt
+	updateStatement  *sql.Stmt
 )
 
 func main() {

+ 6 - 3
installer.py

@@ -7,8 +7,11 @@ class Installer:
   # install_software
   ############################################################
   def install_software(self):
-    self.__install_server_software()
-    self.__install_client_software()
+    if self.benchmarker.install == 'all' or self.benchmarker.install == 'server':
+        self.__install_server_software()    
+
+    if self.benchmarker.install == 'all' or self.benchmarker.install == 'client':
+        self.__install_client_software()
   ############################################################
   # End install_software
   ############################################################
@@ -99,7 +102,7 @@ class Installer:
     #
 
     self.__run_command("curl -L http://cpanmin.us | perl - --sudo App::cpanminus")
-    self.__run_command("cpanm -S DBI DBD::mysql Kelp Dancer Mojolicious Kelp::Module::JSON::XS Dancer::Plugin::Database Starman Plack JSON")
+    self.__run_command("cpanm -S DBI DBD::mysql Kelp Dancer Mojolicious Kelp::Module::JSON::XS Dancer::Plugin::Database Starman Plack JSON Web::Simple DBD::Pg")
 
     #
     # php

+ 1 - 2
php-silex/setup.py

@@ -1,4 +1,3 @@
-
 import subprocess
 import sys
 import setup_util
@@ -17,7 +16,7 @@ def start(args):
     #subprocess.check_call("sudo a2ensite cake", shell=True)
     #subprocess.check_call("sudo chown -R www-data:www-data cake", shell=True)
     #subprocess.check_call("sudo /etc/init.d/apache2 start", shell=True)
-    subprocess.check_call("composer.phar install", shell=True, cwd="php-silex")        
+    subprocess.check_call("composer.phar install --optimize-autoloader", shell=True, cwd="php-silex")        
     subprocess.check_call("sudo php-fpm --fpm-config config/php-fpm.conf -g " + home + "/FrameworkBenchmarks/php-silex/deploy/php-fpm.pid", shell=True)
     subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/php-silex/deploy/nginx.conf", shell=True)
     return 0

+ 1 - 0
run-tests.py

@@ -17,6 +17,7 @@ parser.add_argument('-d', '--database-host')
 parser.add_argument('-i', dest='identity_file', help='ssh key to ssh from the server instance to the client instance.')
 parser.add_argument('-p', dest='password_prompt', action='store_true')
 parser.add_argument('--install-software', action='store_true', help='runs the installation script before running the rest of the commands')
+parser.add_argument('--install', choices=['clinet', 'server', 'all'], default='all', help='Allows you to only install the server or client software')
 parser.add_argument('--test', nargs='+', help='names of tests to run')
 parser.add_argument('--exclude', nargs='+', help='names of tests to exclude')
 parser.add_argument('--type', choices=['all', 'json', 'db', 'query', 'fortune', 'update'], default='all', help='which type of test to run')

+ 23 - 0
web-simple/README.md

@@ -0,0 +1,23 @@
+# Setup
+
+* Perl 5.10+
+* MySQL 5.5
+* Wrk 2.0
+
+# Requirements
+
+* Web::Simple
+* DBD::pg
+* Starman (if using Starman as web server)
+* Plack (for plackup)
+* nginx (if you want to front Dancer with nginx, nginx.conf provided)
+
+# Deployment
+
+Something along the lines of
+
+    plackup -E production -s Starman --workers=8 -l /tmp/frameworks-benchmark.sock -a ./app.pl
+
+if you want to front it with nginx, otherwise
+
+    plackup -E production -s Starman --port=8080 --workers=8 -a ./app.pl

+ 0 - 0
web-simple/__init__.py


+ 32 - 0
web-simple/app.pl

@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+use Web::Simple;
+use JSON::XS;
+use DBI;
+
+my $dsn = "dbi:mysql:database=hello_world;host=localhost";
+my $dbh = DBI->connect( $dsn, 'benchmarkdbuser', 'benchmarkdbpass', { RaiseError => 1 });
+my $sth = $dbh->prepare('SELECT * FROM World where id = ?');
+
+sub dispatch_request {
+ sub (/json) {
+    [ 200, [ 'Content-type' => 'application/json', ],
+      [ encode_json({ message => 'Hello, World!' }) ] ];
+  },
+  sub (/db + ?queries~) {
+    my ($self, $queries) = @_;
+    $queries ||= 1;
+    my $rand;
+    my @response;
+    for ( 1 .. $queries ) {
+        my $id = int(rand 10000) + 1;
+        $sth->execute($id);
+        $sth->bind_col(2, \$rand);
+        if ( my @row = $sth->fetch ) {
+          push @response, { id => $id, randomNumber => $rand };
+        }
+    }
+    [ 200, [ 'Content-type' => 'application/json', ], [ encode_json(\@response)] ];
+  }
+}
+
+__PACKAGE__->run_if_script;

+ 18 - 0
web-simple/benchmark_config

@@ -0,0 +1,18 @@
+{
+  "framework": "web-simple",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "port": 8080,
+      "sort":106 
+    },
+    "raw": {
+      "setup_file": "setup",
+      "db_url": "/db",
+      "query_url": "/db?queries=",
+      "port": 8080,
+      "sort": 106
+    }
+  }]
+}

+ 3 - 0
web-simple/conf/config.pl

@@ -0,0 +1,3 @@
+{
+    modules => ['JSON::XS']
+}

+ 37 - 0
web-simple/nginx.conf

@@ -0,0 +1,37 @@
+user USR;
+
+worker_processes 2;
+
+events {
+  worker_connections  1024;
+}
+
+http {
+  output_buffers   1 32k;
+  postpone_output  1460;
+
+  sendfile         on;
+  tcp_nopush       on;
+
+  tcp_nodelay      on;
+
+  upstream backendurl {
+    server unix:/home/ubuntu/FrameworkBenchmarks/web-simple/frameworks-benchmark.sock;
+  }
+
+  server {
+    listen 8080;
+    server_name localhost;
+
+    location / {
+      try_files $uri @proxy;
+      access_log off;
+      expires max;
+    }
+
+    location @proxy {
+      proxy_set_header Host $http_host;
+      proxy_pass http://backendurl;
+    }
+  }
+}

+ 32 - 0
web-simple/setup.py

@@ -0,0 +1,32 @@
+import subprocess
+import sys
+import setup_util
+from os.path import expanduser
+import os
+import getpass
+
+home = expanduser("~")
+
+def start(args):
+  setup_util.replace_text("web-simple/app.pl", "localhost", ""+ args.database_host +"")
+  setup_util.replace_text("web-simple/nginx.conf", "USR", getpass.getuser())
+  setup_util.replace_text("web-simple/nginx.conf", "server unix:.*\/FrameworkBenchmarks", "server unix:" + home + "/FrameworkBenchmarks")
+
+  try:
+    subprocess.Popen("plackup -E production -s Starman --workers=" + str(args.max_threads) + " -l " + home + "/FrameworkBenchmarks/web-simple/frameworks-benchmark.sock -a ./app.pl", shell=True, cwd="web-simple")
+    subprocess.check_call("sudo /usr/local/nginx/sbin/nginx -c " + home + "/FrameworkBenchmarks/web-simple/nginx.conf", shell=True)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop():
+  try:
+    subprocess.call("sudo /usr/local/nginx/sbin/nginx -s stop", shell=True)
+    p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+    out, err = p.communicate()
+    for line in out.splitlines():
+      if 'starman' in line:
+        pid = int(line.split(None, 2)[1])
+        os.kill(pid, 9)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 15 - 15
webgo/src/hello/hello.go

@@ -1,28 +1,28 @@
 package main
 
 import (
-    "github.com/hoisie/web";
-    "encoding/json";
-    "runtime";
-    "os";
-    "log";
+	"encoding/json"
+	"github.com/hoisie/web"
+	"log"
+	"os"
+	"runtime"
 )
 
 type MessageStruct struct {
-    Message string
+	Message string
 }
 
 func hello(val string) string {
-  m := MessageStruct{"Hello, world"}
-  j, _ := json.Marshal(m)
-  return string(j)
+	m := MessageStruct{"Hello, world"}
+	j, _ := json.Marshal(m)
+	return string(j)
 }
 
 func main() {
-    f, _ := os.Create("server.log")
-    logger := log.New(f, "", log.Ldate|log.Ltime)
-    runtime.GOMAXPROCS(runtime.NumCPU())
-    web.Get("/(.*)", hello)
-    web.SetLogger(logger)
-    web.Run("0.0.0.0:8080")
+	f, _ := os.Create("server.log")
+	logger := log.New(f, "", log.Ldate|log.Ltime)
+	runtime.GOMAXPROCS(runtime.NumCPU())
+	web.Get("/(.*)", hello)
+	web.SetLogger(logger)
+	web.Run("0.0.0.0:8080")
 }