比 GIN 更快的路径匹配算法来了

2023-02-13 13:19:34 +08:00
 Nazz

uRouter v1.2.4版本中, 大幅改进了路由映射性能, 零开销路径匹配, 成为了速度最快的 net/http 框架之一.

Benchmark

goos: darwin
goarch: arm64
pkg: github.com/lxzan/uRouter
BenchmarkOneRoute-8             	77647704	        13.53 ns/op	       0 B/op	       0 allocs/op
BenchmarkOneRouteDynamic-8      	34728837	        34.69 ns/op	       0 B/op	       0 allocs/op
BenchmarkRecoveryMiddleware-8   	70822222	        16.99 ns/op	       0 B/op	       0 allocs/op
Benchmark5Params-8              	15952770	        73.23 ns/op	       0 B/op	       0 allocs/op
BenchmarkOneRouteJSON-8         	89840808	        13.39 ns/op	       0 B/op	       0 allocs/op
Benchmark404-8                  	81540667	        14.89 ns/op	       0 B/op	       0 allocs/op
Benchmark404Many-8              	35411809	        34.11 ns/op	       0 B/op	       0 allocs/op
PASS
goos: darwin
goarch: arm64
pkg: github.com/gin-gonic/gin
BenchmarkOneRoute-8             	45460980	        26.13 ns/op	       0 B/op	       0 allocs/op
BenchmarkRecoveryMiddleware-8   	38337534	        31.00 ns/op	       0 B/op	       0 allocs/op
Benchmark5Params-8              	18889320	        63.42 ns/op	       0 B/op	       0 allocs/op
BenchmarkOneRouteJSON-8         	 7542141	       162.7 ns/op	      48 B/op	       3 allocs/op
Benchmark404-8                  	29467527	        43.23 ns/op	       0 B/op	       0 allocs/op
Benchmark404Many-8              	27458932	        43.92 ns/op	       0 B/op	       0 allocs/op
PASS
得益于`map`, 大部分测试项目都比`gin`快. `uRouter`的路由算法采用动静分离模式, 静态路由使用`map`, 动态路由使用`trie`.

在 v1.2.4 版本中, 主要改进如下:

func FastSplit(str string, f func(segment string) bool) {
	var n = len(str)
	var i = 1
	var j = i
	for k := i; k < n; k++ {
		if str[k] == SeparatorByte || k == n-1 {
			if k == n-1 {
				j++
			}
			if !f(str[i:j]) {
				return
			}
			i = k + 1
			j = i
		} else {
			j++
		}
	}
}
func (c *routeTree) Get(path string) (*apiHandler, bool) {
	var tree = c
	var expected = 0
	var actual = 0

	FastSplit(path, func(str string) bool {
		expected++
		if v, ok := tree.Children[str]; ok {
			tree = v
			actual++
			return true
		}
		if v, ok := tree.Children["*"]; ok {
			tree = v
			actual++
			return true
		}
		return false
	})

	if expected == actual {
		return tree.Value, tree.Value != nil
	}
	return nil, false
}

链接: https://github.com/lxzan/uRouter/blob/main/matcher.go

1730 次点击
所在节点    程序员
4 条回复
missdeer
2023-02-13 13:41:09 +08:00
好像之前看过一个评测说 gin 算是比较慢的梯队里的,连 beego 都比它快得多。。
Nazz
2023-02-13 13:49:46 +08:00
@missdeer 除非 beego 用了非 net/http 实现, 否则不可能, gin 性能和 裸 http 差不多.
R18
2023-02-13 13:52:19 +08:00
有和 echo 的对比吗,毕竟 gin 已经很"老"了
Nazz
2023-02-13 14:08:52 +08:00
@R18 echo 出现时间和 gin 差不多吧. 没对比过 echo, 但是我和 bare net/http 对比过 RPS

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/915648

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX