Router implementation considerations

If you perform a search for Go Frameworks, you will come across a variety of different solutions, all with slightly different routing implementations. Luckily, based on https://github.com/julienschmidt/go-http-routing-benchmark, we have a mechanism by which we can pit all of these routers against each other to see which performs the best and which performs the worst under certain situations. Using these benchmarks when I was initially investigating router capabilities, the benchmarks provided gave some excellent insight into the efficiencies of the various routers from 2015:

BenchmarkAce_GithubAll 93675 ns/op 167 allocs/op
BenchmarkBear_GithubAll 264194 ns/op 943 allocs/op
BenchmarkBeego_GithubAll 1109160 ns/op 2092 allocs/op
BenchmarkBone_GithubAll 2063973 ns/op 8119 allocs/op
BenchmarkDenco_GithubAll 83114 ns/op 167 allocs/op
BenchmarkEcho_GithubAll 38662 ns/op 0 allocs/op
BenchmarkGin_GithubAll 43467 ns/op 0 allocs/op
BenchmarkGocraftWeb_GithubAll 386829 ns/op 1889 allocs/op
BenchmarkGoji_GithubAll 561131 ns/op 334 allocs/op
BenchmarkGoJsonRest_GithubAll 490789 ns/op 2940 allocs/op
BenchmarkGoRestful_GithubAll 15569513 ns/op 7725 allocs/op
BenchmarkGorillaMux_GithubAll 7431130 ns/op 1791 allocs/op
BenchmarkHttpRouter_GithubAll 51192 ns/op 167 allocs/op
BenchmarkHttpTreeMux_GithubAll 138164 ns/op 334 allocs/op
BenchmarkKocha_GithubAll 139625 ns/op 843 allocs/op
BenchmarkMacaron_GithubAll 709932 ns/op 2315 allocs/op
BenchmarkMartini_GithubAll 10261331 ns/op 2686 allocs/op
BenchmarkPat_GithubAll 3989686 ns/op 32222 allocs/op
BenchmarkPossum_GithubAll 259165 ns/op 812 allocs/op
BenchmarkR2router_GithubAll 240345 ns/op 1182 allocs/op
BenchmarkRevel_GithubAll 1203336 ns/op 5918 allocs/op
BenchmarkRivet_GithubAll 247213 ns/op 1079 allocs/op
BenchmarkTango_GithubAll 379960 ns/op 2470 allocs/op
BenchmarkTigerTonic_GithubAll 931401 ns/op 6052 allocs/op
BenchmarkTraffic_GithubAll 7292170 ns/op 22390 allocs/op
BenchmarkVulcan_GithubAll 271682 ns/op 609 allocs/op
BenchmarkZeus_GithubAll 748827 ns/op 2648 allocs/op

It is pretty clear that in my initial testing of the various web application frameworks, the Gin and Echo frameworks were the best performers with large API definitions. Echo was able to resolve a route within its router implementation within 38,662 nanoseconds on average, which is incredibly fast. Moreover, Echo is able to offer a zero allocations per call abstraction. In order to achieve zero allocations per call, Echo reuses context in a context pool. We will discuss that in Chapter 4, Utilizing the Request Context and Data Bindings.

Interestingly, one of the most popular routers is the Gorilla Mux router from the Gorilla web toolkit, which is a collection of independent tools which can be used to create web applications. Gorilla Mux, as seen in the preceding code, performs fairly poorly compared to some of the other high-performance routers, taking an average of 7,431,130 nanoseconds to resolve a route, which is 175 times slower than Echo's router implementation for the full GitHub API. This slowness has everything to do with the implementation of the router. Gorilla Mux uses a regular expression-based routing engine, much like the Django web framework in Python. For every request that comes in, Gorilla Mux will iterate over all of the regular expressions it holds for routes, and check to see if the request matches.

Though seven milliseconds does not seem like much to be worried about from a speed perspective, you have to realize that this is seven milliseconds of computation per request. If you have many requests, you will waste more and more time just trying to isolate which handler to run for the request. Since routing is performed on every single request, we need to keep an eye on performance.

You should always use the best tool for the job when writing a web application, and there are many times when a Radix Tree does not make sense for API endpoint routing. Since a search from a Tree takes O(k), where k is the length of the string being searched within the tree, exceedingly long endpoint paths might have negative performance issues compared to a Hash Map data structure, which is built into the standard library.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.136.226