mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-14 04:54:04 +08:00
在route中使用netip.Addr;修订代码;添加一些go test
This commit is contained in:
@@ -400,7 +400,7 @@ https://t.me/shadowrocket_unofficial
|
|||||||
|
|
||||||
## 免责
|
## 免责
|
||||||
|
|
||||||
MIT协议!作者不负任何责任。本项目只是个代理项目,适合内网测试使用,以及适合阅读代码了解原理。
|
MIT协议!作者不负任何责任。本项目只是个poc项目,适合内网测试使用,以及适合阅读代码了解原理。
|
||||||
|
|
||||||
你如果用于任何其它目的,我们不会帮助你。
|
你如果用于任何其它目的,我们不会帮助你。
|
||||||
|
|
||||||
|
2
go.sum
2
go.sum
@@ -8,8 +8,6 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
|||||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||||
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
|
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
|
||||||
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
|
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
|
||||||
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
|
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
|
||||||
github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
|
github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
@@ -125,6 +125,16 @@ func (a *Addr) UrlString() string {
|
|||||||
return a.Network + "://" + url.PathEscape(str)
|
return a.Network + "://" + url.PathEscape(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Addr) GetNetIPAddr() (na netip.Addr) {
|
||||||
|
if len(a.IP) < 1 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
na, _ = netip.AddrFromSlice(a.IP)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Addr) ToUDPAddr() *net.UDPAddr {
|
func (a *Addr) ToUDPAddr() *net.UDPAddr {
|
||||||
switch a.Network {
|
switch a.Network {
|
||||||
case "udp", "udp4", "udp6":
|
case "udp", "udp4", "udp6":
|
||||||
|
152
netLayer/cidr_test.go
Normal file
152
netLayer/cidr_test.go
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
package netLayer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/netip"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/yl2chen/cidranger"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
go1.18
|
||||||
|
goos: darwin
|
||||||
|
goarch: arm64
|
||||||
|
Benchmark_CIDR_ranger-8 30880119 38.38 ns/op
|
||||||
|
Benchmark_CIDR200_ranger-8 10963292 107.9 ns/op
|
||||||
|
Benchmark_CIDR_netIPList-8 341961285 3.507 ns/op
|
||||||
|
Benchmark_CIDR60_netIPList-8 11371914 105.4 ns/op
|
||||||
|
Benchmark_CIDR200_netIPList-8 3625110 331.4 ns/op
|
||||||
|
|
||||||
|
60个以内时,直接用 netip.Prefix 列表进行遍历更快;其他情况 cidranger 更快;
|
||||||
|
|
||||||
|
考虑到我们国别分流直接用的mmdb,而不是自己给ip段, 而如果要自定义ip段的话,很少有能自定义好几十个点,所以这个确实可以直接用列表优化一下。 不过依然是纳秒级,意义不大
|
||||||
|
*/
|
||||||
|
|
||||||
|
func Benchmark_CIDR_ranger(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
theRange := "192.168.1.0/24"
|
||||||
|
theIPStr := "192.168.1.23"
|
||||||
|
theIP := net.ParseIP(theIPStr)
|
||||||
|
netRanger := cidranger.NewPCTrieRanger()
|
||||||
|
if _, net, err := net.ParseCIDR(theRange); err == nil {
|
||||||
|
netRanger.Insert(cidranger.NewBasicRangerEntry(*net))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
netRanger.Contains(theIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Benchmark_CIDR200_ranger(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
netRanger := cidranger.NewPCTrieRanger()
|
||||||
|
|
||||||
|
theIPStr := "192.168.1.23"
|
||||||
|
theIP := net.ParseIP(theIPStr)
|
||||||
|
|
||||||
|
for i := 0; i < 200; i++ {
|
||||||
|
theRange := "192.168." + strconv.Itoa(i) + ".0/24"
|
||||||
|
|
||||||
|
if _, net, err := net.ParseCIDR(theRange); err == nil {
|
||||||
|
netRanger.Insert(cidranger.NewBasicRangerEntry(*net))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
netRanger.Contains(theIP)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Benchmark_CIDR_netIPList(b *testing.B) {
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
ipStr := "192.168.1.0/24"
|
||||||
|
ipStr2 := "192.168.1.23"
|
||||||
|
theIP, err := netip.ParseAddr(ipStr2)
|
||||||
|
if err != nil {
|
||||||
|
b.Log(err)
|
||||||
|
b.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
thelist := make([]netip.Prefix, 0, 10)
|
||||||
|
|
||||||
|
ipnet, err := netip.ParsePrefix(ipStr)
|
||||||
|
if err != nil {
|
||||||
|
b.Log(err)
|
||||||
|
b.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
thelist = append(thelist, ipnet)
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, n := range thelist {
|
||||||
|
if n.Contains(theIP) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func Benchmark_CIDR60_netIPList(b *testing.B) {
|
||||||
|
benchmark_CIDR_netIPList(b, 60)
|
||||||
|
|
||||||
|
}
|
||||||
|
func Benchmark_CIDR200_netIPList(b *testing.B) {
|
||||||
|
benchmark_CIDR_netIPList(b, 200)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmark_CIDR_netIPList(b *testing.B, num int) {
|
||||||
|
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
theIPStr := "192.168." + strconv.Itoa(num/2) + ".23"
|
||||||
|
theIP, err := netip.ParseAddr(theIPStr)
|
||||||
|
if err != nil {
|
||||||
|
b.Log(err)
|
||||||
|
b.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
thelist := make([]netip.Prefix, num)
|
||||||
|
|
||||||
|
for i := 0; i < num; i++ {
|
||||||
|
theRange := "192.168." + strconv.Itoa(i) + ".0/24"
|
||||||
|
|
||||||
|
ipnet, err := netip.ParsePrefix(theRange)
|
||||||
|
if err != nil {
|
||||||
|
b.Log(err)
|
||||||
|
b.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
thelist[i] = ipnet
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, n := range thelist {
|
||||||
|
if n.Contains(theIP) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
package netLayer
|
package netLayer
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// transport Layer, 使用uint16 mask,所以最多支持16种
|
// Transport Layer Protocols, 使用uint16 mask,所以最多支持16种
|
||||||
|
|
||||||
TCP uint16 = 1 << iota
|
TCP uint16 = 1 << iota
|
||||||
UDP
|
UDP
|
||||||
@@ -16,9 +16,9 @@ const (
|
|||||||
|
|
||||||
func StrToTransportProtocol(s string) uint16 {
|
func StrToTransportProtocol(s string) uint16 {
|
||||||
switch s {
|
switch s {
|
||||||
case "tcp":
|
case "tcp", "tcp4", "tcp6":
|
||||||
return TCP
|
return TCP
|
||||||
case "udp":
|
case "udp", "udp4", "udp6":
|
||||||
return UDP
|
return UDP
|
||||||
case "unix":
|
case "unix":
|
||||||
return UNIX
|
return UNIX
|
||||||
@@ -28,7 +28,6 @@ func StrToTransportProtocol(s string) uint16 {
|
|||||||
return KCP
|
return KCP
|
||||||
case "quic":
|
case "quic":
|
||||||
return Quic
|
return Quic
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@@ -29,7 +29,7 @@ func HasEmbedGeoip() bool {
|
|||||||
func loadMaxmindGeoipBytes(bs []byte) {
|
func loadMaxmindGeoipBytes(bs []byte) {
|
||||||
db, err := maxminddb.FromBytes(bs)
|
db, err := maxminddb.FromBytes(bs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("loadMaxmindGeoipBytes", err)
|
log.Fatalln("err when loadMaxmindGeoipBytes", err)
|
||||||
}
|
}
|
||||||
the_geoipdb = db
|
the_geoipdb = db
|
||||||
}
|
}
|
||||||
|
35
netLayer/mmdb_test.go
Normal file
35
netLayer/mmdb_test.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package netLayer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hahahrfool/v2ray_simple/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
/* go test -bench "CheckMMDB_country" . -v
|
||||||
|
BenchmarkCheckMMDB_country-8 3631854 315.3 ns/op
|
||||||
|
|
||||||
|
总之一次mmdb查询比map查询慢了十倍多 (见 utils/container_test.go.bak)
|
||||||
|
|
||||||
|
有必要设置一个 国别-ip 的map缓存; 不过这种纳秒级别的优化就无所谓了
|
||||||
|
*/
|
||||||
|
|
||||||
|
func BenchmarkCheckMMDB_country(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
LoadMaxmindGeoipFile(utils.GetFilePath("../" + GeoipFileName))
|
||||||
|
|
||||||
|
if the_geoipdb == nil {
|
||||||
|
log.Fatalln("err load")
|
||||||
|
}
|
||||||
|
|
||||||
|
theIP := net.ParseIP("1.22.233.44")
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
GetIP_ISO(theIP)
|
||||||
|
}
|
||||||
|
}
|
@@ -357,11 +357,11 @@ func BenchmarkClassicCopy_SimulateRealWorld_ReadV(b *testing.B) {
|
|||||||
b.Log(err)
|
b.Log(err)
|
||||||
b.FailNow()
|
b.FailNow()
|
||||||
}
|
}
|
||||||
|
unit := bigBytesLen / 10
|
||||||
|
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
||||||
for i := 0; i < transmitCount; i++ {
|
for i := 0; i < transmitCount; i++ {
|
||||||
unit := bigBytesLen / 10
|
|
||||||
|
|
||||||
for cursor := 0; cursor < bigBytesLen; cursor += unit {
|
for cursor := 0; cursor < bigBytesLen; cursor += unit {
|
||||||
_, e := tcpConn.Write(bigBytes[cursor : cursor+unit])
|
_, e := tcpConn.Write(bigBytes[cursor : cursor+unit])
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
package netLayer
|
package netLayer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net/netip"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/yl2chen/cidranger"
|
"github.com/yl2chen/cidranger"
|
||||||
@@ -18,18 +18,17 @@ type TargetDescription struct {
|
|||||||
// 这里的相同点,就是它们同属于 将发往一个方向, 即同属一个路由策略
|
// 这里的相同点,就是它们同属于 将发往一个方向, 即同属一个路由策略
|
||||||
// 任意一个参数匹配后,都将发往相同的方向,由该方向OutTag 指定
|
// 任意一个参数匹配后,都将发往相同的方向,由该方向OutTag 指定
|
||||||
// RouteSet 只负责把一些属性相同的 “网络层/传输层 特征” 放到一起
|
// RouteSet 只负责把一些属性相同的 “网络层/传输层 特征” 放到一起
|
||||||
//
|
|
||||||
// 目前先使用map,以后优化时再考虑使用 能加速查找 的数据结构
|
|
||||||
type RouteSet struct {
|
type RouteSet struct {
|
||||||
//网络层
|
//网络层
|
||||||
NetRanger cidranger.Ranger //一个范围
|
NetRanger cidranger.Ranger //一个范围
|
||||||
IPs map[string]net.IP //一个确定值
|
IPs map[netip.Addr]bool //一个确定值
|
||||||
Domains, InTags, Countries map[string]bool // Countries 使用 ISO 3166 字符串 作为key
|
Domains, InTags, Countries map[string]bool // Countries 使用 ISO 3166 字符串 作为key
|
||||||
|
|
||||||
//传输层
|
//传输层
|
||||||
AllowedTransportLayerProtocols uint16
|
AllowedTransportLayerProtocols uint16
|
||||||
|
|
||||||
OutTag string //目标
|
OutTag string //目标
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouteSetForMyCountry(iso string) *RouteSet {
|
func NewRouteSetForMyCountry(iso string) *RouteSet {
|
||||||
@@ -51,7 +50,7 @@ func NewRouteSetForMyCountry(iso string) *RouteSet {
|
|||||||
func NewFullRouteSet() *RouteSet {
|
func NewFullRouteSet() *RouteSet {
|
||||||
return &RouteSet{
|
return &RouteSet{
|
||||||
NetRanger: cidranger.NewPCTrieRanger(),
|
NetRanger: cidranger.NewPCTrieRanger(),
|
||||||
IPs: make(map[string]net.IP),
|
IPs: make(map[netip.Addr]bool),
|
||||||
Domains: make(map[string]bool),
|
Domains: make(map[string]bool),
|
||||||
InTags: make(map[string]bool),
|
InTags: make(map[string]bool),
|
||||||
Countries: make(map[string]bool),
|
Countries: make(map[string]bool),
|
||||||
@@ -60,7 +59,7 @@ func NewFullRouteSet() *RouteSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sg *RouteSet) IsIn(td *TargetDescription) bool {
|
func (sg *RouteSet) IsIn(td *TargetDescription) bool {
|
||||||
if td.Tag != "" {
|
if td.Tag != "" && sg.InTags != nil {
|
||||||
if _, found := sg.InTags[td.Tag]; found {
|
if _, found := sg.InTags[td.Tag]; found {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -89,16 +88,15 @@ func (sg *RouteSet) IsTCPAllowed() bool {
|
|||||||
func (sg *RouteSet) IsAddrIn(a *Addr) bool {
|
func (sg *RouteSet) IsAddrIn(a *Addr) bool {
|
||||||
//我们先过滤传输层,再过滤网络层
|
//我们先过滤传输层,再过滤网络层
|
||||||
|
|
||||||
//目前我们仅支持udp和tcp这两种传输层协议,所以可以如此。以后如果加了更多的话,还需改动
|
|
||||||
if !sg.IsAddrNetworkAllowed(a) {
|
if !sg.IsAddrNetworkAllowed(a) {
|
||||||
return false
|
return false
|
||||||
|
|
||||||
} else if sg.NetRanger == nil && sg.IPs == nil && sg.Domains == nil && sg.InTags == nil && sg.Countries == nil {
|
} else if sg.NetRanger == nil && sg.IPs == nil && sg.Domains == nil && sg.Countries == nil {
|
||||||
//如果仅限制了一个传输层协议,且本集合里没有任何其它内容,那就直接通过
|
//如果仅限制了一个传输层协议,且本集合里没有任何其它内容,那就直接通过
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
//开始网络层判断
|
//开始网络层判断
|
||||||
if a.IP != nil {
|
if len(a.IP) > 0 {
|
||||||
if sg.NetRanger != nil {
|
if sg.NetRanger != nil {
|
||||||
if has, _ := sg.NetRanger.Contains(a.IP); has {
|
if has, _ := sg.NetRanger.Contains(a.IP); has {
|
||||||
return true
|
return true
|
||||||
@@ -114,7 +112,7 @@ func (sg *RouteSet) IsAddrIn(a *Addr) bool {
|
|||||||
|
|
||||||
}
|
}
|
||||||
if sg.IPs != nil {
|
if sg.IPs != nil {
|
||||||
if _, found := sg.IPs[a.IP.To16().String()]; found {
|
if _, found := sg.IPs[a.GetNetIPAddr()]; found {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,7 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -154,9 +155,10 @@ func LoadRuleForRouteSet(rule *RuleConf) (rs *netLayer.RouteSet) {
|
|||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ip := net.ParseIP(ipStr); ip != nil {
|
|
||||||
rs.IPs[ipStr] = ip
|
na, e := netip.ParseAddr(ipStr)
|
||||||
continue
|
if e == nil {
|
||||||
|
rs.IPs[na] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
194
utils/container_test.go.bak
Normal file
194
utils/container_test.go.bak
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
package utils_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/bits-and-blooms/bloom/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
|
go1.18
|
||||||
|
goos: darwin
|
||||||
|
goarch: arm64
|
||||||
|
pkg: github.com/hahahrfool/v2ray_simple/utils
|
||||||
|
BenchmarkSliceFind_10-8 152484100 7.447 ns/op
|
||||||
|
BenchmarkSliceFind_20-8 100000000 10.43 ns/op
|
||||||
|
BenchmarkSliceFind_40-8 73516086 16.45 ns/op
|
||||||
|
BenchmarkSliceFind_80-8 40491806 30.28 ns/op
|
||||||
|
BenchmarkMapFind_10-8 131343604 8.255 ns/op
|
||||||
|
BenchmarkMapFind_20-8 77772673 13.84 ns/op
|
||||||
|
BenchmarkMapFind_40-8 78834778 14.75 ns/op
|
||||||
|
BenchmarkMapFind_80-8 77047785 15.59 ns/op
|
||||||
|
BenchmarkMapFind_800-8 78424113 14.88 ns/op
|
||||||
|
BenchmarkMapFind_8000-8 78607766 15.09 ns/op
|
||||||
|
BenchmarkMapFind_800000-8 51825218 21.70 ns/op
|
||||||
|
BenchmarkMapFind_80000000-8 21130418 57.20 ns/op
|
||||||
|
BenchmarkBloomFind_10-8 134930332 8.418 ns/op
|
||||||
|
BenchmarkBloomFind_20-8 78121606 16.51 ns/op
|
||||||
|
BenchmarkBloomFind_40-8 73593855 19.28 ns/op
|
||||||
|
BenchmarkBloomFind_80-8 81744565 14.12 ns/op
|
||||||
|
BenchmarkBloomFind_800-8 79790108 15.19 ns/op
|
||||||
|
BenchmarkBloomFind_8000-8 78823557 15.27 ns/op
|
||||||
|
BenchmarkBloomFind_800000-8 53090004 21.57 ns/op
|
||||||
|
BenchmarkBloomFind_80000000-8 21073072 56.83 ns/op
|
||||||
|
PASS
|
||||||
|
ok github.com/hahahrfool/v2ray_simple/utils 147.920s
|
||||||
|
|
||||||
|
|
||||||
|
总之数量小于四十时, 直接用数组循环查找是更快的,但是几纳秒的节约没有实际意义;
|
||||||
|
|
||||||
|
布隆过滤器没测出比map强在哪里,而且还可能假阳性,暂不考虑; 结论是直接用map匹配即可,无需任何其它机制。
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
func BenchmarkSliceFind_10(b *testing.B) {
|
||||||
|
benchmarkSliceFind(b, 10)
|
||||||
|
}
|
||||||
|
func BenchmarkSliceFind_20(b *testing.B) {
|
||||||
|
benchmarkSliceFind(b, 20)
|
||||||
|
}
|
||||||
|
func BenchmarkSliceFind_40(b *testing.B) {
|
||||||
|
benchmarkSliceFind(b, 40)
|
||||||
|
}
|
||||||
|
func BenchmarkSliceFind_80(b *testing.B) {
|
||||||
|
benchmarkSliceFind(b, 80)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMapFind_10(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 10)
|
||||||
|
}
|
||||||
|
func BenchmarkMapFind_20(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 20)
|
||||||
|
}
|
||||||
|
func BenchmarkMapFind_40(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 40)
|
||||||
|
}
|
||||||
|
func BenchmarkMapFind_80(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 80)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMapFind_800(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 800)
|
||||||
|
}
|
||||||
|
func BenchmarkMapFind_8000(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 8000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMapFind_800000(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 800000)
|
||||||
|
}
|
||||||
|
func BenchmarkMapFind_80000000(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 80000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkSliceFind(b *testing.B, size int) {
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
s := make([]int, size)
|
||||||
|
for i := range s {
|
||||||
|
s[i] = rand.Intn(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
randBuf := make([]int, b.N)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
randBuf[i] = rand.Intn(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for j := range s {
|
||||||
|
if s[j] == randBuf[i] {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBloomFind_10(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBloomFind_20(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBloomFind_40(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 40)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBloomFind_80(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 80)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBloomFind_800(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 800)
|
||||||
|
}
|
||||||
|
func BenchmarkBloomFind_8000(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 8000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkBloomFind_800000(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 800000)
|
||||||
|
}
|
||||||
|
func BenchmarkBloomFind_80000000(b *testing.B) {
|
||||||
|
benchmarkMapFind(b, 80000000)
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkMapFind(b *testing.B, size int) {
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
s := make(map[int]bool)
|
||||||
|
for i := 0; i < size; i++ {
|
||||||
|
s[rand.Intn(size)] = true
|
||||||
|
}
|
||||||
|
|
||||||
|
randBuf := make([]int, b.N)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
randBuf[i] = rand.Intn(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
|
||||||
|
if s[randBuf[i]] {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkBloomFind(b *testing.B, size uint32) {
|
||||||
|
b.StopTimer()
|
||||||
|
b.ResetTimer()
|
||||||
|
s := bloom.NewWithEstimates(uint(b.N), 0.01)
|
||||||
|
|
||||||
|
var curRand uint32
|
||||||
|
|
||||||
|
for i := 0; i < int(size); i++ {
|
||||||
|
curRand = uint32(rand.Intn(int(size)))
|
||||||
|
|
||||||
|
s.Add((*(*[4]byte)(unsafe.Pointer(&curRand)))[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
randBuf := make([]int, b.N)
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
randBuf[i] = rand.Intn(int(size))
|
||||||
|
}
|
||||||
|
|
||||||
|
b.StartTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
|
||||||
|
if s.Test((*(*[4]byte)(unsafe.Pointer(&randBuf[i])))[:]) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user