Build Tiny Load Tool Using Go and Concurrency Model

Build Tiny Load Tool Using Go and 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 period of 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 seem like it's  parallel but underneath cpu serving all the process in sequence for very short span of time(e.g. nanoseconds). you can check this digram to understand this:

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()
 }

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

 provides methods as : , and .  identify how many goroutines need to be waited. When a goroutine exits, it must call . The goroutine blocks on , Once the becomes, the will return, and 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 signals that this goroutine is done.

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

Let's build one simple load 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 almost everything is really simple and same as above.

Run this code as : go run main.go -rps 10 -req "http://google.com" -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.

To view or add a comment, sign in

More articles by Sunil Kapil

  • Validate Rest API Using Json Schema

    It's a common understanding that when we build any API, we expect a specific data format to be pass to API method and…

  • Thinking Serverless with Python!

    Since, some time I have been using serverless and found that it's really awesome technology and give lot of freedom and…

  • Build Test Framework for WPF Apps

    Recently I build a test framework for WPF apps on windows. When I started the project, I wanted to use open source…

    1 Comment
  • How I Launch Golang Web App Using Docker

    I have recently build and launch one monitoring web app in my current company. which to monitor our internal test and…

    1 Comment
  • Chrome in Docker

    I have been playing with docker since some time and trying to setup different environment with it. Recently I have…

Others also viewed

Explore content categories