Browse Source

Merge pull request #1418 from ebramanti-techempower/master

New Framework: go-mongodb
Brittany Mazza 10 years ago
parent
commit
88845a960e

+ 2 - 0
.travis.yml

@@ -44,6 +44,8 @@ env:
     - "TESTDIR=Go/falcore"
     - "TESTDIR=Go/gin"
     - "TESTDIR=Go/go"
+    - "TESTDIR=Go/go-mongodb"
+    - "TESTDIR=Go/gorail"
     - "TESTDIR=Go/revel"
     - "TESTDIR=Go/revel-jet"
     - "TESTDIR=Go/revel-qbs"

+ 3 - 0
frameworks/Go/go-mongodb/README.md

@@ -0,0 +1,3 @@
+# Go MongoDB Benchmarking Test
+
+This is the Go portion of a [benchmarking test suite](../), which uses MongoDB as its database.

+ 28 - 0
frameworks/Go/go-mongodb/benchmark_config.json

@@ -0,0 +1,28 @@
+{
+  "framework": "go-mongodb",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MongoDB",
+      "framework": "go",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "go-mongodb",
+      "notes": "mongodb implementation for go net/http",
+      "versus": ""
+    }
+  }]
+}

+ 3 - 0
frameworks/Go/go-mongodb/install.sh

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

+ 2 - 0
frameworks/Go/go-mongodb/setup.bat

@@ -0,0 +1,2 @@
+set GOPATH=C:\FrameworkBenchmarks\go
+go run src\hello\hello.go

+ 12 - 0
frameworks/Go/go-mongodb/setup.sh

@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# Set the root of our go installation
+export GOROOT=${IROOT}/go
+export GOPATH=${TROOT}
+
+# Where to find the go executable
+export PATH="$GOROOT/bin:$PATH"
+
+go get ./...
+
+go run src/hello/hello.go &

+ 6 - 0
frameworks/Go/go-mongodb/source_code

@@ -0,0 +1,6 @@
+./go/src/
+./go/src/hello
+./go/src/hello/hello.go
+./go/templates/
+./go/templates/fortune.html
+./go/templates/layout.html

+ 205 - 0
frameworks/Go/go-mongodb/src/hello/hello.go

@@ -0,0 +1,205 @@
+package main
+
+import (
+	"encoding/json"
+	"gopkg.in/mgo.v2"
+	"gopkg.in/mgo.v2/bson"
+	"html/template"
+	"log"
+	"math/rand"
+	"net/http"
+	"runtime"
+	"sort"
+	"strconv"
+)
+
+const (
+	connectionString = "localhost"
+	helloWorldString = "Hello, world!"
+	worldRowCount    = 10000
+)
+
+var (
+	tmpl = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
+
+	database *mgo.Database
+	fortunes *mgo.Collection
+	worlds   *mgo.Collection
+)
+
+type Message struct {
+	Message string `json:"message"`
+}
+
+type World struct {
+	Id           uint16 `bson:"id" json:"id"`
+	RandomNumber uint16 `bson:"randomNumber" json:"randomNumber"`
+}
+
+type Fortune struct {
+	Id      uint16 `bson:"id" json:"id"`
+	Message string `bson:"message" json:"message"`
+}
+
+type Fortunes []Fortune
+
+func (s Fortunes) Len() int {
+	return len(s)
+}
+
+func (s Fortunes) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+type ByMessage struct{ Fortunes }
+
+func (s ByMessage) Less(i, j int) bool {
+	return s.Fortunes[i].Message < s.Fortunes[j].Message
+}
+
+func main() {
+	runtime.GOMAXPROCS(runtime.NumCPU())
+	if session, err := mgo.Dial(connectionString); err != nil {
+		log.Fatalf("Error opening database: %v", err)
+	} else {
+		defer session.Close()
+		session.SetPoolLimit(5)
+		database = session.DB("hello_world")
+		worlds = database.C("world")
+		fortunes = database.C("fortune")
+		http.HandleFunc("/json", jsonHandler)
+		http.HandleFunc("/db", dbHandler)
+		http.HandleFunc("/fortune", fortuneHandler)
+		http.HandleFunc("/queries", queriesHandler)
+		http.HandleFunc("/update", updateHandler)
+		http.HandleFunc("/plaintext", plaintextHandler)
+		http.ListenAndServe(":8080", nil)
+	}
+}
+
+// Helper for random numbers
+func getRandomNumber() uint16 {
+	return uint16(rand.Intn(worldRowCount) + 1)
+}
+
+// Test 1: JSON serialization
+func jsonHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Server", "go-mongodb")
+	json.NewEncoder(w).Encode(&Message{helloWorldString})
+}
+
+func dbHandler(w http.ResponseWriter, r *http.Request) {
+	var world World
+	query := bson.M{"id": getRandomNumber()}
+	if worlds != nil {
+		if err := worlds.Find(query).One(&world); err != nil {
+			log.Fatalf("Error finding world with id: %s", err.Error())
+			return
+		} else {
+			w.Header().Set("Content-Type", "application/json")
+			w.Header().Set("Server", "go-mongodb")
+			json.NewEncoder(w).Encode(&world)
+			return
+		}
+	} else {
+		log.Fatal("Collection not initialized properly")
+	}
+}
+
+func queriesHandler(w http.ResponseWriter, r *http.Request) {
+	n := 1
+	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
+		n, _ = strconv.Atoi(nStr)
+	}
+
+	if n > 500 {
+		n = 500
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Server", "go-mongodb")
+	encoder := json.NewEncoder(w)
+
+	if n <= 1 {
+		result := make([]World, 1)
+		query := bson.M{"id": getRandomNumber()}
+		if err := worlds.Find(query).One(&result[0]); err != nil {
+			log.Fatalf("Error finding world with id: %s", err.Error())
+			return
+		}
+		encoder.Encode(&result)
+	} else {
+		result := make([]World, n)
+		for i := 0; i < n; i++ {
+			query := bson.M{"id": getRandomNumber()}
+			if err := worlds.Find(query).One(&result[i]); err != nil {
+				log.Fatalf("Error finding world with id: %s", err.Error())
+				return
+			}
+		}
+		encoder.Encode(&result)
+	}
+}
+
+func fortuneHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/html")
+	w.Header().Set("Server", "go-mongodb")
+	f := make(Fortunes, 16)
+	if err := fortunes.Find(nil).All(&f); err == nil {
+		f = append(f, Fortune{
+			Message: "Additional fortune added at request time.",
+		})
+		sort.Sort(ByMessage{f})
+		if err := tmpl.Execute(w, f); err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+		}
+	}
+
+}
+
+func updateHandler(w http.ResponseWriter, r *http.Request) {
+	n := 1
+	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
+		n, _ = strconv.Atoi(nStr)
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Server", "go-mongodb")
+	encoder := json.NewEncoder(w)
+
+	if n <= 1 {
+		result := make([]World, 1)
+		colQuery := bson.M{"id": getRandomNumber()}
+		update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
+		if err := worlds.Update(colQuery, update); err != nil {
+			log.Fatalf("Error updating world with id: %s", err.Error())
+		} else {
+			result[0].Id = colQuery["id"].(uint16)
+			result[0].RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
+		}
+		encoder.Encode(&result)
+	} else {
+		if n > 500 {
+			n = 500
+		}
+		result := make([]World, n)
+		for i := 0; i < n; i++ {
+			colQuery := bson.M{"id": getRandomNumber()}
+			update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
+			if err := worlds.Update(colQuery, update); err != nil {
+				log.Fatalf("Error updating world with id: %s", err.Error())
+			} else {
+				result[i].Id = colQuery["id"].(uint16)
+				result[i].RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
+			}
+		}
+		encoder.Encode(&result)
+	}
+}
+
+func plaintextHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain")
+	w.Header().Set("Server", "go-mongodb")
+	w.Write([]byte(helloWorldString))
+}

+ 14 - 0
frameworks/Go/go-mongodb/templates/fortune.html

@@ -0,0 +1,14 @@
+{{define "content"}}
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+{{range .}}
+<tr>
+<td>{{.Id}}</td>
+<td>{{.Message}}</td>
+</tr>
+{{end}}
+</table>
+{{end}}

+ 9 - 0
frameworks/Go/go-mongodb/templates/layout.html

@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+{{template "content" .}}
+</body>
+</html>

+ 1 - 0
toolset/setup/linux/prerequisites.sh

@@ -42,6 +42,7 @@ sudo apt-get -qqy install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options:
   libjemalloc-dev libluajit-5.1-dev `# Needed by lwan at least` \
   libhiredis-dev                    `# Redis client - Needed by ngx_mruby at least` \
   cloc dstat                        `# Collect resource usage statistics` \
+  libsasl2-dev                      `# Needed by mgo for go-mongodb test` \
   llvm-dev                          `# Required for correct Ruby installation` \
   libboost-dev                      `# Silicon relies on boost::lexical_cast.`