Build Tiny Load Tool In Go Using Concurrency Model

One of the best thing in go is concurrency and channels and it’s really useful while building the tools or application which need high concurrency. I have recently build the load application tool using golang which need to make multiple requests to server for certain time.

What is concurrency:

Ability to run multiple tasks concurrently or simultaneously.

May be above statement vague for some of the people but consider this scenario:

There are 10 process which need to write in a file simultaneously and system has one CPU. Now cpu can only serve one process at one time. So at one time there could be only one process which would be writing in file and other process will wait but wait would be very short(e.g. nanoseconds) and cpu will serve other process very quickly which would seem like it’s parallel but actually cpu serving all the process for very short span of time(e.g. nanoseconds) sequentially. you can check this digram to understand this:

serving_requests

 

How Concurrency work on Golang:

You just say : go foo() =>  which called goroutine

Which basically call method and create goroutine. goroutine is light weight thread, which take very less stack memory(2k) and cpu and destroy automatically as soon as they done.

Here is sample example to build goroutines:

package main

import (
  "fmt"
  "runtime"
  "sync"
  )

func main() {
                     runtime.GOMAXPROCS(1)
                     fmt.Println("Starting it => ")
                     var swg sync.WaitGroup
                     swg.Add(1)
                    go func() {
                                defer swg.Done()
                                for count := 0; count < 1; count++ {
                                                    for char := 'a'; char < 'a'+26; char++ {
                                                    fmt.Printf("%c", char)
                                                  }
                                }
                    }()

                 fmt.Println("\nWaiting to finish")
                  swg.Wait()
                  fmt.Println("\nTerminating Programe")
  }

Let me explain, what’s happening here:

runtime.GoMAXPROCS(1) : This is golang official site say about runtime:

The GOMAXPROCS variable limits the number of operating system 
threads that can execute user-level Go code simultaneously. 
There is no limit to the number of threads that can be blocked 
in system calls on behalf of Go code; those do not count against 
the GOMAXPROCS limit. This package's GOMAXPROCS function queries 
and changes the limit.

go func() { }() : This is go anonymous function but here it’s serving as goroutine. When controller come to this point it generate goroutine(which is basically a method) to do the job.

sync.WaitGroup : it waits for goroutine to complete

sync.WaitGroup provides methods as : Add, Done and Wait. Add identify how many goroutines need to be waited. When a goroutine exits, it must call Done. The main goroutine blocks on Wait, Once the counter becomes0, the Wait will return, and main goroutine can continue to run.

swg.Add(1) : you are adding one goroutine in the group and telling main function to wait for this goroutine to complete.

defer swg.Done() : defer is golang keyword. it allow the statement to be executed at the end of method and Done(method) which signal that this goroutine done.

swg.Wait() : Wait in main function until swg.Done hasn’t been called.

Let’s build one simple load test tool using goroutine:

Let’s modify our above code and build a load testing tool which will make the requests to server continuously. It doesn’t need much change, we just need to include some of the new libs like flag(for command line options) and log(for logging). Other than that everything is really simple.

Run this code as : go run main.go -rps 10 -req “http://google.com&#8221; -req_type GET

package main

import (
             "flag"
             "log"
            "sync"
            "time"
 )

var wg sync.WaitGroup

func main() {
                    rps := flag.Int("rps", 10, "request per second 
                                       or throughput")
                    req := flag.String("req", "http://google.com", 
                                         "server need to hit")
                    reqType := flag.String("req_type", "GET", 
                                          "Request type to make")

flag.Parse()
  log.Printf("Throughput => %d\n", *rps)
  log.Printf("Requests => %s\n", *req)
  log.Printf("Type of Request => %s\n", *reqType)

wg.Add(*rps)                       //dynamically adding goroutine
  var i = 0
  for i < *rps {                   // Loop to generate goroutines
                go func() {
                               for {
                                         time.Sleep(time.Second)
                                         log.Printf("RPS : %d\n", *rps)
                               }
                 }()
                 i++
  }
  wg.Wait()

}

   I guess, most of the things would be clear as everything is same as our first example. 

Hope this will give some light to understand goroutine  in golang. Please provide your comments and feedback below.

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: