Home

Awesome

Go HTTP Router Benchmark

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.

Tested routers & frameworks:

Motivation

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:

Results

Benchmark System:

Memory Consumption

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:

RouterStaticGitHubGoogle+Parse
HttpServeMux17728 B---
Ace37720 B60520 B4280 B7968 B
Beego103240 B165192 B11368 B21040 B
Bone30160 B44576 B3040 B5648 B
Denco9696 B36728 B3256 B4184 B
Gin41760 B66896 B4800 B8712 B
Gocraft Web51304 B88856 B6840 B11936 B
Goji27536 B47256 B3216 B5536 B
Go-Json-Rest130944 B128032 B11104 B13760 B
go-restful886200 B1369208 B89176 B142856 B
Gorilla Mux668512 B1493072 B71056 B122136 B
HttpRouter25064 B44184 B3144 B5792 B
HttpTreeMux73288 B74992 B7120 B7616 B
Kocha114960 B785264 B128880 B181712 B
Macaron51752 B103624 B8264 B13384 B
Martini309040 B476992 B23904 B45952 B
Pat15704 B15832 B1448 B1976 B
Revel93808 B141504 B10768 B15488 B
Rivet42872 B110080 B7896 B13496 B
TigerTonic80112 B96240 B9408 B9840 B
Traffic624416 B1053536 B49504 B93496 B
Vulcan624416 B425792 B25496 B44296 B
Zeus14560 B15840 B1456 B1984 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.

Static Routes

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.

BenchmarkHttpServeMux_StaticAll     2000           1083520 ns/op              96 B/op          8 allocs/op

BenchmarkAce_StaticAll             30000             41254 ns/op               0 B/op          0 allocs/op
BenchmarkBeego_StaticAll           10000            316800 ns/op           57744 B/op       1099 allocs/op
BenchmarkBone_StaticAll            20000             61164 ns/op            4736 B/op         48 allocs/op
BenchmarkDenco_StaticAll          100000             16256 ns/op               0 B/op          0 allocs/op
BenchmarkGin_StaticAll             30000             40553 ns/op               0 B/op          0 allocs/op
BenchmarkGocraftWeb_StaticAll      10000            216057 ns/op           47696 B/op        942 allocs/op
BenchmarkGoji_StaticAll            10000            107313 ns/op               0 B/op          0 allocs/op
BenchmarkGoJsonRest_StaticAll       1000           1357206 ns/op          169567 B/op       4553 allocs/op
BenchmarkGoRestful_StaticAll         200           6560934 ns/op          294346 B/op       5007 allocs/op
BenchmarkGorillaMux_StaticAll       1000           2341979 ns/op           72944 B/op       1264 allocs/op
BenchmarkHttpRouter_StaticAll      50000             25481 ns/op               0 B/op          0 allocs/op
BenchmarkHttpTreeMux_StaticAll     50000             25453 ns/op               0 B/op          0 allocs/op
BenchmarkKocha_StaticAll           50000             27373 ns/op               0 B/op          0 allocs/op
BenchmarkMacaron_StaticAll          5000            491792 ns/op          118032 B/op       1256 allocs/op
BenchmarkMartini_StaticAll           300           4421434 ns/op          140352 B/op       2335 allocs/op
BenchmarkPat_StaticAll              1000           2010572 ns/op          533904 B/op      11123 allocs/op
BenchmarkRevel_StaticAll            2000           1127954 ns/op          204528 B/op       3925 allocs/op
BenchmarkRivet_StaticAll           10000            100330 ns/op           17584 B/op        314 allocs/op
BenchmarkTigerTonic_StaticAll      20000             76555 ns/op            7504 B/op        157 allocs/op
BenchmarkTraffic_StaticAll           100          10982528 ns/op         3713994 B/op      27161 allocs/op
BenchmarkVulcan_StaticAll            100          11028290 ns/op         3713993 B/op      27161 allocs/op
BenchmarkZeus_StaticAll             3000            550942 ns/op            4736 B/op         48 allocs/op

Micro Benchmarks

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.

