Skip to content

Instantly share code, notes, and snippets.

@hackintoshrao
Last active February 24, 2017 02:47
Show Gist options
  • Select an option

  • Save hackintoshrao/c13bda4a3093b850b72cfba00f665f96 to your computer and use it in GitHub Desktop.

Select an option

Save hackintoshrao/c13bda4a3093b850b72cfba00f665f96 to your computer and use it in GitHub Desktop.
Server with leaky endpoint and instrumentation for getting the number of go routines in the system.
package main
import (
"fmt"
"log"
"net/http"
"runtime"
"strconv"
)
// get the count of number of go routines in the system.
func countGoRoutines() int {
return runtime.NumGoroutine()
}
func getGoroutinesCountHandler(w http.ResponseWriter, r *http.Request) {
// Get the count of number of go routines running.
count := countGoRoutines()
w.Write([]byte(strconv.Itoa(count)))
}
// function to add an array of numbers.
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
// writes the sum to the go routines.
c <- sum // send sum to c
}
// HTTP handler for /sum
func sumConcurrent(w http.ResponseWriter, r *http.Request) {
s := []int{7, 2, 8, -9, 4, 0}
c1 := make(chan int)
c2 := make(chan int)
// spin up a goroutine.
go sum(s[:len(s)/2], c1)
// spin up a goroutine.
go sum(s[len(s)/2:], c2)
// not reading from c2.
// go routine writing to c2 will be blocked.
// Since we are not reading from c2,
// the goroutine attempting to write to c2
// will be blocked forever resulting in leak.
x := <-c1
// write the response.
fmt.Fprintf(w, strconv.Itoa(x))
}
func main() {
// get the sum of numbers.
http.HandleFunc("/sum", sumConcurrent)
// get the count of number of go routines in the system.
http.HandleFunc("/_count", getGoroutinesCountHandler)
err := http.ListenAndServe(":8001", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
package main
import (
"io/ioutil"
"log"
"net/http"
"strconv"
"sync"
)
const (
leakyServer = "http://localhost:8001"
)
// get the count of the number of go routines in the server.
func getRoutineCount() (int, error) {
body, err := getReq("/_count")
if err != nil {
return -1, err
}
count, err := strconv.Atoi(string(body))
if err != nil {
return -1, err
}
return count, nil
}
// Send get request and return the repsonse body.
func getReq(endPoint string) ([]byte, error) {
response, err := http.Get(leakyServer + endPoint)
if err != nil {
return []byte{}, err
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
return []byte{}, err
}
return body, nil
}
func main() {
// get the number of go routines in the leaky server.
count, err := getRoutineCount()
if err != nil {
log.Fatal(err)
}
log.Printf("\n %d Go routines before the load test in the system.", count)
var wg sync.WaitGroup
// send 50 concurrent request to the leaky endpoint.
for i := 0; i < 50; i++ {
wg.Add(1)
go func() {
defer wg.Done()
_, err = getReq("/sum")
if err != nil {
log.Fatal(err)
}
}()
}
wg.Wait()
// get the cout of number of goroutines in the system after the load test.
count, err = getRoutineCount()
if err != nil {
log.Fatal(err)
}
log.Printf("\n %d Go routines after the load test in the system.", count)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment