Skip to content

Commit a9ce6d4

Browse files
authored
Refine geodata decoder (#322)
* Refactor: geodata loader * Feat: add membench & benchmark for geodata decoder * Feat: log router memory usage when initialization
1 parent 9c437b9 commit a9ce6d4

File tree

4 files changed

+118
-43
lines changed

4 files changed

+118
-43
lines changed

common/geodata/decode_test.go

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,19 @@ import (
66
"io/fs"
77
"os"
88
"path/filepath"
9+
"runtime"
910
"testing"
1011

1112
"github.com/p4gefau1t/trojan-go/common"
1213
"github.com/p4gefau1t/trojan-go/common/geodata"
1314
)
1415

15-
const (
16-
geoipURL = "https://raw.githubusercontent.com/v2fly/geoip/release/geoip.dat"
17-
geositeURL = "https://raw.githubusercontent.com/v2fly/domain-list-community/release/dlc.dat"
18-
)
19-
2016
func init() {
17+
const (
18+
geoipURL = "https://raw.githubusercontent.com/v2fly/geoip/release/geoip.dat"
19+
geositeURL = "https://raw.githubusercontent.com/v2fly/domain-list-community/release/dlc.dat"
20+
)
21+
2122
wd, err := os.Getwd()
2223
common.Must(err)
2324

@@ -66,3 +67,39 @@ func TestDecodeGeoSite(t *testing.T) {
6667
t.Errorf("failed to load geosite:test, expected: %v, got: %v", expected, result)
6768
}
6869
}
70+
71+
func BenchmarkLoadGeoIP(b *testing.B) {
72+
m1 := runtime.MemStats{}
73+
m2 := runtime.MemStats{}
74+
75+
loader := geodata.GetGeodataLoader()
76+
77+
runtime.ReadMemStats(&m1)
78+
cn, _ := loader.LoadGeoIP("cn")
79+
private, _ := loader.LoadGeoIP("private")
80+
runtime.KeepAlive(cn)
81+
runtime.KeepAlive(private)
82+
runtime.ReadMemStats(&m2)
83+
84+
b.ReportMetric(float64(m2.Alloc-m1.Alloc)/1024, "KiB(GeoIP-Alloc)")
85+
b.ReportMetric(float64(m2.TotalAlloc-m1.TotalAlloc)/1024/1024, "MiB(GeoIP-TotalAlloc)")
86+
}
87+
88+
func BenchmarkLoadGeoSite(b *testing.B) {
89+
m3 := runtime.MemStats{}
90+
m4 := runtime.MemStats{}
91+
92+
loader := geodata.GetGeodataLoader()
93+
94+
runtime.ReadMemStats(&m3)
95+
cn, _ := loader.LoadGeoSite("cn")
96+
notcn, _ := loader.LoadGeoSite("geolocation-!cn")
97+
private, _ := loader.LoadGeoSite("private")
98+
runtime.KeepAlive(cn)
99+
runtime.KeepAlive(notcn)
100+
runtime.KeepAlive(private)
101+
runtime.ReadMemStats(&m4)
102+
103+
b.ReportMetric(float64(m4.Alloc-m3.Alloc)/1024/1024, "MiB(GeoSite-Alloc)")
104+
b.ReportMetric(float64(m4.TotalAlloc-m3.TotalAlloc)/1024/1024, "MiB(GeoSite-TotalAlloc)")
105+
}

common/geodata/load.go

Lines changed: 0 additions & 36 deletions
This file was deleted.

common/geodata/loader.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package geodata
2+
3+
import (
4+
"runtime"
5+
6+
v2router "github.com/v2fly/v2ray-core/v4/app/router"
7+
)
8+
9+
type geodataLoader interface {
10+
LoadIP(filename, country string) ([]*v2router.CIDR, error)
11+
LoadSite(filename, list string) ([]*v2router.Domain, error)
12+
LoadGeoIP(country string) ([]*v2router.CIDR, error)
13+
LoadGeoSite(list string) ([]*v2router.Domain, error)
14+
}
15+
16+
func GetGeodataLoader() geodataLoader {
17+
return &geodataCache{
18+
make(map[string]*v2router.GeoIP),
19+
make(map[string]*v2router.GeoSite),
20+
}
21+
}
22+
23+
type geodataCache struct {
24+
GeoIPCache
25+
GeoSiteCache
26+
}
27+
28+
func (g *geodataCache) LoadIP(filename, country string) ([]*v2router.CIDR, error) {
29+
geoip, err := g.GeoIPCache.Unmarshal(filename, country)
30+
if err != nil {
31+
return nil, err
32+
}
33+
runtime.GC()
34+
return geoip.Cidr, nil
35+
}
36+
37+
func (g *geodataCache) LoadSite(filename, list string) ([]*v2router.Domain, error) {
38+
geosite, err := g.GeoSiteCache.Unmarshal(filename, list)
39+
if err != nil {
40+
return nil, err
41+
}
42+
runtime.GC()
43+
return geosite.Domain, nil
44+
}
45+
46+
func (g *geodataCache) LoadGeoIP(country string) ([]*v2router.CIDR, error) {
47+
return g.LoadIP("geoip.dat", country)
48+
}
49+
50+
func (g *geodataCache) LoadGeoSite(list string) ([]*v2router.Domain, error) {
51+
return g.LoadSite("geosite.dat", list)
52+
}

tunnel/router/client.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"net"
66
"regexp"
7+
"runtime"
78
"strconv"
89
"strings"
910

@@ -264,6 +265,11 @@ func loadCode(cfg *Config, prefix string) []codeInfo {
264265
}
265266

266267
func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
268+
m1 := runtime.MemStats{}
269+
m2 := runtime.MemStats{}
270+
m3 := runtime.MemStats{}
271+
m4 := runtime.MemStats{}
272+
267273
cfg := config.FromContext(ctx, Name).(*Config)
268274
var cancel context.CancelFunc
269275
ctx, cancel = context.WithCancel(ctx)
@@ -304,10 +310,14 @@ func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
304310
return nil, common.NewError("unknown strategy: " + cfg.Router.DomainStrategy)
305311
}
306312

