LoginSignup
15
5

More than 5 years have passed since last update.

GoでHTTPルータを作ってみた

Last updated at Posted at 2017-03-01

はじめに

パトリシア木を使ってHTTPルーティングすると早いって聞いたので、
こんな感じかなと思ってGoで実装してみました

要件

まず、下記のようなパスのパターンをルーティングするとします

GET /users
GET /users/:name
GET /users/taro/man
GET /users/hanako/woman
GET /users/akira/:sex
GET /users/:name/:sex
GET /users/:name/woman

パスのパターンとして二種類あって、パラム付きは : と * の二種類をメタ文字として扱います
まあよくあるやつです

  • 静的パターン /users/taro/man
  • パラム付きパターン /users/:name/woman

優先度は 静的 → : → * とします

実装

で、考えた結果こんな感じの木になりました
オレンジは終端ノードです

スクリーンショット 2017-03-01 17.07.57.png

ルックアップの処理として、まず根の下にメソッドがあってそれを進みます
次にフルパスが静的パスかどうかを判定します
先頭に / があるものが静的のフルパスになります
判定に失敗したらパラム付きパスと判断して、ディレクトリ単位で木を辿っていきます
ディレクトリの静的判定に失敗したときに、兄弟にパラム付きの物があればそっちに進みます
文字列が最後まで進んだとき、ノードに http.HandlerFunc が入っていたらそれを返します

詳しくは下記に実装してみたので見てみてください
https://github.com/ngc224/mux/

ベンチマーク

で、せっかく作ったので早いと言われている他のルーターとくらべてみました
BenchmarkMy が今回作ったやつです
ミドルウェアなどの機能がないからかもしれませんが、まあそこそこの速度は出ているようです

BenchmarkMy_GithubAll                    10000         229581 ns/op        53444 B/op          501 allocs/op
BenchmarkBeego_GithubAll                  3000         438911 ns/op        74709 B/op          812 allocs/op
BenchmarkChi_GithubAll                   10000         295937 ns/op        61716 B/op          406 allocs/op
BenchmarkDenco_GithubAll                 20000          96656 ns/op        20224 B/op          167 allocs/op
BenchmarkGin_GithubAll                   50000          44018 ns/op            0 B/op            0 allocs/op
BenchmarkHttpRouter_GithubAll            20000          65990 ns/op        13792 B/op          167 allocs/op
BenchmarkLARS_GithubAll                  50000          33338 ns/op            0 B/op            0 allocs/op
BenchmarkPossum_GithubAll                 3000         385266 ns/op        84454 B/op          609 allocs/op
BenchmarkRivet_GithubAll                 10000         119507 ns/op        16272 B/op          167 allocs/op
BenchmarkTango_GithubAll                  3000         441718 ns/op        63845 B/op         1618 allocs/op
BenchmarkVulcan_GithubAll                10000         263241 ns/op        19894 B/op          609 allocs/op

何故か静的パスが早いです

BenchmarkMy_StaticAll                   200000           9118 ns/op            0 B/op            0 allocs/op
BenchmarkBeego_StaticAll                  5000         356464 ns/op        57780 B/op          628 allocs/op
BenchmarkChi_StaticAll                   10000         201796 ns/op        47731 B/op          314 allocs/op
BenchmarkDenco_StaticAll                200000           9202 ns/op            0 B/op            0 allocs/op
BenchmarkGin_StaticAll                  100000          20539 ns/op            0 B/op            0 allocs/op
BenchmarkHttpRouter_StaticAll           100000          12728 ns/op            0 B/op            0 allocs/op
BenchmarkHttpTreeMux_StaticAll          100000          12333 ns/op            0 B/op            0 allocs/op
BenchmarkLARS_StaticAll                  50000          20841 ns/op            0 B/op            0 allocs/op
BenchmarkPossum_StaticAll                 5000         282806 ns/op        65316 B/op          471 allocs/op
BenchmarkRivet_StaticAll                 50000          29397 ns/op            0 B/op            0 allocs/op
BenchmarkTango_StaticAll                  5000         321933 ns/op        39235 B/op         1256 allocs/op
BenchmarkVulcan_StaticAll                10000         177711 ns/op        15386 B/op          471 allocs/op

総評

ていうか分岐していない節を一つにまとめたものをパトリシア木っていうらしいですが、
これ違いますね...
他のルータの実装見て研究していきたいです

15
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
5