BenchmarkAce_Param               5000000               267 ns/op              32 B/op          1 allocs/op
BenchmarkBeego_Param             1000000              2856 ns/op             720 B/op         10 allocs/op
BenchmarkBone_Param              1000000              2231 ns/op             656 B/op         10 allocs/op
BenchmarkDenco_Param             5000000               251 ns/op              32 B/op          1 allocs/op
BenchmarkGin_Param               5000000               277 ns/op              32 B/op          1 allocs/op
BenchmarkGocraftWeb_Param        1000000              2266 ns/op             656 B/op          9 allocs/op
BenchmarkGoji_Param              1000000              1179 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_Param         200000              9802 ns/op            1712 B/op         33 allocs/op
BenchmarkGoRestful_Param          500000              3841 ns/op             568 B/op         16 allocs/op
BenchmarkGorillaMux_Param         500000              4043 ns/op             784 B/op          9 allocs/op
BenchmarkHttpRouter_Param       10000000               181 ns/op              32 B/op          1 allocs/op
BenchmarkHttpTreeMux_Param       2000000               878 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_Param             3000000               433 ns/op              56 B/op          3 allocs/op
BenchmarkMacaron_Param            500000              4479 ns/op            1144 B/op         13 allocs/op
BenchmarkMartini_Param            200000              8350 ns/op            1152 B/op         12 allocs/op
BenchmarkPat_Param               1000000              2416 ns/op             656 B/op         14 allocs/op
BenchmarkRevel_Param              200000              8216 ns/op            1672 B/op         28 allocs/op
BenchmarkRivet_Param             1000000              1377 ns/op             464 B/op          5 allocs/op
BenchmarkTigerTonic_Param         500000              4159 ns/op             992 B/op         19 allocs/op
BenchmarkTraffic_Param            300000              6792 ns/op            1984 B/op         23 allocs/op
BenchmarkVulcan_Param            1000000              1031 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_Param              1000000              2699 ns/op             696 B/op         13 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:

BenchmarkAce_Param5              2000000               635 ns/op             160 B/op          1 allocs/op
BenchmarkBeego_Param5             500000              4092 ns/op             992 B/op         13 allocs/op
BenchmarkBone_Param5             1000000              1672 ns/op             528 B/op          5 allocs/op
BenchmarkDenco_Param5            2000000               684 ns/op             160 B/op          1 allocs/op
BenchmarkGin_Param5              2000000               644 ns/op             160 B/op          1 allocs/op
BenchmarkGocraftWeb_Param5       1000000              3518 ns/op             928 B/op         12 allocs/op
BenchmarkGoji_Param5             1000000              1835 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_Param5        100000             16112 ns/op            3168 B/op         44 allocs/op
BenchmarkGoRestful_Param5         500000              4437 ns/op             568 B/op         16 allocs/op
BenchmarkGorillaMux_Param5        300000              6467 ns/op             912 B/op          9 allocs/op
BenchmarkHttpRouter_Param5       3000000               555 ns/op             160 B/op          1 allocs/op
BenchmarkHttpTreeMux_Param5      1000000              1327 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_Param5            1000000              1871 ns/op             440 B/op         10 allocs/op
BenchmarkMacaron_Param5           300000              5692 ns/op            1416 B/op         16 allocs/op
BenchmarkMartini_Param5           100000             18164 ns/op            1280 B/op         12 allocs/op
BenchmarkPat_Param5               300000              4787 ns/op            1408 B/op         25 allocs/op
BenchmarkRevel_Param5             200000              9986 ns/op            2024 B/op         35 allocs/op
BenchmarkRivet_Param5            1000000              2221 ns/op             528 B/op          9 allocs/op
BenchmarkTigerTonic_Param5        200000             13293 ns/op            2519 B/op         53 allocs/op
BenchmarkTraffic_Param5           200000             10399 ns/op            2280 B/op         31 allocs/op
BenchmarkVulcan_Param5           1000000              1387 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_Param5             1000000              1822 ns/op             544 B/op          6 allocs/op

BenchmarkAce_Param20             1000000              1876 ns/op             640 B/op          1 allocs/op
BenchmarkBeego_Param20            100000             12704 ns/op            3867 B/op         17 allocs/op
BenchmarkBone_Param20            1000000              2261 ns/op             784 B/op          5 allocs/op
BenchmarkDenco_Param20           1000000              2285 ns/op             640 B/op          1 allocs/op
BenchmarkGin_Param20             1000000              1888 ns/op             640 B/op          1 allocs/op
BenchmarkGocraftWeb_Param20       200000             11342 ns/op            3803 B/op         16 allocs/op
BenchmarkGoji_Param20             300000              5755 ns/op            1247 B/op          2 allocs/op
BenchmarkGoJsonRest_Param20        30000             40293 ns/op           10461 B/op         78 allocs/op
BenchmarkGoRestful_Param20        300000              5314 ns/op             568 B/op         16 allocs/op
BenchmarkGorillaMux_Param20       100000             14199 ns/op            3277 B/op         11 allocs/op
BenchmarkHttpRouter_Param20      1000000              1790 ns/op             640 B/op          1 allocs/op
BenchmarkHttpTreeMux_Param20      200000              7524 ns/op            2188 B/op          4 allocs/op
BenchmarkKocha_Param20            300000              6193 ns/op            1808 B/op         27 allocs/op
BenchmarkMacaron_Param20          100000             14366 ns/op            4291 B/op         20 allocs/op
BenchmarkMartini_Param20           20000             68579 ns/op            3645 B/op         14 allocs/op
BenchmarkPat_Param20              300000              4796 ns/op            1408 B/op         25 allocs/op
BenchmarkRevel_Param20            100000             20410 ns/op            5552 B/op         54 allocs/op
BenchmarkRivet_Param20            200000              9790 ns/op            2619 B/op         26 allocs/op
BenchmarkTigerTonic_Param20        30000             52599 ns/op           10541 B/op        178 allocs/op
BenchmarkTraffic_Param20           50000             32802 ns/op            8000 B/op         66 allocs/op
BenchmarkVulcan_Param20          1000000              2303 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_Param20            1000000              2461 ns/op             784 B/op          6 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).

