tomMoulard / fail2ban

Traefik plugin on fail2ban middleware
MIT License
191 stars 10 forks source link

Replace net.IPNet to netip.Prefix for performances purposes #76

Closed tomMoulard closed 9 months ago

tomMoulard commented 9 months ago

This PR replaces the usage of net.IPNet to netip.Prefix for performances purposes.

Following the netip doc:

Compared to the net.IP type, Addr type takes less memory, is immutable, and is comparable (supports == and being a map key).

here are a few benchmarks (results may vary) ``` > go test -bench=. github.com/tomMoulard/fail2ban/ipchecking -test.run=Benchmark goos: linux goarch: amd64 pkg: github.com/tomMoulard/fail2ban/ipchecking cpu: Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz BenchmarkIPChecking_new-12 1000000 1042 ns/op BenchmarkIPChecking_old-12 512394 2307 ns/op PASS ok github.com/tomMoulard/fail2ban/ipchecking 2.618s ``` ```go func BenchmarkIPChecking_new(b *testing.B) { tests := []struct { ip1 string ip2 string expect bool }{ {ip1: "127.0.0.1", ip2: "127.0.0.1", expect: true}, {ip1: "127.0.0.1", ip2: "127.0.0.2", expect: false}, {ip1: "127.0.0.1/24", ip2: "127.0.0.2", expect: true}, {ip1: "127.0.0.1/32", ip2: "127.0.0.2", expect: false}, {ip1: "10.0.0.1/32", ip2: "127.0.0.2", expect: false}, {ip1: "10.0.0.1/0", ip2: "127.0.0.2", expect: true}, {ip1: "0.0.0.0", ip2: "127.0.0.2", expect: false}, } for n := 0; n < b.N; n++ { for _, tt := range tests { ipv4, _ := ipchecking.ParseNetIP(tt.ip1) if ipv4.Contains(tt.ip2) != tt.expect { b.Logf("ip1: %s, ip2: %s", tt.ip1, tt.ip2) b.Errorf("wanted '%v' got '%v'", tt.expect, ipv4.Contains(tt.ip2)) } } } } func BenchmarkIPChecking_old(b *testing.B) { tests := []struct { ip1 string ip2 string expect bool }{ {ip1: "127.0.0.1", ip2: "127.0.0.1", expect: true}, {ip1: "127.0.0.1", ip2: "127.0.0.2", expect: false}, {ip1: "127.0.0.1/24", ip2: "127.0.0.2", expect: true}, {ip1: "127.0.0.1/32", ip2: "127.0.0.2", expect: false}, {ip1: "10.0.0.1/32", ip2: "127.0.0.2", expect: false}, {ip1: "10.0.0.1/0", ip2: "127.0.0.2", expect: true}, {ip1: "0.0.0.0", ip2: "127.0.0.2", expect: false}, } for n := 0; n < b.N; n++ { for _, tt := range tests { ipv4, _ := ipchecking.BuildIP(tt.ip1) if ipv4.CheckIPInSubnet(tt.ip2) != tt.expect { b.Logf("ip1: %s, ip2: %s", tt.ip1, tt.ip2) b.Errorf("wanted '%v' got '%v'", tt.expect, ipv4.CheckIPInSubnet(tt.ip2)) } } } } ```

There is one breaking change in the ipchecking API (except for the functions renaming to be closer to netip function calls) that is StrToIP now breaks when some IPs are faulty instead of ignoring them.