Name: go-http-routing-benchmark
Owner: Gin-Gonic
Description: Go HTTP request router and web framework benchmark
Created: 2015-05-23 14:52:07.0
Updated: 2018-04-27 08:55:17.0
Pushed: 2015-05-23 15:59:17.0
Size: 351
Language: Go
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
This benchmark suite aims to compare the performance of HTTP request routers for Go by implementing the routing structure of some real world APIs. Some of the APIs are slightly adapted, since they can not be implemented 1:1 in some of the routers.
Of course the tested routers can be used for any kind of HTTP request ? handler function routing, not only (REST) APIs.
Go is a great language for web applications. Since the default request multiplexer of Go's net/http package is very simple and limited, an accordingly high number of HTTP request routers exist.
Unfortunately, most of the (early) routers use pretty bad routing algorithms. Moreover, many of them are very wasteful with memory allocations, which can become a problem in a language with Garbage Collection like Go, since every (heap) allocation results in more work for the Garbage Collector.
Lately more and more bloated frameworks pop up, outdoing one another in the number of features. This benchmark tries to measure their overhead.
Beware that we are comparing apples to oranges here, we compare feature-rich frameworks to packages with simple routing functionality only. But since we are only interested in decent request routing, I think this is not entirely unfair. The frameworks are configured to do as little additional work as possible.
If you care about performance, this benchmark can maybe help you find the right router, which scales with your application.
Personally, I prefer slim and optimized software, which is why I implemented HttpRouter, which is also tested here. In fact, this benchmark suite started as part of the packages tests, but was then extended to a generic benchmark suite. So keep in mind, that I am not completely unbiased :relieved:
Benchmark System:
Besides the micro-benchmarks, there are 3 sets of benchmarks where we play around with clones of some real-world APIs, and one benchmark with static routes only, to allow a comparison with http.ServeMux. The following table shows the memory required only for loading the routing structure for the respective API. The best 3 values for each test are bold. I'm pretty sure you can detect a pattern :wink:
| Router | Static | GitHub | Google+ | Parse | |:————-|———-:|———–:|———-:|———-:| | HttpServeMux |18064 B| - | - | - | | Beego | 79472 B | 497248 B | 26480 B | 38768 B | | Denco | 44752 B | 107632 B | 54896 B | 36368 B | | Gocraft Web | 57976 B | 95736 B | 8024 B | 13120 B | | Goji | 32400 B | 58424 B| 3392 B| 6704 B| | Go-Json-Rest | 152608 B | 148352 B | 11696 B | 13712 B | | Gorilla Mux | 685152 B | 1557216 B | 80240 B | 125480 B | | HttpRouter |26232 B| 44344 B| 3144 B| 5792 B| | HttpTreeMux | 75624 B | 81408 B | 7712 B | 7616 B | | Kocha | 130336 B | 811744 B | 139968 B | 191632 B | | Martini | 312592 B | 579472 B | 27520 B | 50608 B | | Pat |21272 B| 18968 B| 1448 B| 2360 B| | TigerTonic | 85264 B | 99392 B | 10576 B | 11008 B | | Traffic | 649568 B | 1124704 B | 57984 B | 98168 B |
The first place goes to Pat, followed by HttpRouter and Goji. Now, before everyone starts reading the documentation of Pat, [SPOILER]
this low memory consumption comes at the price of relatively bad routing performance. The routing structure of Pat is simple - probably too simple. [/SPOILER]
.
Moreover main memory is cheap and usually not a scarce resource. As long as the router doesn't require Megabytes of memory, it should be no deal breaker. But it gives us a first hint how efficient or wasteful a router works.
The Static
benchmark is not really a clone of a real-world API. It is just a collection of random static paths inspired by the structure of the Go directory. It might not be a realistic URL-structure.
The only intention of this benchmark is to allow a comparison with the default router of Go's net/http package, http.ServeMux, which is limited to static routes and does not support parameters in the route pattern.
In the StaticAll
benchmark each of 157 URLs is called once per repetition (op, operation). If you are unfamiliar with the go test -bench
tool, the first number is the number of repetitions the go test
tool made, to get a test running long enough for measurements. The second column shows the time in nanoseconds that a single repetition takes. The third number is the amount of heap memory allocated in bytes, the last one the average number of allocations made per repetition.
The logs below show, that http.ServeMux has only medium performance, compared to more feature-rich routers. The fastest router only needs 1.8% of the time http.ServeMux needs.
HttpRouter was the first router (I know of) that managed to serve all the static URLs without a single heap allocation. Since the first run of this benchmark more routers followed this trend and were optimized in the same way.
hmarkHttpServeMux_StaticAll 5000 706222 ns/op 96 B/op 6 allocs/op
hmarkBeego_StaticAll 2000 1408954 ns/op 482433 B/op 14088 allocs/op
hmarkDenco_StaticAll 200000 12679 ns/op 0 B/op 0 allocs/op
hmarkGocraftWeb_StaticAll 10000 154142 ns/op 51468 B/op 947 allocs/op
hmarkGoji_StaticAll 20000 80518 ns/op 0 B/op 0 allocs/op
hmarkGoJsonRest_StaticAll 2000 978164 ns/op 180973 B/op 3945 allocs/op
hmarkGorillaMux_StaticAll 1000 1763690 ns/op 71804 B/op 956 allocs/op
hmarkHttpRouter_StaticAll 100000 15010 ns/op 0 B/op 0 allocs/op
hmarkHttpTreeMux_StaticAll 100000 15123 ns/op 0 B/op 0 allocs/op
hmarkKocha_StaticAll 100000 23093 ns/op 0 B/op 0 allocs/op
hmarkMartini_StaticAll 500 3444278 ns/op 156015 B/op 2351 allocs/op
hmarkPat_StaticAll 1000 1640745 ns/op 549187 B/op 11186 allocs/op
hmarkTigerTonic_StaticAll 50000 58264 ns/op 7714 B/op 157 allocs/op
hmarkTraffic_StaticAll 500 7230129 ns/op 3763731 B/op 27453 allocs/op
The following benchmarks measure the cost of some very basic operations.
In the first benchmark, only a single route, containing a parameter, is loaded into the routers. Then a request for a URL matching this pattern is made and the router has to call the respective registered handler function. End.
hmarkBeego_Param 500000 5495 ns/op 1165 B/op 14 allocs/op
hmarkDenco_Param 5000000 312 ns/op 50 B/op 2 allocs/op
hmarkGocraftWeb_Param 1000000 1440 ns/op 684 B/op 9 allocs/op
hmarkGoji_Param 5000000 748 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_Param 500000 6980 ns/op 1787 B/op 29 allocs/op
hmarkGorillaMux_Param 1000000 2665 ns/op 780 B/op 7 allocs/op
hmarkHttpRouter_Param 20000000 139 ns/op 33 B/op 1 allocs/op
hmarkHttpTreeMux_Param 5000000 558 ns/op 340 B/op 2 allocs/op
hmarkKocha_Param 5000000 377 ns/op 58 B/op 2 allocs/op
hmarkMartini_Param 500000 6265 ns/op 1251 B/op 12 allocs/op
hmarkPat_Param 1000000 1620 ns/op 670 B/op 11 allocs/op
hmarkTigerTonic_Param 1000000 2766 ns/op 1015 B/op 18 allocs/op
hmarkTraffic_Param 500000 4440 ns/op 2013 B/op 22 allocs/op
Same as before, but now with multiple parameters, all in the same single route. The intention is to see how the routers scale with the number of parameters. The values of the parameters must be passed to the handler function somehow, which requires allocations. Let's see how clever the routers solve this task with a route containing 5 and 20 parameters:
hmarkBeego_Param5 100000 18473 ns/op 1291 B/op 14 allocs/op
hmarkDenco_Param5 2000000 982 ns/op 405 B/op 5 allocs/op
hmarkGocraftWeb_Param5 1000000 2218 ns/op 957 B/op 12 allocs/op
hmarkGoji_Param5 1000000 1093 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_Param5 200000 10462 ns/op 3264 B/op 40 allocs/op
hmarkGorillaMux_Param5 500000 4680 ns/op 906 B/op 7 allocs/op
hmarkHttpRouter_Param5 5000000 319 ns/op 162 B/op 1 allocs/op
hmarkHttpTreeMux_Param5 2000000 898 ns/op 340 B/op 2 allocs/op
hmarkKocha_Param5 1000000 1326 ns/op 448 B/op 7 allocs/op
hmarkMartini_Param5 200000 13027 ns/op 1376 B/op 12 allocs/op
hmarkPat_Param5 500000 3416 ns/op 1435 B/op 18 allocs/op
hmarkTigerTonic_Param5 200000 9247 ns/op 2568 B/op 41 allocs/op
hmarkTraffic_Param5 500000 7206 ns/op 2312 B/op 26 allocs/op
hmarkBeego_Param20 10000 106746 ns/op 3681 B/op 17 allocs/op
hmarkDenco_Param20 1000000 2882 ns/op 1666 B/op 7 allocs/op
hmarkGocraftWeb_Param20 500000 7156 ns/op 3857 B/op 16 allocs/op
hmarkGoji_Param20 1000000 3197 ns/op 1260 B/op 2 allocs/op
hmarkGoJsonRest_Param20 100000 25809 ns/op 10605 B/op 75 allocs/op
hmarkGorillaMux_Param20 200000 9885 ns/op 3295 B/op 9 allocs/op
hmarkHttpRouter_Param20 2000000 954 ns/op 646 B/op 1 allocs/op
hmarkHttpTreeMux_Param20 500000 5016 ns/op 2216 B/op 4 allocs/op
hmarkKocha_Param20 500000 4268 ns/op 1836 B/op 17 allocs/op
hmarkMartini_Param20 50000 55039 ns/op 3765 B/op 14 allocs/op
hmarkPat_Param20 500000 3412 ns/op 1435 B/op 18 allocs/op
hmarkTigerTonic_Param20 50000 36825 ns/op 10710 B/op 131 allocs/op
hmarkTraffic_Param20 100000 22605 ns/op 8077 B/op 49 allocs/op
Now let's see how expensive it is to access a parameter. The handler function reads the value (by the name of the parameter, e.g. with a map lookup; depends on the router) and writes it to our web scale storage (/dev/null
).
hmarkBeego_ParamWrite 500000 6604 ns/op 1602 B/op 18 allocs/op
hmarkDenco_ParamWrite 5000000 377 ns/op 50 B/op 2 allocs/op
hmarkGocraftWeb_ParamWrite 1000000 1590 ns/op 693 B/op 9 allocs/op
hmarkGoji_ParamWrite 2000000 818 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_ParamWrite 200000 8388 ns/op 2265 B/op 33 allocs/op
hmarkGorillaMux_ParamWrite 1000000 2913 ns/op 780 B/op 7 allocs/op
hmarkHttpRouter_ParamWrite 10000000 193 ns/op 33 B/op 1 allocs/op
hmarkHttpTreeMux_ParamWrite 5000000 649 ns/op 340 B/op 2 allocs/op
hmarkKocha_ParamWrite 5000000 435 ns/op 58 B/op 2 allocs/op
hmarkMartini_ParamWrite 500000 7538 ns/op 1359 B/op 15 allocs/op
hmarkPat_ParamWrite 1000000 2940 ns/op 1109 B/op 15 allocs/op
hmarkTigerTonic_ParamWrite 500000 4639 ns/op 1471 B/op 23 allocs/op
hmarkTraffic_ParamWrite 500000 5855 ns/op 2435 B/op 25 allocs/op
Enough of the micro benchmark stuff. Let's play a bit with real APIs. In the first set of benchmarks, we use a clone of the structure of Parse's decent medium-sized REST API, consisting of 26 routes.
The tasks are 1.) routing a static URL (no parameters), 2.) routing a URL containing 1 parameter, 3.) same with 2 parameters, 4.) route all of the routes once (like the StaticAll benchmark, but the routes now contain parameters).
Worth noting is, that the requested route might be a good case for some routing algorithms, while it is a bad case for another algorithm. The values might vary slightly depending on the selected route.
hmarkBeego_ParseStatic 500000 3461 ns/op 1247 B/op 15 allocs/op
hmarkDenco_ParseStatic 50000000 42.6 ns/op 0 B/op 0 allocs/op
hmarkGocraftWeb_ParseStatic 2000000 889 ns/op 328 B/op 6 allocs/op
hmarkGoji_ParseStatic 5000000 341 ns/op 0 B/op 0 allocs/op
hmarkGoJsonRest_ParseStatic 500000 5860 ns/op 1136 B/op 25 allocs/op
hmarkGorillaMux_ParseStatic 1000000 2760 ns/op 456 B/op 6 allocs/op
hmarkHttpRouter_ParseStatic 50000000 36.7 ns/op 0 B/op 0 allocs/op
hmarkHttpTreeMux_ParseStatic 50000000 62.6 ns/op 0 B/op 0 allocs/op
hmarkKocha_ParseStatic 50000000 72.2 ns/op 0 B/op 0 allocs/op
hmarkMartini_ParseStatic 500000 5528 ns/op 927 B/op 11 allocs/op
hmarkPat_ParseStatic 2000000 809 ns/op 246 B/op 5 allocs/op
hmarkTigerTonic_ParseStatic 10000000 264 ns/op 49 B/op 1 allocs/op
hmarkTraffic_ParseStatic 500000 5008 ns/op 2377 B/op 24 allocs/op
hmarkBeego_ParseParam 500000 7983 ns/op 1775 B/op 28 allocs/op
hmarkDenco_ParseParam 5000000 347 ns/op 50 B/op 2 allocs/op
hmarkGocraftWeb_ParseParam 1000000 1535 ns/op 700 B/op 9 allocs/op
hmarkGoji_ParseParam 2000000 983 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_ParseParam 500000 7208 ns/op 1789 B/op 29 allocs/op
hmarkGorillaMux_ParseParam 1000000 3186 ns/op 780 B/op 7 allocs/op
hmarkHttpRouter_ParseParam 10000000 178 ns/op 65 B/op 1 allocs/op
hmarkHttpTreeMux_ParseParam 5000000 617 ns/op 340 B/op 2 allocs/op
hmarkKocha_ParseParam 5000000 413 ns/op 58 B/op 2 allocs/op
hmarkMartini_ParseParam 500000 7524 ns/op 1251 B/op 12 allocs/op
hmarkPat_ParseParam 1000000 2707 ns/op 1160 B/op 18 allocs/op
hmarkTigerTonic_ParseParam 1000000 3010 ns/op 1048 B/op 19 allocs/op
hmarkTraffic_ParseParam 500000 5228 ns/op 2314 B/op 24 allocs/op
hmarkBeego_Parse2Params 200000 9217 ns/op 1935 B/op 28 allocs/op
hmarkDenco_Parse2Params 5000000 542 ns/op 115 B/op 3 allocs/op
hmarkGocraftWeb_Parse2Params 1000000 1756 ns/op 750 B/op 10 allocs/op
hmarkGoji_Parse2Params 2000000 954 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_Parse2Params 500000 8131 ns/op 2145 B/op 32 allocs/op
hmarkGorillaMux_Parse2Params 500000 3623 ns/op 812 B/op 7 allocs/op
hmarkHttpRouter_Parse2Params 10000000 202 ns/op 65 B/op 1 allocs/op
hmarkHttpTreeMux_Parse2Params 5000000 708 ns/op 340 B/op 2 allocs/op
hmarkKocha_Parse2Params 5000000 666 ns/op 132 B/op 4 allocs/op
hmarkMartini_Parse2Params 200000 7723 ns/op 1283 B/op 12 allocs/op
hmarkPat_Parse2Params 1000000 2687 ns/op 887 B/op 19 allocs/op
hmarkTigerTonic_Parse2Params 500000 4720 ns/op 1473 B/op 28 allocs/op
hmarkTraffic_Parse2Params 500000 5467 ns/op 2120 B/op 24 allocs/op
hmarkBeego_ParseAll 10000 197920 ns/op 38877 B/op 616 allocs/op
hmarkDenco_ParseAll 500000 7692 ns/op 1000 B/op 35 allocs/op
hmarkGocraftWeb_ParseAll 50000 36226 ns/op 14639 B/op 208 allocs/op
hmarkGoji_ParseAll 100000 19721 ns/op 5448 B/op 32 allocs/op
hmarkGoJsonRest_ParseAll 10000 180128 ns/op 41202 B/op 727 allocs/op
hmarkGorillaMux_ParseAll 10000 120929 ns/op 17138 B/op 173 allocs/op
hmarkHttpRouter_ParseAll 500000 3592 ns/op 660 B/op 16 allocs/op
hmarkHttpTreeMux_ParseAll 200000 11650 ns/op 5452 B/op 32 allocs/op
hmarkKocha_ParseAll 200000 9371 ns/op 1163 B/op 44 allocs/op
hmarkMartini_ParseAll 10000 200307 ns/op 29375 B/op 305 allocs/op
hmarkPat_ParseAll 50000 53113 ns/op 18017 B/op 363 allocs/op
hmarkTigerTonic_ParseAll 50000 67208 ns/op 20547 B/op 419 allocs/op
hmarkTraffic_ParseAll 10000 164938 ns/op 70161 B/op 743 allocs/op
The GitHub API is rather large, consisting of 203 routes. The tasks are basically the same as in the benchmarks before.
hmarkBeego_GithubStatic 500000 3880 ns/op 1148 B/op 31 allocs/op
hmarkDenco_GithubStatic 50000000 60.5 ns/op 0 B/op 0 allocs/op
hmarkGocraftWeb_GithubStatic 2000000 933 ns/op 328 B/op 6 allocs/op
hmarkGoji_GithubStatic 5000000 401 ns/op 0 B/op 0 allocs/op
hmarkGoJsonRest_GithubStatic 500000 6006 ns/op 1150 B/op 25 allocs/op
hmarkGorillaMux_GithubStatic 100000 18227 ns/op 456 B/op 6 allocs/op
hmarkHttpRouter_GithubStatic 50000000 63.2 ns/op 0 B/op 0 allocs/op
hmarkHttpTreeMux_GithubStatic 50000000 65.1 ns/op 0 B/op 0 allocs/op
hmarkKocha_GithubStatic 20000000 99.5 ns/op 0 B/op 0 allocs/op
hmarkMartini_GithubStatic 100000 18546 ns/op 927 B/op 11 allocs/op
hmarkPat_GithubStatic 200000 11503 ns/op 3754 B/op 76 allocs/op
hmarkTigerTonic_GithubStatic 5000000 308 ns/op 49 B/op 1 allocs/op
hmarkTraffic_GithubStatic 50000 44923 ns/op 23105 B/op 168 allocs/op
hmarkBeego_GithubParam 50000 44645 ns/op 2973 B/op 50 allocs/op
hmarkDenco_GithubParam 5000000 643 ns/op 115 B/op 3 allocs/op
hmarkGocraftWeb_GithubParam 1000000 1855 ns/op 750 B/op 10 allocs/op
hmarkGoji_GithubParam 1000000 1314 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_GithubParam 200000 8427 ns/op 2159 B/op 32 allocs/op
hmarkGorillaMux_GithubParam 200000 11485 ns/op 813 B/op 7 allocs/op
hmarkHttpRouter_GithubParam 5000000 304 ns/op 97 B/op 1 allocs/op
hmarkHttpTreeMux_GithubParam 2000000 770 ns/op 340 B/op 2 allocs/op
hmarkKocha_GithubParam 5000000 754 ns/op 132 B/op 4 allocs/op
hmarkMartini_GithubParam 100000 22637 ns/op 1284 B/op 12 allocs/op
hmarkPat_GithubParam 500000 7319 ns/op 2538 B/op 44 allocs/op
hmarkTigerTonic_GithubParam 500000 4722 ns/op 1467 B/op 26 allocs/op
hmarkTraffic_GithubParam 100000 18700 ns/op 7076 B/op 58 allocs/op
hmarkBeego_GithubAll 100 23430165 ns/op 502614 B/op 9871 allocs/op
hmarkDenco_GithubAll 10000 120365 ns/op 21219 B/op 506 allocs/op
hmarkGocraftWeb_GithubAll 5000 358982 ns/op 139091 B/op 1903 allocs/op
hmarkGoji_GithubAll 5000 604522 ns/op 56896 B/op 340 allocs/op
hmarkGoJsonRest_GithubAll 1000 1645794 ns/op 404222 B/op 6303 allocs/op
hmarkGorillaMux_GithubAll 500 6634737 ns/op 152277 B/op 1402 allocs/op
hmarkHttpRouter_GithubAll 50000 51138 ns/op 14039 B/op 168 allocs/op
hmarkHttpTreeMux_GithubAll 10000 132507 ns/op 56907 B/op 340 allocs/op
hmarkKocha_GithubAll 10000 143398 ns/op 24117 B/op 676 allocs/op
hmarkMartini_GithubAll 200 9802351 ns/op 258349 B/op 2713 allocs/op
hmarkPat_GithubAll 500 4154815 ns/op 1539081 B/op 24970 allocs/op
hmarkTigerTonic_GithubAll 2000 920839 ns/op 247085 B/op 5171 allocs/op
hmarkTraffic_GithubAll 200 8087393 ns/op 3143039 B/op 23958 allocs/op
Last but not least the Google+ API, consisting of 13 routes. In reality this is just a subset of a much larger API.
hmarkBeego_GPlusStatic 1000000 2321 ns/op 808 B/op 11 allocs/op
hmarkDenco_GPlusStatic 50000000 37.2 ns/op 0 B/op 0 allocs/op
hmarkGocraftWeb_GPlusStatic 2000000 862 ns/op 312 B/op 6 allocs/op
hmarkGoji_GPlusStatic 10000000 270 ns/op 0 B/op 0 allocs/op
hmarkGoJsonRest_GPlusStatic 500000 5827 ns/op 1136 B/op 25 allocs/op
hmarkGorillaMux_GPlusStatic 1000000 1793 ns/op 456 B/op 6 allocs/op
hmarkHttpRouter_GPlusStatic 50000000 34.6 ns/op 0 B/op 0 allocs/op
hmarkHttpTreeMux_GPlusStatic 50000000 35.4 ns/op 0 B/op 0 allocs/op
hmarkKocha_GPlusStatic 50000000 63.8 ns/op 0 B/op 0 allocs/op
hmarkMartini_GPlusStatic 500000 4887 ns/op 927 B/op 11 allocs/op
hmarkPat_GPlusStatic 5000000 336 ns/op 98 B/op 2 allocs/op
hmarkTigerTonic_GPlusStatic 10000000 186 ns/op 33 B/op 1 allocs/op
hmarkTraffic_GPlusStatic 500000 3350 ns/op 1503 B/op 18 allocs/op
hmarkBeego_GPlusParam 200000 7657 ns/op 1231 B/op 16 allocs/op
hmarkDenco_GPlusParam 5000000 365 ns/op 50 B/op 2 allocs/op
hmarkGocraftWeb_GPlusParam 1000000 1519 ns/op 684 B/op 9 allocs/op
hmarkGoji_GPlusParam 2000000 889 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_GPlusParam 500000 7388 ns/op 1806 B/op 29 allocs/op
hmarkGorillaMux_GPlusParam 500000 4040 ns/op 780 B/op 7 allocs/op
hmarkHttpRouter_GPlusParam 10000000 203 ns/op 65 B/op 1 allocs/op
hmarkHttpTreeMux_GPlusParam 5000000 638 ns/op 340 B/op 2 allocs/op
hmarkKocha_GPlusParam 5000000 444 ns/op 58 B/op 2 allocs/op
hmarkMartini_GPlusParam 200000 8672 ns/op 1251 B/op 12 allocs/op
hmarkPat_GPlusParam 1000000 1895 ns/op 719 B/op 12 allocs/op
hmarkTigerTonic_GPlusParam 1000000 3166 ns/op 1085 B/op 18 allocs/op
hmarkTraffic_GPlusParam 500000 5369 ns/op 2030 B/op 22 allocs/op
hmarkBeego_GPlus2Params 200000 9999 ns/op 1293 B/op 16 allocs/op
hmarkDenco_GPlus2Params 5000000 618 ns/op 115 B/op 3 allocs/op
hmarkGocraftWeb_GPlus2Params 1000000 1860 ns/op 750 B/op 10 allocs/op
hmarkGoji_GPlus2Params 1000000 1296 ns/op 340 B/op 2 allocs/op
hmarkGoJsonRest_GPlus2Params 200000 8516 ns/op 2178 B/op 32 allocs/op
hmarkGorillaMux_GPlus2Params 200000 9007 ns/op 812 B/op 7 allocs/op
hmarkHttpRouter_GPlus2Params 10000000 246 ns/op 65 B/op 1 allocs/op
hmarkHttpTreeMux_GPlus2Params 2000000 751 ns/op 340 B/op 2 allocs/op
hmarkKocha_GPlus2Params 5000000 744 ns/op 132 B/op 4 allocs/op
hmarkMartini_GPlus2Params 100000 27700 ns/op 1382 B/op 16 allocs/op
hmarkPat_GPlus2Params 500000 5981 ns/op 2347 B/op 34 allocs/op
hmarkTigerTonic_GPlus2Params 500000 5076 ns/op 1561 B/op 27 allocs/op
hmarkTraffic_GPlus2Params 200000 12711 ns/op 3599 B/op 34 allocs/op
hmarkBeego_GPlusAll 10000 113601 ns/op 15897 B/op 217 allocs/op
hmarkDenco_GPlusAll 500000 5761 ns/op 880 B/op 27 allocs/op
hmarkGocraftWeb_GPlusAll 100000 20527 ns/op 8513 B/op 116 allocs/op
hmarkGoji_GPlusAll 200000 12312 ns/op 3746 B/op 22 allocs/op
hmarkGoJsonRest_GPlusAll 20000 99250 ns/op 23871 B/op 386 allocs/op
hmarkGorillaMux_GPlusAll 50000 63046 ns/op 9655 B/op 90 allocs/op
hmarkHttpRouter_GPlusAll 1000000 2513 ns/op 655 B/op 11 allocs/op
hmarkHttpTreeMux_GPlusAll 500000 7706 ns/op 3748 B/op 22 allocs/op
hmarkKocha_GPlusAll 500000 6858 ns/op 1017 B/op 35 allocs/op
hmarkMartini_GPlusAll 10000 155402 ns/op 16368 B/op 179 allocs/op
hmarkPat_GPlusAll 50000 47397 ns/op 17270 B/op 302 allocs/op
hmarkTigerTonic_GPlusAll 50000 49864 ns/op 15160 B/op 311 allocs/op
hmarkTraffic_GPlusAll 10000 108007 ns/op 41779 B/op 430 allocs/op
First of all, there is no reason to use net/http's default ServeMux, which is very limited and does not have especially good performance. There are enough alternatives coming in every flavor, choose the one you like best.
Secondly, the broad range of functions of some of the frameworks comes at a high price in terms of performance. For example Martini has great flexibility, but very bad performance. Martini has the worst performance of all tested routers in a lot of the benchmarks. Beego seems to have some scalability problems and easily defeats Martini with even worse performance, when the number of parameters or routes is high. I really hope, that the routing of these packages can be optimized. I think the Go-ecosystem needs great feature-rich frameworks like these.
Last but not least, we have to determine the performance champion.
Denco and its predecessor Kocha-urlrouter seem to have great performance, but are not convenient to use as a router for the net/http package. A lot of extra work is necessary to use it as a http.Handler. The README of Denco claims, that the package is not intended as a replacement for http.ServeMux.
Goji looks very decent. It has great performance while also having a great range of features, more than any other router / framework in the top group.
Currently no router can beat the performance of the HttpRouter package, which currently dominates nearly all benchmarks.
In the end, performance can not be the (only) criterion for choosing a router. Play around a bit with some of the routers, and choose the one you like best.