BenchmarkAce_ParamWrite          5000000               404 ns/op              40 B/op          2 allocs/op
BenchmarkBeego_ParamWrite        1000000              2952 ns/op             728 B/op         11 allocs/op
BenchmarkBone_ParamWrite          500000              3796 ns/op            1072 B/op         13 allocs/op
BenchmarkDenco_ParamWrite        5000000               328 ns/op              32 B/op          1 allocs/op
BenchmarkGin_ParamWrite          3000000               418 ns/op              40 B/op          2 allocs/op
BenchmarkGocraftWeb_ParamWrite   1000000              2470 ns/op             664 B/op         10 allocs/op
BenchmarkGoji_ParamWrite         1000000              1270 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_ParamWrite    200000             11968 ns/op            2184 B/op         38 allocs/op
BenchmarkGoRestful_ParamWrite     500000              3834 ns/op             568 B/op         16 allocs/op
BenchmarkGorillaMux_ParamWrite    500000              4391 ns/op             792 B/op         10 allocs/op
BenchmarkHttpRouter_ParamWrite   5000000               275 ns/op              32 B/op          1 allocs/op
BenchmarkHttpTreeMux_ParamWrite  2000000               951 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_ParamWrite        3000000               518 ns/op              56 B/op          3 allocs/op
BenchmarkMacaron_ParamWrite       500000              4968 ns/op            1208 B/op         15 allocs/op
BenchmarkMartini_ParamWrite       200000              9632 ns/op            1256 B/op         16 allocs/op
BenchmarkPat_ParamWrite           500000              4167 ns/op            1088 B/op         19 allocs/op
BenchmarkRevel_ParamWrite         200000              9273 ns/op            2128 B/op         33 allocs/op
BenchmarkRivet_ParamWrite        1000000              1649 ns/op             472 B/op          6 allocs/op
BenchmarkTigerTonic_ParamWrite    200000              6512 ns/op            1440 B/op         25 allocs/op
BenchmarkTraffic_ParamWrite       200000              8410 ns/op            2400 B/op         27 allocs/op
BenchmarkVulcan_ParamWrite       1000000              1030 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_ParamWrite          500000              4210 ns/op            1112 B/op         16 allocs/op

Parse.com

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.

BenchmarkAce_ParseStatic                10000000               127 ns/op               0 B/op          0 allocs/op
BenchmarkBeego_ParseStatic               1000000              1800 ns/op             368 B/op          7 allocs/op
BenchmarkBone_ParseStatic                2000000               695 ns/op             144 B/op          3 allocs/op
BenchmarkDenco_ParseStatic              20000000              58.0 ns/op               0 B/op          0 allocs/op
BenchmarkGin_ParseStatic                10000000               143 ns/op               0 B/op          0 allocs/op
BenchmarkGocraftWeb_ParseStatic          1000000              1265 ns/op             304 B/op          6 allocs/op
BenchmarkGoji_ParseStatic                3000000               438 ns/op               0 B/op          0 allocs/op
BenchmarkGoJsonRest_ParseStatic           200000              8209 ns/op            1064 B/op         29 allocs/op
BenchmarkGoRestful_ParseStatic            100000             14952 ns/op            2904 B/op         32 allocs/op
BenchmarkGorillaMux_ParseStatic           500000              3905 ns/op             464 B/op          8 allocs/op
BenchmarkHttpRouter_ParseStatic         30000000              55.3 ns/op               0 B/op          0 allocs/op
BenchmarkHttpTreeMux_ParseStatic        20000000              87.9 ns/op               0 B/op          0 allocs/op
BenchmarkKocha_ParseStatic              20000000              81.7 ns/op               0 B/op          0 allocs/op
BenchmarkMacaron_ParseStatic             1000000              2974 ns/op             752 B/op          8 allocs/op
BenchmarkMartini_ParseStatic              300000              6952 ns/op             832 B/op         11 allocs/op
BenchmarkPat_ParseStatic                 1000000              1027 ns/op             240 B/op          5 allocs/op
BenchmarkRevel_ParseStatic                300000              6923 ns/op            1288 B/op         25 allocs/op
BenchmarkRivet_ParseStatic               3000000               537 ns/op             112 B/op          2 allocs/op
BenchmarkTigerTonic_ParseStatic          5000000               356 ns/op              48 B/op          1 allocs/op
BenchmarkTraffic_ParseStatic              200000              7521 ns/op            2344 B/op         25 allocs/op
BenchmarkVulcan_ParseStatic               200000              7496 ns/op            2344 B/op         25 allocs/op
BenchmarkZeus_ParseStatic                1000000              1521 ns/op             256 B/op          6 allocs/op

