Browse Source

go: optimize tests

Julien Schmidt 12 years ago
parent
commit
0b321fcfda
2 changed files with 73 additions and 47 deletions
  1. 72 46
      go/src/hello/hello.go
  2. 1 1
      go/templates/fortune.html

+ 72 - 46
go/src/hello/hello.go

@@ -15,7 +15,7 @@ import (
 )
 
 type Message struct {
-	Message string
+	Message string `json:"message"`
 }
 
 type World struct {
@@ -28,13 +28,15 @@ type Fortune struct {
 	Message string `json:"message"`
 }
 
+// TODO: remove ?charset=utf8 drom DSN after the next Go-MySQL-Driver release
+// https://github.com/go-sql-driver/mysql#unicode-support
 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 = ?"
-	FortuneSelect      = "SELECT id, message FROM Fortune;"
-	WorldRowCount      = 10000
-	MaxConnectionCount = 256
+	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 = ?"
+	fortuneSelect      = "SELECT id, message FROM Fortune;"
+	worldRowCount      = 10000
+	maxConnectionCount = 256
 )
 
 var (
@@ -48,25 +50,26 @@ var (
 func main() {
 	runtime.GOMAXPROCS(runtime.NumCPU())
 
-	db, err := sql.Open("mysql", ConnectionString)
+	db, err := sql.Open("mysql", connectionString)
 	if err != nil {
 		log.Fatalf("Error opening database: %v", err)
 	}
-	db.SetMaxIdleConns(MaxConnectionCount)
-	worldStatement, err = db.Prepare(WorldSelect)
+	db.SetMaxIdleConns(maxConnectionCount)
+	worldStatement, err = db.Prepare(worldSelect)
 	if err != nil {
 		log.Fatal(err)
 	}
-	fortuneStatement, err = db.Prepare(FortuneSelect)
+	fortuneStatement, err = db.Prepare(fortuneSelect)
 	if err != nil {
 		log.Fatal(err)
 	}
-	updateStatement, err = db.Prepare(WorldUpdate)
+	updateStatement, err = db.Prepare(worldUpdate)
 	if err != nil {
 		log.Fatal(err)
 	}
 
-	http.HandleFunc("/db", worldHandler)
+	http.HandleFunc("/db", dbHandler)
+	http.HandleFunc("/queries", queriesHandler)
 	http.HandleFunc("/json", jsonHandler)
 	http.HandleFunc("/fortune", fortuneHandler)
 	http.HandleFunc("/update", updateHandler)
@@ -74,6 +77,7 @@ func main() {
 	http.ListenAndServe(":8080", nil)
 }
 
+// Test 1: JSON serialization
 func jsonHandler(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "application/javascript")
 	json.NewEncoder(w).Encode(&Message{"Hello, world"})
@@ -86,76 +90,98 @@ func plaintextHandler(w http.ResponseWriter, r *http.Request) {
 	w.Write(HelloWorld)
 }
 
-func worldHandler(w http.ResponseWriter, r *http.Request) {
+// Test 2: Single database query
+func dbHandler(w http.ResponseWriter, r *http.Request) {
+	var world World
+	err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber)
+	if err != nil {
+		log.Fatalf("Error scanning world row: %s", err.Error())
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(&world)
+}
+
+// Test 3: Multiple database queries
+func queriesHandler(w http.ResponseWriter, r *http.Request) {
 	n := 1
-	if nStr := r.URL.Query().Get("queries"); len(nStr) != 0 {
+	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
 		n, _ = strconv.Atoi(nStr)
 	}
-	ww := make([]World, n)
-	if n == 1 {
-		err := worldStatement.QueryRow(rand.Intn(WorldRowCount)+1).Scan(&ww[0].Id, &ww[0].RandomNumber)
+
+	if n <= 1 {
+		dbHandler(w, r)
+		return
+	}
+
+	world := make([]World, n)
+	for i := 0; i < n; i++ {
+		err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world[i].Id, &world[i].RandomNumber)
 		if err != nil {
-			log.Fatalf("Error scanning world row: %v", err)
-		}
-	} else {
-		for i := 0; i < n; i++ {
-			err := worldStatement.QueryRow(rand.Intn(WorldRowCount)+1).Scan(&ww[i].Id, &ww[i].RandomNumber)
-			if err != nil {
-				log.Fatalf("Error scanning world row: %v", err)
-			}
+			log.Fatalf("Error scanning world row: %s", err.Error())
 		}
 	}
+
 	w.Header().Set("Content-Type", "application/json")
-	json.NewEncoder(w).Encode(ww)
+	json.NewEncoder(w).Encode(world)
 }
 
+// Test 4: Fortunes
 func fortuneHandler(w http.ResponseWriter, r *http.Request) {
 	rows, err := fortuneStatement.Query()
 	if err != nil {
 		log.Fatalf("Error preparing statement: %v", err)
 	}
 
-	fortunes := make([]*Fortune, 0, 16)
+	fortunes := make(Fortunes, 0, 16)
 	for rows.Next() { //Fetch rows
-		fortune := new(Fortune)
+		fortune := Fortune{}
 		if err := rows.Scan(&fortune.Id, &fortune.Message); err != nil {
-			log.Fatalf("Error scanning fortune row: %v", err)
+			log.Fatalf("Error scanning fortune row: %s", err.Error())
 		}
-		fortunes = append(fortunes, fortune)
+		fortunes = append(fortunes, &fortune)
 	}
 	fortunes = append(fortunes, &Fortune{Message: "Additional fortune added at request time."})
 
 	sort.Sort(ByMessage{fortunes})
 	w.Header().Set("Content-Type", "text/html")
-	if err := tmpl.Execute(w, map[string]interface{}{"fortunes": fortunes}); err != nil {
+	if err := tmpl.Execute(w, fortunes); err != nil {
 		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
 }
 
+// Test 5: Database updates
 func updateHandler(w http.ResponseWriter, r *http.Request) {
 	n := 1
-	if nStr := r.URL.Query().Get("queries"); len(nStr) != 0 {
+	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
 		n, _ = strconv.Atoi(nStr)
 	}
-	ww := make([]World, n)
-	if n == 1 {
-		worldStatement.QueryRow(rand.Intn(WorldRowCount)+1).Scan(&ww[0].Id, &ww[0].RandomNumber)
-		ww[0].RandomNumber = uint16(rand.Intn(WorldRowCount) + 1)
-		updateStatement.Exec(ww[0].RandomNumber, ww[0].Id)
+
+	var jsonData []byte
+
+	if n <= 1 {
+		var world World
+		worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber)
+		world.RandomNumber = uint16(rand.Intn(worldRowCount) + 1)
+		updateStatement.Exec(world.RandomNumber, world.Id)
+		jsonData, _ = json.Marshal(world)
 	} else {
+		world := make([]World, n)
 		for i := 0; i < n; i++ {
-			err := worldStatement.QueryRow(rand.Intn(WorldRowCount)+1).Scan(&ww[i].Id, &ww[i].RandomNumber)
-			ww[i].RandomNumber = uint16(rand.Intn(WorldRowCount) + 1)
-			updateStatement.Exec(ww[i].RandomNumber, ww[i].Id)
-			if err != nil {
-				log.Fatalf("Error scanning world row: %v", err)
+			if err := worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world[i].Id, &world[i].RandomNumber); err != nil {
+				log.Fatalf("Error scanning world row: %s", err.Error())
+			}
+			world[i].RandomNumber = uint16(rand.Intn(worldRowCount) + 1)
+			if _, err := updateStatement.Exec(world[i].RandomNumber, world[i].Id); err != nil {
+				log.Fatalf("Error updating world row: %s", err.Error())
 			}
 		}
+		jsonData, _ = json.Marshal(world)
 	}
-	j, _ := json.Marshal(ww)
+
 	w.Header().Set("Content-Type", "application/json")
-	w.Header().Set("Content-Length", strconv.Itoa(len(j)))
-	w.Write(j)
+	w.Header().Set("Content-Length", strconv.Itoa(len(jsonData)))
+	w.Write(jsonData)
 }
 
 type Fortunes []*Fortune

+ 1 - 1
go/templates/fortune.html

@@ -4,7 +4,7 @@
 <th>id</th>
 <th>message</th>
 </tr>
-{{range .fortunes}}
+{{range .}}
 <tr>
 <td>{{.Id}}</td>
 <td>{{.Message}}</td>