Kaynağa Gözat

Adds Martini framework to project (#4126)

Julian Coleman 6 yıl önce
ebeveyn
işleme
2e727e1fba

+ 0 - 0
frameworks/Go/martini/README.md


+ 29 - 0
frameworks/Go/martini/benchmark_config.json

@@ -0,0 +1,29 @@
+{
+  "framework": "martini",
+  "tests": [
+    {
+      "default": {
+        "json_url": "/bench/json",
+        "db_url": "/bench/single",
+        "query_url": "/bench/multiple?queries=",
+        "update_url": "/bench/update?queries=",
+        "plaintext_url": "/bench/plaintext",
+        "port": 8080,
+        "approach": "Realistic",
+        "classification": "Micro",
+        "database": "Postgres",
+        "framework": "martini",
+        "language": "Go",
+        "flavor": "None",
+        "orm": "Raw",
+        "platform": "None",
+        "webserver": "None",
+        "os": "Linux",
+        "database_os": "Linux",
+        "display_name": "martini",
+        "notes": "",
+        "versus": "go"
+      }
+    }
+  ]
+}

+ 148 - 0
frameworks/Go/martini/main.go

@@ -0,0 +1,148 @@
+package main
+
+import (
+  "database/sql"
+  "encoding/json"
+  "log"
+  "net/http"
+  "time"
+
+  "github.com/go-martini/martini"
+  _ "github.com/lib/pq"
+)
+
+var (
+	db                    *sql.DB
+	worldSelectPrepared   *sql.Stmt
+	worldUpdatePrepared   *sql.Stmt
+	fortuneSelectPrepared *sql.Stmt
+)
+
+type World struct {
+  Id           uint16 `json:"id"`
+  RandomNumber uint16 `json:"randomNumber"`
+}
+
+
+func main() {
+  initDB()
+
+  m := martini.Classic()
+
+  m.Use(setRequiredHeaders)
+
+  m.Group("/bench", func (r martini.Router) {
+    r.Get("/plaintext", plaintextHandler)
+    r.Get("/json"     , jsonHandler)
+    r.Get("/single"   , singleQueryHandler)
+    r.Get("/multiple" , multipleQueriesHandler)
+    r.Get("/update"   , updatesHandler)
+  })
+
+  m.RunOnAddr(":8080")
+}
+
+// Initialize the connection to the database
+func initDB() {
+  driverName := "postgres"
+  connectionString := "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world?sslmode=disable"
+  worldSelect := "SELECT id, randomNumber FROM World WHERE id = $1"
+	worldUpdate := "UPDATE World SET randomNumber = $1 WHERE id = $2"
+	fortuneSelect := "SELECT id, message FROM Fortune"
+	// worldRowCount := 10000
+	maxConnections := 256
+
+  db, err := sql.Open(driverName, connectionString)
+
+  if err != nil {
+    log.Fatalf("Error opening database: %v", err)
+  }
+
+  db.SetMaxIdleConns(maxConnections)
+  db.SetMaxOpenConns(maxConnections)
+
+  worldSelectPrepared, err = db.Prepare(worldSelect)
+	if err != nil {
+		log.Fatal(err)
+	}
+	worldUpdatePrepared, err = db.Prepare(worldUpdate)
+	if err != nil {
+		log.Fatal(err)
+	}
+	fortuneSelectPrepared, err = db.Prepare(fortuneSelect)
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+// Create middleware to add Server and Date headers to all
+// routes.
+func setRequiredHeaders(w http.ResponseWriter, r *http.Request) {
+  t := time.Now();
+
+  w.Header().Set("Server", "Martini")
+  w.Header().Set("Date", t.Format(time.RFC1123))
+}
+
+// Route handlers
+func plaintextHandler() string {
+  return "Hello, World!"
+}
+
+func jsonHandler(w http.ResponseWriter) []byte {
+  message := map[string]interface{}{"message": "Hello, World!"}
+  w.Header().Set("Content-Type", "application/json")
+
+  res, _ := json.Marshal(message);
+  return res
+}
+
+func singleQueryHandler(w http.ResponseWriter) {
+  var world World
+
+  w.Header().Set("Content-Type", "application/json")
+
+  err := worldSelectPrepared.QueryRow(RandomNumber()).Scan(&world.Id, &world.RandomNumber)
+  if err != nil {
+    log.Fatalf("Error scanning world row: %s", err.Error())
+  }
+
+  // No need to return anything as we are writing straight
+  // to the response itself
+  json.NewEncoder(w).Encode(&world)
+}
+
+func multipleQueriesHandler(w http.ResponseWriter, r *http.Request) {
+  queries := SanitizeQueries(r)
+  worlds := make([]World, queries)
+
+  w.Header().Set("Content-Type", "application/json")
+
+  for i := 0; i < queries; i += 1 {
+    err := worldSelectPrepared.QueryRow(RandomNumber()).Scan(&worlds[i].Id, &worlds[i].RandomNumber)
+
+    if err != nil {
+      log.Fatalf("Error scanning world row: %v", err)
+    }
+  }
+
+  json.NewEncoder(w).Encode(worlds)
+}
+
+func updatesHandler(w http.ResponseWriter, r *http.Request) {
+	queries := SanitizeQueries(r)
+
+	worlds := make([]World, queries)
+	for i := 0; i < queries; i++ {
+		if err := worldSelectPrepared.QueryRow(RandomNumber()).Scan(&worlds[i].Id, &worlds[i].RandomNumber); err != nil {
+			log.Fatalf("Error scanning world row: %v", err)
+		}
+		worlds[i].RandomNumber = uint16(RandomNumber())
+		if _, err := worldUpdatePrepared.Exec(worlds[i].RandomNumber, worlds[i].Id); err != nil {
+			log.Fatalf("Error updating world row: %v", err)
+		}
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(worlds)
+}

+ 13 - 0
frameworks/Go/martini/martini.dockerfile

@@ -0,0 +1,13 @@
+FROM golang:1.11.1
+
+WORKDIR /home
+COPY . .
+
+RUN mkdir -p bin
+ENV GOPATH /home
+ENV path ${GOPATH}/bin:${PATH}
+
+RUN go get github.com/go-martini/martini
+RUN go get github.com/lib/pq
+
+CMD go run randomNumber.go sanitizeQueries.go main.go

+ 9 - 0
frameworks/Go/martini/randomNumber.go

@@ -0,0 +1,9 @@
+package main
+
+import "math/rand"
+
+func RandomNumber() uint16 {
+  max := 10000
+
+  return uint16(rand.Intn(max) + 1)
+}

+ 25 - 0
frameworks/Go/martini/sanitizeQueries.go

@@ -0,0 +1,25 @@
+package main
+
+import (
+  "net/http"
+  "strconv"
+)
+
+func SanitizeQueries(r *http.Request) int {
+  n := 1
+  max := 500
+  min := 1
+
+  if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
+		n, _ = strconv.Atoi(nStr)
+  }
+
+
+  if n < min {
+		return min
+	} else if n > max {
+		return max
+  }
+
+	return n
+}