BenchmarkAce_ParseParam                  5000000               334 ns/op              64 B/op          1 allocs/op
BenchmarkBeego_ParseParam                1000000              2886 ns/op             736 B/op         10 allocs/op
BenchmarkBone_ParseParam                 1000000              2659 ns/op             752 B/op         11 allocs/op
BenchmarkDenco_ParseParam                5000000               347 ns/op              64 B/op          1 allocs/op
BenchmarkGin_ParseParam                  5000000               344 ns/op              64 B/op          1 allocs/op
BenchmarkGocraftWeb_ParseParam           1000000              2376 ns/op             672 B/op          9 allocs/op
BenchmarkGoji_ParseParam                 1000000              1456 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_ParseParam            200000             10412 ns/op            1712 B/op         33 allocs/op
BenchmarkGoRestful_ParseParam             200000              7994 ns/op             568 B/op         16 allocs/op
BenchmarkGorillaMux_ParseParam            500000              4492 ns/op             784 B/op          9 allocs/op
BenchmarkHttpRouter_ParseParam           5000000               251 ns/op              64 B/op          1 allocs/op
BenchmarkHttpTreeMux_ParseParam          2000000               911 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_ParseParam                3000000               475 ns/op              56 B/op          3 allocs/op
BenchmarkMacaron_ParseParam               500000              4100 ns/op            1120 B/op         11 allocs/op
BenchmarkMartini_ParseParam               200000             10506 ns/op            1152 B/op         12 allocs/op
BenchmarkRevel_ParseParam                 200000              8457 ns/op            1704 B/op         28 allocs/op
BenchmarkRivet_ParseParam                1000000              1519 ns/op             464 B/op          5 allocs/op
BenchmarkPat_ParseParam                   500000              3926 ns/op            1136 B/op         20 allocs/op
BenchmarkTigerTonic_ParseParam            500000              4418 ns/op            1024 B/op         19 allocs/op
BenchmarkTraffic_ParseParam               200000              7665 ns/op            2280 B/op         25 allocs/op
BenchmarkVulcan_ParseParam               1000000              1125 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_ParseParam                 1000000              3557 ns/op             864 B/op         16 allocs/op

BenchmarkAce_Parse2Params                5000000               381 ns/op              64 B/op          1 allocs/op
BenchmarkBeego_Parse2Params              1000000              3272 ns/op             784 B/op         11 allocs/op
BenchmarkBone_Parse2Params               1000000              2495 ns/op             736 B/op         10 allocs/op
BenchmarkDenco_Parse2Params              3000000               414 ns/op              64 B/op          1 allocs/op
BenchmarkGin_Parse2Params                5000000               385 ns/op              64 B/op          1 allocs/op
BenchmarkGocraftWeb_Parse2Params         1000000              2670 ns/op             720 B/op         10 allocs/op
BenchmarkGoji_Parse2Params               1000000              1428 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_Parse2Params          200000             11545 ns/op            2064 B/op         36 allocs/op
BenchmarkGoRestful_Parse2Params           200000              8659 ns/op             568 B/op         16 allocs/op
BenchmarkGorillaMux_Parse2Params          300000              5257 ns/op             816 B/op          9 allocs/op
BenchmarkHttpRouter_Parse2Params         5000000               297 ns/op              64 B/op          1 allocs/op
BenchmarkHttpTreeMux_Parse2Params        1000000              1009 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_Parse2Params              2000000               836 ns/op             128 B/op          5 allocs/op
BenchmarkMacaron_Parse2Params             500000              4443 ns/op            1168 B/op         12 allocs/op
BenchmarkMartini_Parse2Params             200000             10658 ns/op            1184 B/op         12 allocs/op
BenchmarkRevel_Parse2Params               200000              8833 ns/op            1768 B/op         30 allocs/op
BenchmarkRivet_Parse2Params              1000000              1737 ns/op             480 B/op          6 allocs/op
BenchmarkPat_Parse2Params                 500000              3843 ns/op             864 B/op         21 allocs/op
BenchmarkTigerTonic_Parse2Params          200000              6969 ns/op            1440 B/op         28 allocs/op
BenchmarkTraffic_Parse2Params             200000              7947 ns/op            2088 B/op         25 allocs/op
BenchmarkVulcan_Parse2Params             1000000              1396 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_Parse2Params                500000              3938 ns/op             896 B/op         17 allocs/op

