Open2

Potetoの水溜まり

ぽてとぽてと

PotetoはGolangのwebAPIフレームワーク
https://github.com/poteto0/poteto

こんな感じで良い感じにroutingできる。

func main() {
	p := poteto.New()

	// Leaf >= 0.21.0
	p.Leaf("/users", func(userApi poteto.Leaf) {
		userApi.Register(middleware.CamaraWithConfig(middleware.DefaultCamaraConfig))
		userApi.GET("/", controller.UserHandler)
		userApi.GET("/:name", controller.UserIdHandler)
	})

	p.Run(":8000")
}

routingについての詳しい話はこちら
https://zenn.dev/poteto0/articles/aae407f0d21f0f

ぽてとぽてと

v0.23.4アップデート

ルーターのパフォーマンスチューニングを行いました!!

パフォーマンスが2倍に

プルリク

https://github.com/poteto0/poteto/pull/117

変更内容

元々検索の際に、例えば

params := strings.Split(path, "/")
for _, param := range params {
  ...
}

のように配列を作ってループを回していました。この処理を以下のように毎回インデックスから取得するように変えました。

for {
  id := strings.Index(rightPath, "/")
  if id < 0 {
    param = rightPath
  } else {
    param = rightPath[:id]
    rightPath = rightPath[(id + 1):]
  }
  ...
}

要因

これはstrings.Split()が内部でループを挟むため、計算量が2Nになっていたことが原因です。

func genSplit(s, sep string, sepSave, n int) []string {
	if n == 0 {
		return nil
	}
	if sep == "" {
		return explode(s, n)
	}
	if n < 0 {
		n = Count(s, sep) + 1
	}

	if n > len(s)+1 {
		n = len(s) + 1
	}
	a := make([]string, n)
	n--
	i := 0
	for i < n {
		m := Index(s, sep)
		if m < 0 {
			break
		}
		a[i] = s[:m+sepSave]
		s = s[m+len(sep):]
		i++
	}
	a[i] = s
	return a[:i+1]
}

競プロとかではあまりNと2Nを区別している印象はないですが、webフレームワークはこれだけで捌けるリクエスト数が2倍になるので、大きな差があります