Loading...

Follow All things Tech | Golang on Feedspot

Continue with Google
Continue with Facebook
or

Valid
All things Tech | Golang by Maria Desouza - 4M ago

An empty struct in Go has no data elements.

type S struct{}

The most important property of the empty struct is that the width is zero. This allows to create a slice or channel of thousands of empty structs with a tiny memory footprint.

Here is a size comparison of the empty struct vs empty interface vs bool:

package main 
import (
"fmt"
"unsafe"
)

func main() {
var s struct{}
var i interface{}
var b bool
fmt.Println(unsafe.Sizeof(s), unsafe.Sizeof(i), unsafe.Sizeof(b))
}

On a 32 bit system: 0 8 1

On a 64-bit system:0 16 1null

Uses of empty struct As a method receiver 

An empty struct{} can be used as a method receiver in cases when you don’t need data on a struct just methods with predefined input and output. E.g. You may want have a mock for testing interfaces.

An empty struct channel

An empty struct is very useful in channels when you have to notify that some event occurred but you don’t need to pass any information about it. Using a channel of  empty structure will only increment a counter in the channel but not assign memory, copy elements and so on. Using boolean values for this purpose has a memory footprint that can be avoided using the empty struct.

As a Set data type

Go has no Set data type. This can be easily emulated by using map[keyType]struct{}. This way map keeps only keys and no values.

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

Golang’s net/http package can be used to build a web server in a minutes. It packs in a pretty wide use of Golang concepts like functions, interfaces and types to achieve this.

Here is a basic web server using Go:

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", handlerHelloWorld)
	http.ListenAndServe(":8082", nil)
}

func handlerHelloWorld(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello world")
}

If we run the above server we can make a GET request and the server will print “Hello World”.

What we need to understand that in the background the package runs a ServeMux to map the url to the handler.

What is ServeMux?

A ServeMux is a HTTP request multiplexer or router that  matches the incoming requests with a set of registered patterns and  calls  the associated handler for that pattern.

http.ListenAndServe has the following signature

func ListenAndServe(addr string, handler Handler) error

If we pass nil as the handler, the DefaultServeMux is used.

ServeMux struct contains the following four vital functions that are key to the working of the http package:

func (mux *ServeMux) Handle(pattern string, handler Handler)
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request))
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string)
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request)
What is a Handler?

Notice that ServeMux has a function named Handler that takes in a request param and returns a object of type Handler.   Made my head spin a bit when I first saw that.

http.Handler is an interface. Any object can be made a handler as long as it implements the ServeHTTP function with the following signature.

 ServeHTTP(ResponseWriter, *Request)

So essentially the default ServeMux is a Handler since it implements ServeHTTP.

HandleFunc and Handle

In our simple server code above, we did not define a Handler that implements ServeHTTP nor did we define a ServeMux. Instead we called HandleFunc and the function that would handle the response.

This is the source code for HandleFunc in the net/http package

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
   	DefaultServeMux.HandleFunc(pattern, handler)
  }  

Internally this calls the DefaultServerMux’s HandleFunc. If you take a look at ServeMuxes HandleFunc implementation here is what you’ll find:

func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
 	if handler == nil {
 		panic("http: nil handler")
 	}
  	mux.Handle(pattern, HandlerFunc(handler))
  }

From the net/http source, we find that HandlerFunc type is an adapter to allows the use of an ordinary functions as HTTP handlers.

type HandlerFunc func(ResponseWriter, *Request)
  
   // ServeHTTP calls f(w, r).
  func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
  	f(w, r)
  }

The HandlerFunc makes it possible for us to pass in any function to make it a Handler. So in our simple server example above, we could change the HandleFunc call to a call to the Handle function.

http.Handle("/", http.HandlerFunc(indexHandlerHelloWorld))

The Handle function is used when we want to use a custom Handler in our code.

Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

The goal of API Performance Tests are to conduct  load tests that will run broadly across all endpoints of an API to understand the distribution of throughput in requests per second – average, peak, etc.

It is important to record response times and resource utilization at average and peak loads. This will allow us to determine system response times, network latency, etc. We should also be able to determine how the concurrency and processing overhead of the API. We should measure performance when concurrent instances are instantiated with instructions to run load testing scripts.

Tooling Vegeta

Vegeta is an easy to use command line tool for API load testing.

https://github.com/tsenart/vegeta

Testing can be done in 3 simple steps:

  • Install
$ brew update && brew install vegeta
  • Run a list of APIs can be listed in a file called targets.txt
vegeta -cpus 4 attack -targets targets.txt -rate 50 -duration 30s | tee results.bin | vegeta report
  • Plot
cat results.bin | vegeta plot > plot.html

One limitation of vegeta is that cookie session are not supported which shouldn’t be an issue if we follow the JWT stateless model that is scalable and avoid sessions.

K6

k6 is another modern load testing tool that allows us to easily create load test scenarios based on virtual users and simulated traffic configurations

https://docs.k6.io/docs

  • Install
$brew tap loadimpact/k6 && brew install k6
  • Run a es6 Javascript that defines which endpoints to test and what  custom metrics and thresholds need to be gathered.
k6 run --vus 100 --duration 5m --out json=outputs/result.json  k6/script.js
vus  are used to define the number of concurrent users that allow to send API requests in parallel.
  • Plot
We can output to an influxDB instance and plot this using a UI tool like Grafana
Types of Performance Test
  • Stress test: Determine what is the maximum number of concurrent users that the system supports with an acceptable user experience.
  • Soak test: Used to find problems that arise when a system is under pressure for extended periods of time. Test is run for longer duration and is used to find long term problems such as memory leaks, resource leaks or corruption and degradation that occurs over time
  • Spike test:  Spike tests are vital to testing how well your API can perform at peak times. This will ensure your API can handle the amount of users coming in a very short amount of time e.g. if you running a holiday ad campaign and you see a significant rise in traffic.
Read Full Article
  • Show original
  • .
  • Share
  • .
  • Favorite
  • .
  • Email
  • .
  • Add Tags 

Separate tags by commas
To access this feature, please upgrade your account.
Start your free month
Free Preview