BenchmarkAce_ParseAll                     200000              8009 ns/op             640 B/op         16 allocs/op
BenchmarkBeego_ParseAll                    20000             70857 ns/op           15600 B/op        233 allocs/op
BenchmarkBone_ParseAll                     50000             35804 ns/op            8656 B/op        144 allocs/op
BenchmarkDenco_ParseAll                   200000              7701 ns/op             928 B/op         16 allocs/op
BenchmarkGin_ParseAll                     200000              8150 ns/op             640 B/op         16 allocs/op
BenchmarkGocraftWeb_ParseAll               30000             53824 ns/op           13936 B/op        207 allocs/op
BenchmarkGoji_ParseAll                     50000             28891 ns/op            5376 B/op         32 allocs/op
BenchmarkGoJsonRest_ParseAll               10000            257803 ns/op           39218 B/op        827 allocs/op
BenchmarkGoRestful_ParseAll                 5000            486378 ns/op           97312 B/op        904 allocs/op
BenchmarkGorillaMux_ParseAll               10000            165608 ns/op           17280 B/op        224 allocs/op
BenchmarkHttpRouter_ParseAll              300000              5375 ns/op             640 B/op         16 allocs/op
BenchmarkHttpTreeMux_ParseAll             100000             18532 ns/op            5376 B/op         32 allocs/op
BenchmarkKocha_ParseAll                   200000             12009 ns/op            1112 B/op         54 allocs/op
BenchmarkMacaron_ParseAll                  20000             98486 ns/op           25584 B/op        259 allocs/op
BenchmarkMartini_ParseAll                  10000            264803 ns/op           26848 B/op        302 allocs/op
BenchmarkRevel_ParseAll                    10000            210805 ns/op           40464 B/op        704 allocs/op
BenchmarkRivet_ParseAll                    50000             31548 ns/op            8592 B/op        103 allocs/op
BenchmarkPat_ParseAll                      20000             72594 ns/op           17568 B/op        382 allocs/op
BenchmarkTigerTonic_ParseAll               20000             97870 ns/op           20032 B/op        417 allocs/op
BenchmarkTraffic_ParseAll                  10000            242080 ns/op           69136 B/op        750 allocs/op
BenchmarkVulcan_ParseAll                   50000             36888 ns/op            2548 B/op         78 allocs/op
BenchmarkZeus_ParseAll                     10000            107571 ns/op           25504 B/op        463 allocs/op

GitHub

The GitHub API is rather large, consisting of 203 routes. The tasks are basically the same as in the benchmarks before.

BenchmarkAce_GithubStatic               10000000               169 ns/op               0 B/op          0 allocs/op
BenchmarkBeego_GithubStatic              1000000              1856 ns/op             368 B/op          7 allocs/op
BenchmarkBone_GithubStatic                100000             13747 ns/op            2880 B/op         60 allocs/op
BenchmarkDenco_GithubStatic             20000000              68.5 ns/op               0 B/op          0 allocs/op
BenchmarkGin_GithubStatic               10000000               188 ns/op               0 B/op          0 allocs/op
BenchmarkGocraftWeb_GithubStatic         1000000              1298 ns/op             304 B/op          6 allocs/op
BenchmarkGoji_GithubStatic               3000000               496 ns/op               0 B/op          0 allocs/op
BenchmarkGoRestful_GithubStatic            30000             51190 ns/op            2968 B/op         34 allocs/op
BenchmarkGoJsonRest_GithubStatic          200000              8264 ns/op            1080 B/op         29 allocs/op
BenchmarkGorillaMux_GithubStatic           50000             24870 ns/op             464 B/op          8 allocs/op
BenchmarkHttpRouter_GithubStatic        20000000              99.2 ns/op               0 B/op          0 allocs/op
BenchmarkHttpTreeMux_GithubStatic       20000000              86.1 ns/op               0 B/op          0 allocs/op
BenchmarkKocha_GithubStatic             20000000               105 ns/op               0 B/op          0 allocs/op
BenchmarkMacaron_GithubStatic            1000000              3010 ns/op             752 B/op          8 allocs/op
BenchmarkMartini_GithubStatic             100000             22996 ns/op             832 B/op         11 allocs/op
BenchmarkPat_GithubStatic                 100000             14131 ns/op            3648 B/op         76 allocs/op
BenchmarkRevel_GithubStatic               300000              7107 ns/op            1288 B/op         25 allocs/op
BenchmarkRivet_GithubStatic              3000000               563 ns/op             112 B/op          2 allocs/op
BenchmarkTigerTonic_GithubStatic         3000000               410 ns/op              48 B/op          1 allocs/op
BenchmarkTraffic_GithubStatic              20000             67309 ns/op           22792 B/op        167 allocs/op
BenchmarkVulcan_GithubStatic             1000000              1589 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_GithubStatic                 50000             41160 ns/op            7664 B/op        140 allocs/op