313+
runtime.ReadMemStats(&m1)
314+
315+
geodataLoader := geodata.GetGeodataLoader()
316+
307317
ipCode := loadCode(cfg, "geoip:")
308318
for _, c := range ipCode {
309319
code := c.code
310-
cidrs, err := geodata.LoadGeoIP(code)
320+
cidrs, err := geodataLoader.LoadGeoIP(code)
311321
if err != nil {
312322
log.Error(err)
313323
} else {
@@ -316,6 +326,8 @@ func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
316326
}
317327
}
318328

329+
runtime.ReadMemStats(&m2)
330+
319331
siteCode := loadCode(cfg, "geosite:")
320332
for _, c := range siteCode {
321333
code := c.code
@@ -334,7 +346,7 @@ func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
334346
continue
335347
}
336348

337-
domainList, err := geodata.LoadGeoSite(code)
349+
domainList, err := geodataLoader.LoadGeoSite(code)
338350
if err != nil {
339351
log.Error(err)
340352
} else {
@@ -360,6 +372,8 @@ func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
360372
}
361373
}
362374

375+
runtime.ReadMemStats(&m3)
376+
363377
domainInfo := loadCode(cfg, "domain:")
364378
for _, info := range domainInfo {
365379
client.domains[info.strategy] = append(client.domains[info.strategy], &v2router.Domain{
@@ -433,5 +447,13 @@ func NewClient(ctx context.Context, underlay tunnel.Client) (*Client, error) {
433447
}
434448

435449
log.Info("router client created")
450+
451+
runtime.ReadMemStats(&m4)
452+
453+
log.Debugf("GeoIP rules -> Alloc: %s; TotalAlloc: %s", common.HumanFriendlyTraffic(m2.Alloc-m1.Alloc), common.HumanFriendlyTraffic(m2.TotalAlloc-m1.TotalAlloc))
454+
log.Debugf("GeoSite rules -> Alloc: %s; TotalAlloc: %s", common.HumanFriendlyTraffic(m3.Alloc-m2.Alloc), common.HumanFriendlyTraffic(m3.TotalAlloc-m2.TotalAlloc))
455+
log.Debugf("Plaintext rules -> Alloc: %s; TotalAlloc: %s", common.HumanFriendlyTraffic(m4.Alloc-m3.Alloc), common.HumanFriendlyTraffic(m4.TotalAlloc-m3.TotalAlloc))
456+
log.Debugf("Total(router) -> Alloc: %s; TotalAlloc: %s", common.HumanFriendlyTraffic(m4.Alloc-m1.Alloc), common.HumanFriendlyTraffic(m4.TotalAlloc-m1.TotalAlloc))
457+
436458
return client, nil
437459
}

0 commit comments

Comments
 (0)