diff --git a/bench_test.go b/bench_test.go index a875ee8..3271a4c 100644 --- a/bench_test.go +++ b/bench_test.go @@ -200,6 +200,12 @@ func BenchmarkGorillaMux_Param(b *testing.B) { r, _ := http.NewRequest("GET", "/user/gordon", nil) benchRequest(b, router, r) } +func BenchmarkGouldianRouter_Param(b *testing.B) { + router := loadGouldianRouterSingle("GET", []interface{}{"user", gouldianName}, gouldianHandle) + + r, _ := http.NewRequest("GET", "/user/gordon", nil) + benchRequest(b, router, r) +} func BenchmarkGowwwRouter_Param(b *testing.B) { router := loadGowwwRouterSingle("GET", "/user/:name", http.HandlerFunc(httpHandlerFunc)) @@ -410,6 +416,13 @@ func BenchmarkGorillaMux_Param5(b *testing.B) { r, _ := http.NewRequest("GET", fiveRoute, nil) benchRequest(b, router, r) } +func BenchmarkGouldianRouter_Param5(b *testing.B) { + path := []interface{}{"r", gldV0, gldV1, gldV2, gldV3, gldV4} + router := loadGouldianRouterSingle("GET", path, gouldianHandle) + + r, _ := http.NewRequest("GET", "/r"+fiveRoute, nil) + benchRequest(b, router, r) +} func BenchmarkGowwwRouter_Param5(b *testing.B) { router := loadGowwwRouterSingle("GET", fiveColon, http.HandlerFunc(httpHandlerFunc)) @@ -620,6 +633,14 @@ func BenchmarkGorillaMux_Param20(b *testing.B) { r, _ := http.NewRequest("GET", twentyRoute, nil) benchRequest(b, router, r) } +func BenchmarkGouldianRouter_Param20(b *testing.B) { + path := []interface{}{"r", gldV0, gldV1, gldV2, gldV3, gldV4, gldV5, gldV6, gldV7, gldV8, gldV9, gldV0, gldV1, gldV2, gldV3, gldV4, gldV5, gldV6, gldV7, gldV8, gldV9} + router := loadGouldianRouterSingle("GET", path, gouldianHandle) + + r, _ := http.NewRequest("GET", "/r"+twentyRoute, nil) + benchRequest(b, router, r) +} + func BenchmarkGowwwRouter_Param20(b *testing.B) { router := loadGowwwRouterSingle("GET", twentyColon, http.HandlerFunc(httpHandlerFunc)) @@ -826,6 +847,12 @@ func BenchmarkGorillaMux_ParamWrite(b *testing.B) { r, _ := http.NewRequest("GET", "/user/gordon", nil) benchRequest(b, router, r) } +func BenchmarkGouldianRouter_ParamWrite(b *testing.B) { + router := loadGouldianRouterSingle("GET", []interface{}{"user", gouldianName}, gouldianHandleWrite) + + r, _ := http.NewRequest("GET", "/user/gordon", nil) + benchRequest(b, router, r) +} func BenchmarkGowwwRouter_ParamWrite(b *testing.B) { router := loadGowwwRouterSingle("GET", "/user/:name", http.HandlerFunc(gowwwRouterHandleWrite)) diff --git a/github_test.go b/github_test.go index 6f483cd..681e255 100644 --- a/github_test.go +++ b/github_test.go @@ -290,6 +290,7 @@ var ( githubGoJsonRest http.Handler githubGoRestful http.Handler githubGorillaMux http.Handler + githubGouldian http.Handler githubGowwwRouter http.Handler githubHttpRouter http.Handler githubHttpTreeMux http.Handler @@ -360,6 +361,9 @@ func init() { calcMem("GorillaMux", func() { githubGorillaMux = loadGorillaMux(githubAPI) }) + calcMem("Gouldian", func() { + githubGouldian = loadGouldianRouter(githubAPI) + }) calcMem("GowwwRouter", func() { githubGowwwRouter = loadGowwwRouter(githubAPI) }) @@ -480,6 +484,10 @@ func BenchmarkGorillaMux_GithubStatic(b *testing.B) { req, _ := http.NewRequest("GET", "/user/repos", nil) benchRequest(b, githubGorillaMux, req) } +func BenchmarkGouldian_GithubStatic(b *testing.B) { + req, _ := http.NewRequest("GET", "/user/repos", nil) + benchRequest(b, githubGouldian, req) +} func BenchmarkGowwwRouter_GithubStatic(b *testing.B) { req, _ := http.NewRequest("GET", "/user/repos", nil) benchRequest(b, githubGowwwRouter, req) @@ -616,6 +624,10 @@ func BenchmarkGorillaMux_GithubParam(b *testing.B) { req, _ := http.NewRequest("GET", "/repos/julienschmidt/httprouter/stargazers", nil) benchRequest(b, githubGorillaMux, req) } +func BenchmarkGouldian_GithubParam(b *testing.B) { + req, _ := http.NewRequest("GET", "/repos/julienschmidt/httprouter/stargazers", nil) + benchRequest(b, githubGouldian, req) +} func BenchmarkGowwwRouter_GithubParam(b *testing.B) { req, _ := http.NewRequest("GET", "/repos/julienschmidt/httprouter/stargazers", nil) benchRequest(b, githubGowwwRouter, req) @@ -736,6 +748,9 @@ func BenchmarkGoRestful_GithubAll(b *testing.B) { func BenchmarkGorillaMux_GithubAll(b *testing.B) { benchRoutes(b, githubGorillaMux, githubAPI) } +func BenchmarkGouldian_GithubAll(b *testing.B) { + benchRoutes(b, githubGouldian, githubAPI) +} func BenchmarkGowwwRouter_GithubAll(b *testing.B) { benchRoutes(b, githubGowwwRouter, githubAPI) } diff --git a/go.mod b/go.mod index b911842..763ba7e 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect github.com/dimfeld/httptreemux v5.0.1+incompatible github.com/emicklei/go-restful v2.10.0+incompatible + github.com/fogfish/gouldian v1.4.1 github.com/fsnotify/fsnotify v1.4.7 // indirect github.com/gin-gonic/gin v1.5.0 github.com/go-chi/chi v4.0.2+incompatible diff --git a/go.sum b/go.sum index 258bc82..559bec3 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ gitea.com/lunny/log v0.0.0-20190322053110-01b5df579c4e h1:r1en/D7xJmcY24VkHkjkcJFa+7ZWubVWPBrvsHkmHxk= gitea.com/lunny/log v0.0.0-20190322053110-01b5df579c4e/go.mod h1:uJEsN4LQpeGYRCjuPXPZBClU7N5pWzGuyF4uqLpE/e0= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/OwnLocal/goes v1.0.0/go.mod h1:8rIFjBGTue3lCU0wplczcUgt9Gxgrkkrw7etMIcn8TM= github.com/aerogo/aero v1.3.42 h1:MW/zMYnlyzATokbSUHTq8aGGja3SCA9eUuKj+ueoRyA= @@ -15,6 +16,8 @@ github.com/aerogo/session v0.1.8 h1:l28Ii/YBfh4/vDWOc1YXLXg2vkHsRFuMLAeVhhl1eME= github.com/aerogo/session v0.1.8/go.mod h1:Q9QqpT8nM6HTaklE14T+bzNSKrwW1M2wZ/NZV1HUTB0= github.com/aerogo/session-store-memory v0.1.9 h1:1OswTCtyqzffX5aGr6jI3H8gt/hkU3LKNiKpia7ntcs= github.com/aerogo/session-store-memory v0.1.9/go.mod h1:z4ZxP+xLVdH69F/Cvgy93v8fWzeDmiJo+Mm+Th3un4c= +github.com/ajg/form v1.5.2-0.20200323032839-9aeb3cf462e1 h1:8Qzi+0Uch1VJvdrOhJ8U8FqoPLbUdETPgMqGJ6DSMSQ= +github.com/ajg/form v1.5.2-0.20200323032839-9aeb3cf462e1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/akyoto/assert v0.2.2/go.mod h1:g5e6ag+ksCEQENq/LnmU9z04wCAIFDr8KacBusVL0H8= github.com/akyoto/assert v0.2.3/go.mod h1:g5e6ag+ksCEQENq/LnmU9z04wCAIFDr8KacBusVL0H8= github.com/akyoto/assert v0.2.4 h1:n0FwcNH5dMYq3I8Iu7MOR1WWGkkGH8ao84nvCRJmsbs= @@ -36,6 +39,7 @@ github.com/ant0ine/go-json-rest v3.3.2+incompatible h1:nBixrkLFiDNAW0hauKDLc8yJI github.com/ant0ine/go-json-rest v3.3.2+incompatible/go.mod h1:q6aCt0GfU6LhpBsnZ/2U+mwe+0XB5WStbmwyoPfc+sk= github.com/astaxie/beego v1.12.0 h1:MRhVoeeye5N+Flul5PoVfD9CslfdoH+xqC/xvSQ5u2Y= github.com/astaxie/beego v1.12.0/go.mod h1:fysx+LZNZKnvh4GED/xND7jWtjCR6HzydR2Hh2Im57o= +github.com/aws/aws-lambda-go v1.23.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo= @@ -50,6 +54,8 @@ github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcju github.com/couchbase/go-couchbase v0.0.0-20181122212707-3e9b6e1258bb/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -62,6 +68,12 @@ github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3C github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= github.com/emicklei/go-restful v2.10.0+incompatible h1:l6Soi8WCOOVAeCo4W98iBFC6Og7/X8bpRt51oNLZ2C8= github.com/emicklei/go-restful v2.10.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/fogfish/gouldian v1.4.1 h1:RfbCP3nTZ5B+dJGZJesU9UKqwdKR+V7UiUbmKTEacuI= +github.com/fogfish/gouldian v1.4.1/go.mod h1:pwL6eiqvM9HxBpSRQ06SvkDWtpqtRPJBliATFSweL6k= +github.com/fogfish/guid v1.0.0 h1:Wf19/7IWFAQvuvfJDEc/Jr47OzFm+Mk+zHJnvo6S31k= +github.com/fogfish/guid v1.0.0/go.mod h1:5iZJAJEepH9rXpnNOi+UYIIzjX57yQqMpXF6K/nKEEg= +github.com/fogfish/it v0.9.1 h1:Pu+qgqBV2ilZDzZzPIbUIhMIkdpHgbGUsdEwVQvBxNQ= +github.com/fogfish/it v0.9.1/go.mod h1:NQJG4Ygvek85y7zGj0Gny8+6ygAnHjfBORhI7TdQhp4= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -119,7 +131,6 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -177,10 +188,12 @@ github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7 github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-tigertonic v0.0.0-20170420123839-fe6b9f080eb7 h1:IF6au04LnXfITvXy4gwKKcka4zKYp73RXCEGUACqC/Y= github.com/rcrowley/go-tigertonic v0.0.0-20170420123839-fe6b9f080eb7/go.mod h1:iFmRpXEuybfivhzfxebaHxO63V+ye2AFJMBk12tZPck= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM= github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo= github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= github.com/siddontang/ledisdb v0.0.0-20181029004158-becf5f38d373/go.mod h1:mF1DpOSOUiJRMR+FDqaqu3EBqrybQtrDDszLUZ6oxPg= github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= @@ -198,8 +211,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= @@ -209,10 +223,10 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM= github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/ursiform/bear v1.0.1 h1:77/y+Hiir4LyLTyUdj0MmxpcW6rYLgeX8WLLxM7e7uY= github.com/ursiform/bear v1.0.1/go.mod h1:AYsqyNUafOkYwqZV0zZeBkTOpfCRfWCNWvO5CnO7Tv4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -232,7 +246,6 @@ goji.io v2.0.2+incompatible h1:uIssv/elbKRLznFUy3Xj4+2Mz/qKhek/9aZQDUMae7c= goji.io v2.0.2+incompatible/go.mod h1:sbqFwrtqZACxLBTQcdgVjFh54yGVCvwq8+w49MVMMIk= golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -240,7 +253,6 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190926025831-c00fd9afed17 h1:qPnAdmjNA41t3QBTx2mFGf/SD1IoslhYu7AmdsVzCcs= golang.org/x/net v0.0.0-20190926025831-c00fd9afed17/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -250,7 +262,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191025090151-53bf42e6b339 h1:zSqWKgm/o7HAnlAzBQ+aetp9fpuyytsXnKA8eiLHYQM= @@ -269,7 +280,6 @@ gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXa gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= -gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag= gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.48.0 h1:URjZc+8ugRY5mL5uUeQH/a63JcHwdX9xZaWvmNWD7z8= gopkg.in/ini.v1 v1.48.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -278,3 +288,6 @@ gopkg.in/macaron.v1 v1.3.4/go.mod h1:/RoHTdC8ALpyJ3+QR36mKjwnT1F1dyYtsGM9Ate6ZFI gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/gplus_test.go b/gplus_test.go index b11699a..552ef83 100644 --- a/gplus_test.go +++ b/gplus_test.go @@ -52,6 +52,7 @@ var ( gplusGoJsonRest http.Handler gplusGoRestful http.Handler gplusGorillaMux http.Handler + gplusGouldian http.Handler gplusGowwwRouter http.Handler gplusHttpRouter http.Handler gplusHttpTreeMux http.Handler @@ -122,6 +123,9 @@ func init() { calcMem("GorillaMux", func() { gplusGorillaMux = loadGorillaMux(gplusAPI) }) + calcMem("Gouldian", func() { + gplusGouldian = loadGouldianRouter(gplusAPI) + }) calcMem("GowwwRouter", func() { gplusGowwwRouter = loadGowwwRouter(gplusAPI) }) @@ -242,6 +246,10 @@ func BenchmarkGorillaMux_GPlusStatic(b *testing.B) { req, _ := http.NewRequest("GET", "/people", nil) benchRequest(b, gplusGorillaMux, req) } +func BenchmarkGouldian_GPlusStatic(b *testing.B) { + req, _ := http.NewRequest("GET", "/people", nil) + benchRequest(b, gplusGouldian, req) +} func BenchmarkGowwwRouter_GPlusStatic(b *testing.B) { req, _ := http.NewRequest("GET", "/people", nil) benchRequest(b, gplusGowwwRouter, req) @@ -378,6 +386,10 @@ func BenchmarkGorillaMux_GPlusParam(b *testing.B) { req, _ := http.NewRequest("GET", "/people/118051310819094153327", nil) benchRequest(b, gplusGorillaMux, req) } +func BenchmarkGouldian_GPlusParam(b *testing.B) { + req, _ := http.NewRequest("GET", "/people/118051310819094153327", nil) + benchRequest(b, gplusGouldian, req) +} func BenchmarkGowwwRouter_GPlusParam(b *testing.B) { req, _ := http.NewRequest("GET", "/people/118051310819094153327", nil) benchRequest(b, gplusGowwwRouter, req) @@ -514,6 +526,10 @@ func BenchmarkGorillaMux_GPlus2Params(b *testing.B) { req, _ := http.NewRequest("GET", "/people/118051310819094153327/activities/123456789", nil) benchRequest(b, gplusGorillaMux, req) } +func BenchmarkGouldian_GPlus2Params(b *testing.B) { + req, _ := http.NewRequest("GET", "/people/118051310819094153327/activities/123456789", nil) + benchRequest(b, gplusGouldian, req) +} func BenchmarkGowwwRouter_GPlus2Params(b *testing.B) { req, _ := http.NewRequest("GET", "/people/118051310819094153327/activities/123456789", nil) benchRequest(b, gplusGowwwRouter, req) @@ -634,6 +650,9 @@ func BenchmarkGoRestful_GPlusAll(b *testing.B) { func BenchmarkGorillaMux_GPlusAll(b *testing.B) { benchRoutes(b, gplusGorillaMux, gplusAPI) } +func BenchmarkGouldian_GPlusAll(b *testing.B) { + benchRoutes(b, gplusGouldian, gplusAPI) +} func BenchmarkGowwwRouter_GPlusAll(b *testing.B) { benchRoutes(b, gplusGowwwRouter, gplusAPI) } diff --git a/parse_test.go b/parse_test.go index 51a6520..dc800c5 100644 --- a/parse_test.go +++ b/parse_test.go @@ -72,6 +72,7 @@ var ( parseGoJsonRest http.Handler parseGoRestful http.Handler parseGorillaMux http.Handler + parseGouldian http.Handler parseGowwwRouter http.Handler parseHttpRouter http.Handler parseHttpTreeMux http.Handler @@ -142,6 +143,9 @@ func init() { calcMem("GorillaMux", func() { parseGorillaMux = loadGorillaMux(parseAPI) }) + calcMem("Gouldian", func() { + parseGouldian = loadGouldianRouter(parseAPI) + }) calcMem("GowwwRouter", func() { parseGowwwRouter = loadGowwwRouter(parseAPI) }) @@ -262,6 +266,10 @@ func BenchmarkGorillaMux_ParseStatic(b *testing.B) { req, _ := http.NewRequest("GET", "/1/users", nil) benchRequest(b, parseGorillaMux, req) } +func BenchmarkGouldian_ParseStatic(b *testing.B) { + req, _ := http.NewRequest("GET", "/1/users", nil) + benchRequest(b, parseGouldian, req) +} func BenchmarkGowwwRouter_ParseStatic(b *testing.B) { req, _ := http.NewRequest("GET", "/1/users", nil) benchRequest(b, parseGowwwRouter, req) @@ -398,6 +406,10 @@ func BenchmarkGorillaMux_ParseParam(b *testing.B) { req, _ := http.NewRequest("GET", "/1/classes/go", nil) benchRequest(b, parseGorillaMux, req) } +func BenchmarkGouldian_ParseParam(b *testing.B) { + req, _ := http.NewRequest("GET", "/1/classes/go", nil) + benchRequest(b, parseGouldian, req) +} func BenchmarkGowwwRouter_ParseParam(b *testing.B) { req, _ := http.NewRequest("GET", "/1/classes/go", nil) benchRequest(b, parseGowwwRouter, req) @@ -534,6 +546,10 @@ func BenchmarkGorillaMux_Parse2Params(b *testing.B) { req, _ := http.NewRequest("GET", "/1/classes/go/123456789", nil) benchRequest(b, parseGorillaMux, req) } +func BenchmarkGouldian_Parse2Params(b *testing.B) { + req, _ := http.NewRequest("GET", "/1/classes/go/123456789", nil) + benchRequest(b, parseGouldian, req) +} func BenchmarkGowwwRouter_Parse2Params(b *testing.B) { req, _ := http.NewRequest("GET", "/1/classes/go/123456789", nil) benchRequest(b, parseGowwwRouter, req) @@ -654,6 +670,9 @@ func BenchmarkGoRestful_ParseAll(b *testing.B) { func BenchmarkGorillaMux_ParseAll(b *testing.B) { benchRoutes(b, parseGorillaMux, parseAPI) } +func BenchmarkGouldian_ParseAll(b *testing.B) { + benchRoutes(b, parseGouldian, parseAPI) +} func BenchmarkGowwwRouter_ParseAll(b *testing.B) { benchRoutes(b, parseGowwwRouter, parseAPI) } diff --git a/routers.go b/routers.go index c94f8fe..94ba759 100644 --- a/routers.go +++ b/routers.go @@ -12,6 +12,7 @@ import ( "os" "regexp" "runtime" + "strings" // If you add new routers please: // - Keep the benchmark functions etc. alphabetically sorted @@ -27,6 +28,9 @@ import ( cloudykitrouter "github.com/cloudykit/router" "github.com/dimfeld/httptreemux" "github.com/emicklei/go-restful" + µ "github.com/fogfish/gouldian" + "github.com/fogfish/gouldian/optics" + "github.com/fogfish/gouldian/server/httpd" "github.com/gin-gonic/gin" "github.com/go-chi/chi" "github.com/go-martini/martini" @@ -872,6 +876,78 @@ func loadGorillaMuxSingle(method, path string, handler http.HandlerFunc) http.Ha return m } +// gouldian +type gouldianReqType struct{ Name string } + +var gouldianName = optics.ForProduct1(gouldianReqType{}) + +type gouldianReqLargeType struct { + V0, V1, V2, V3, V4, V5, V6, V7, V8, V9 string +} + +var gldV0, gldV1, gldV2, gldV3, gldV4, gldV5, gldV6, gldV7, gldV8, gldV9 = optics.ForProduct10(gouldianReqLargeType{}) + +func gouldianHandle(*µ.Context) error { return nil } + +func gouldianHandleWrite(ctx *µ.Context) error { + var req gouldianReqType + if err := ctx.Get(&req); err != nil { + return µ.Status.BadRequest() + } + + return µ.Status.OK(µ.WithText(req.Name)) +} + +func gouldianHandleTest(ctx *µ.Context) error { + return µ.Status.OK(µ.WithText(ctx.Request.RequestURI)) +} + +func loadGouldianRouter(routes []route) http.Handler { + h := gouldianHandle + if loadTestHandler { + h = gouldianHandleTest + } + + seq := make([]µ.Routable, 0, len(routes)) + for _, ep := range routes { + lens := []interface{}{gldV0, gldV1, gldV2, gldV3, gldV4, gldV5, gldV6, gldV7, gldV8, gldV9} + segs := []interface{}{} + path := strings.Split(ep.path, "/")[1:] + for _, seg := range path { + switch { + case len(seg) == 0: + break + case seg[0] != ':': + segs = append(segs, seg) + continue + default: + segs = append(segs, lens[0]) + lens = lens[1:] + } + } + seq = append(seq, + µ.Route( + µ.Path(segs...), + µ.Method(ep.method), + h, + )) + } + + return httpd.Serve(seq...) +} + +func loadGouldianRouterSingle(method string, path []interface{}, handler func(*µ.Context) error) http.Handler { + router := httpd.Serve( + µ.Route( + µ.Path(path...), + µ.Method(method), + handler, + ), + ) + + return router +} + // gowww/router func gowwwRouterHandleWrite(w http.ResponseWriter, r *http.Request) { io.WriteString(w, gowwwrouter.Parameter(r, "name")) diff --git a/static_test.go b/static_test.go index c11823f..d268d1c 100644 --- a/static_test.go +++ b/static_test.go @@ -188,6 +188,7 @@ var ( staticGoJsonRest http.Handler staticGoRestful http.Handler staticGorillaMux http.Handler + staticGouldian http.Handler staticGowwwRouter http.Handler staticHttpRouter http.Handler staticHttpTreeMux http.Handler @@ -266,6 +267,9 @@ func init() { calcMem("GorillaMux", func() { staticGorillaMux = loadGorillaMux(staticRoutes) }) + calcMem("Gouldian", func() { + staticGouldian = loadGouldianRouter(staticRoutes) + }) calcMem("GowwwRouter", func() { staticGowwwRouter = loadGowwwRouter(staticRoutes) }) @@ -374,6 +378,9 @@ func BenchmarkGoRestful_StaticAll(b *testing.B) { func BenchmarkGorillaMux_StaticAll(b *testing.B) { benchRoutes(b, staticGorillaMux, staticRoutes) } +func BenchmarkGouldian_StaticAll(b *testing.B) { + benchRoutes(b, staticGouldian, staticRoutes) +} func BenchmarkGowwwRouter_StaticAll(b *testing.B) { benchRoutes(b, staticGowwwRouter, staticRoutes) }