BenchmarkAce_GithubParam                 3000000               553 ns/op              96 B/op          1 allocs/op
BenchmarkBeego_GithubParam                500000              3525 ns/op             784 B/op         11 allocs/op
BenchmarkBone_GithubParam                1000000              3403 ns/op             853 B/op         12 allocs/op
BenchmarkDenco_GithubParam               2000000               625 ns/op             128 B/op          1 allocs/op
BenchmarkGin_GithubParam                 3000000               560 ns/op              96 B/op          1 allocs/op
BenchmarkGocraftWeb_GithubParam          1000000              2770 ns/op             720 B/op         10 allocs/op
BenchmarkGoji_GithubParam                1000000              1917 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_GithubParam           200000             11845 ns/op            2080 B/op         36 allocs/op
BenchmarkGoRestful_GithubParam             30000             43783 ns/op             568 B/op         16 allocs/op
BenchmarkGorillaMux_GithubParam           100000             14472 ns/op             816 B/op          9 allocs/op
BenchmarkHttpRouter_GithubParam          3000000               476 ns/op              96 B/op          1 allocs/op
BenchmarkHttpTreeMux_GithubParam         1000000              1190 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_GithubParam               2000000               935 ns/op             128 B/op          5 allocs/op
BenchmarkMacaron_GithubParam              500000              4551 ns/op            1168 B/op         12 allocs/op
BenchmarkMartini_GithubParam               50000             31201 ns/op            1184 B/op         12 allocs/op
BenchmarkPat_GithubParam                  200000             10139 ns/op            2480 B/op         56 allocs/op
BenchmarkRevel_GithubParam                200000              9009 ns/op            1784 B/op         30 allocs/op
BenchmarkRivet_GithubParam               1000000              1910 ns/op             480 B/op          6 allocs/op
BenchmarkTigerTonic_GithubParam           200000              7003 ns/op            1440 B/op         28 allocs/op
BenchmarkTraffic_GithubParam               50000             25926 ns/op            6984 B/op         59 allocs/op
BenchmarkVulcan_GithubParam               500000              2508 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_GithubParam                  50000             26529 ns/op            6448 B/op         96 allocs/op

BenchmarkAce_GithubAll                     10000            101042 ns/op           13792 B/op        167 allocs/op
BenchmarkBeego_GithubAll                    2000            702309 ns/op          146272 B/op       2092 allocs/op
BenchmarkBone_GithubAll                     1000           1699515 ns/op          360704 B/op       5370 allocs/op
BenchmarkDenco_GithubAll                   10000            111352 ns/op           20224 B/op        167 allocs/op
BenchmarkGin_GithubAll                     10000            104368 ns/op           13792 B/op        167 allocs/op
BenchmarkGocraftWeb_GithubAll               5000            524757 ns/op          133280 B/op       1889 allocs/op
BenchmarkGoji_GithubAll                     2000            981690 ns/op           56112 B/op        334 allocs/op
BenchmarkGoJsonRest_GithubAll               1000           2308087 ns/op          387716 B/op       7069 allocs/op
BenchmarkGoRestful_GithubAll                 100          11144575 ns/op          598108 B/op       7152 allocs/op
BenchmarkGorillaMux_GithubAll                200           8798084 ns/op          153137 B/op       1791 allocs/op
BenchmarkHttpRouter_GithubAll              20000             82522 ns/op           13792 B/op        167 allocs/op
BenchmarkHttpTreeMux_GithubAll             10000            208423 ns/op           56112 B/op        334 allocs/op
BenchmarkKocha_GithubAll                   10000            183138 ns/op           23304 B/op        843 allocs/op
BenchmarkMacaron_GithubAll                  2000            943212 ns/op          224960 B/op       2315 allocs/op
BenchmarkMartini_GithubAll                   100          13946836 ns/op          237952 B/op       2686 allocs/op
BenchmarkPat_GithubAll                       300           5622027 ns/op         1504101 B/op      32222 allocs/op
BenchmarkRevel_GithubAll                    1000           1800536 ns/op          345553 B/op       5918 allocs/op
BenchmarkRivet_GithubAll                   10000            334249 ns/op           84272 B/op       1079 allocs/op
BenchmarkTigerTonic_GithubAll               2000           1313607 ns/op          241088 B/op       6052 allocs/op
BenchmarkTraffic_GithubAll                   100          12054665 ns/op         3103197 B/op      24284 allocs/op
BenchmarkVulcan_GithubAll                   5000            402176 ns/op           19894 B/op        609 allocs/op
BenchmarkZeus_GithubAll                      200           9157014 ns/op         1925239 B/op      30938 allocs/op

Google+

Last but not least the Google+ API, consisting of 13 routes. In reality this is just a subset of a much larger API.

BenchmarkAce_GPlusStatic                10000000               123 ns/op               0 B/op          0 allocs/op
BenchmarkBeego_GPlusStatic               1000000              1673 ns/op             352 B/op          7 allocs/op
BenchmarkBone_GPlusStatic               10000000               212 ns/op              32 B/op          1 allocs/op
BenchmarkDenco_GPlusStatic              30000000              48.3 ns/op               0 B/op          0 allocs/op
BenchmarkGin_GPlusStatic                10000000               138 ns/op               0 B/op          0 allocs/op
BenchmarkGocraftWeb_GPlusStatic          1000000              1191 ns/op             288 B/op          6 allocs/op
BenchmarkGoji_GPlusStatic                5000000               352 ns/op               0 B/op          0 allocs/op
BenchmarkGoJsonRest_GPlusStatic           200000              8232 ns/op            1064 B/op         29 allocs/op
BenchmarkGoRestful_GPlusStatic            200000              9405 ns/op            1736 B/op         28 allocs/op
BenchmarkGorillaMux_GPlusStatic          1000000              2604 ns/op             464 B/op          8 allocs/op
BenchmarkHttpRouter_GPlusStatic         30000000              52.5 ns/op               0 B/op          0 allocs/op
BenchmarkHttpTreeMux_GPlusStatic        30000000              50.5 ns/op               0 B/op          0 allocs/op
BenchmarkKocha_GPlusStatic              20000000              76.5 ns/op               0 B/op          0 allocs/op
BenchmarkMacaron_GPlusStatic             1000000              2899 ns/op             736 B/op          8 allocs/op
BenchmarkMartini_GPlusStatic              300000              6046 ns/op             832 B/op         11 allocs/op
BenchmarkPat_GPlusStatic                 3000000               425 ns/op              96 B/op          2 allocs/op
BenchmarkRevel_GPlusStatic                300000              6823 ns/op            1272 B/op         25 allocs/op
BenchmarkRivet_GPlusStatic               3000000               510 ns/op             112 B/op          2 allocs/op
BenchmarkTigerTonic_GPlusStatic         10000000               233 ns/op              32 B/op          1 allocs/op
BenchmarkTraffic_GPlusStatic              300000              4939 ns/op            1480 B/op         19 allocs/op
BenchmarkVulcan_GPlusStatic              2000000               957 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_GPlusStatic                3000000               429 ns/op              48 B/op          2 allocs/op

BenchmarkAce_GPlusParam                  5000000               385 ns/op              64 B/op          1 allocs/op
BenchmarkBeego_GPlusParam                1000000              2940 ns/op             720 B/op         10 allocs/op
BenchmarkBone_GPlusParam                 1000000              2452 ns/op             696 B/op         10 allocs/op
BenchmarkDenco_GPlusParam                5000000               359 ns/op              64 B/op          1 allocs/op
BenchmarkGin_GPlusParam                  5000000               392 ns/op              64 B/op          1 allocs/op
BenchmarkGocraftWeb_GPlusParam           1000000              2301 ns/op             656 B/op          9 allocs/op
BenchmarkGoji_GPlusParam                 1000000              1312 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_GPlusParam            200000             10726 ns/op            1728 B/op         33 allocs/op
BenchmarkGoRestful_GPlusParam             200000              7841 ns/op             632 B/op         18 allocs/op
BenchmarkGorillaMux_GPlusParam            300000              5398 ns/op             784 B/op          9 allocs/op
BenchmarkHttpRouter_GPlusParam           5000000               294 ns/op              64 B/op          1 allocs/op
BenchmarkHttpTreeMux_GPlusParam          2000000               930 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_GPlusParam                3000000               512 ns/op              56 B/op          3 allocs/op
BenchmarkMacaron_GPlusParam               500000              4077 ns/op            1104 B/op         11 allocs/op
BenchmarkMartini_GPlusParam               200000             11757 ns/op            1152 B/op         12 allocs/op
BenchmarkPat_GPlusParam                  1000000              2701 ns/op             704 B/op         14 allocs/op
BenchmarkRevel_GPlusParam                 200000              8374 ns/op            1704 B/op         28 allocs/op
BenchmarkRivet_GPlusParam                1000000              1557 ns/op             464 B/op          5 allocs/op
BenchmarkTigerTonic_GPlusParam            500000              4575 ns/op            1064 B/op         19 allocs/op
BenchmarkTraffic_GPlusParam               200000              7626 ns/op            2000 B/op         23 allocs/op
BenchmarkVulcan_GPlusParam               1000000              1410 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_GPlusParam                 1000000              2935 ns/op             752 B/op         13 allocs/op

BenchmarkAce_GPlus2Params                3000000               447 ns/op              64 B/op          1 allocs/op
BenchmarkBeego_GPlus2Params               500000              3755 ns/op             784 B/op         11 allocs/op
BenchmarkBone_GPlus2Params                500000              3669 ns/op             896 B/op         12 allocs/op
BenchmarkDenco_GPlus2Params              3000000               495 ns/op              64 B/op          1 allocs/op
BenchmarkGin_GPlus2Params                3000000               453 ns/op              64 B/op          1 allocs/op
BenchmarkGocraftWeb_GPlus2Params         1000000              2771 ns/op             720 B/op         10 allocs/op
BenchmarkGoji_GPlus2Params               1000000              1802 ns/op             336 B/op          2 allocs/op
BenchmarkGoJsonRest_GPlus2Params          200000             12098 ns/op            2096 B/op         36 allocs/op
BenchmarkGoRestful_GPlus2Params           200000              9790 ns/op             632 B/op         18 allocs/op
BenchmarkGorillaMux_GPlus2Params          200000             11349 ns/op             816 B/op          9 allocs/op
BenchmarkHttpRouter_GPlus2Params         5000000               358 ns/op              64 B/op          1 allocs/op
BenchmarkHttpTreeMux_GPlus2Params        1000000              1116 ns/op             336 B/op          2 allocs/op
BenchmarkKocha_GPlus2Params              2000000               939 ns/op             128 B/op          5 allocs/op
BenchmarkMacaron_GPlus2Params             500000              4473 ns/op            1168 B/op         12 allocs/op
BenchmarkMartini_GPlus2Params              50000             38068 ns/op            1280 B/op         16 allocs/op
BenchmarkPat_GPlus2Params                 200000              8489 ns/op            2304 B/op         41 allocs/op
BenchmarkRevel_GPlus2Params               200000              9014 ns/op            1800 B/op         30 allocs/op
BenchmarkRivet_GPlus2Params              1000000              1777 ns/op             480 B/op          6 allocs/op
BenchmarkTigerTonic_GPlus2Params          200000              7387 ns/op            1528 B/op         28 allocs/op
BenchmarkTraffic_GPlus2Params             100000             17274 ns/op            3552 B/op         35 allocs/op
BenchmarkVulcan_GPlus2Params             1000000              2053 ns/op              98 B/op          3 allocs/op
BenchmarkZeus_GPlus2Params                200000             11579 ns/op            2680 B/op         41 allocs/op

BenchmarkAce_GPlusAll                     300000              4996 ns/op             640 B/op         11 allocs/op
BenchmarkBeego_GPlusAll                    30000             39325 ns/op            8976 B/op        129 allocs/op
BenchmarkBone_GPlusAll                    100000             18105 ns/op            3472 B/op         59 allocs/op
BenchmarkDenco_GPlusAll                   300000              5277 ns/op             672 B/op         11 allocs/op
BenchmarkGin_GPlusAll                     300000              5110 ns/op             640 B/op         11 allocs/op
BenchmarkGocraftWeb_GPlusAll               50000             30943 ns/op            8144 B/op        116 allocs/op
BenchmarkGoji_GPlusAll                    100000             18565 ns/op            3696 B/op         22 allocs/op
BenchmarkGoJsonRest_GPlusAll               10000            143977 ns/op           22849 B/op        436 allocs/op
BenchmarkGoRestful_GPlusAll                10000            170441 ns/op           26264 B/op        404 allocs/op
BenchmarkGorillaMux_GPlusAll               20000             87191 ns/op            9712 B/op        115 allocs/op
BenchmarkHttpRouter_GPlusAll              500000              3774 ns/op             640 B/op         11 allocs/op
BenchmarkHttpTreeMux_GPlusAll             200000             11488 ns/op            3696 B/op         22 allocs/op
BenchmarkKocha_GPlusAll                   200000              8773 ns/op             976 B/op         43 allocs/op
BenchmarkMacaron_GPlusAll                  30000             53987 ns/op           13968 B/op        142 allocs/op
BenchmarkMartini_GPlusAll                  10000            210862 ns/op           15072 B/op        178 allocs/op
BenchmarkPat_GPlusAll                      20000             66910 ns/op           16880 B/op        343 allocs/op
BenchmarkRevel_GPlusAll                    10000            110125 ns/op           21656 B/op        368 allocs/op
BenchmarkRivet_GPlusAll                   100000             19947 ns/op            5408 B/op         64 allocs/op
BenchmarkTigerTonic_GPlusAll               20000             72119 ns/op           14800 B/op        320 allocs/op
BenchmarkTraffic_GPlusAll                  10000            156004 ns/op           41184 B/op        439 allocs/op
BenchmarkVulcan_GPlusAll                  100000             19854 ns/op            1274 B/op         39 allocs/op
BenchmarkZeus_GPlusAll                     20000             90316 ns/op           19024 B/op        352 allocs/op

Conclusions

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.