ip6: partially replace math.big, Ipv6Net iterator performance up to x3.2 times better with TCC and up to x2 with -prod

This commit is contained in:
ge
2025-04-23 02:27:17 +03:00
parent 023b399a32
commit cf39b623ae
2 changed files with 19 additions and 10 deletions

23
ip6.v
View File

@ -514,7 +514,7 @@ pub:
host_address ?Ipv6Addr host_address ?Ipv6Addr
prefix_len int prefix_len int
mut: mut:
current big.Integer current [16]u8
} }
// Ipv6Net.new creates new IPv6 network from given Ipv6Addr and prefix. // Ipv6Net.new creates new IPv6 network from given Ipv6Addr and prefix.
@ -548,7 +548,7 @@ pub fn Ipv6Net.new(addr Ipv6Addr, prefix int) !Ipv6Net {
broadcast_address: broadcast broadcast_address: broadcast
host_address: host_addr host_address: host_addr
prefix_len: prefix prefix_len: prefix
current: net_addr.bigint() current: net_addr.u8_array_fixed()
} }
} }
@ -617,7 +617,7 @@ pub fn Ipv6Net.from_string(cidr string) !Ipv6Net {
broadcast_address: broadcast broadcast_address: broadcast
host_address: host_addr host_address: host_addr
prefix_len: prefix_len prefix_len: prefix_len
current: net_addr.bigint() current: net_addr.u8_array_fixed()
} }
} }
@ -639,14 +639,15 @@ pub fn Ipv6Net.from_bigint(addr big.Integer, prefix int) !Ipv6Net {
} }
host_mask := net_mask.bitwise_xor(max_u128) host_mask := net_mask.bitwise_xor(max_u128)
broadcast := net_addr.bitwise_or(host_mask) broadcast := net_addr.bitwise_or(host_mask)
net_addr6 := Ipv6Addr.from_bigint(net_addr)!
return Ipv6Net{ return Ipv6Net{
network_address: Ipv6Addr.from_bigint(net_addr)! network_address: net_addr6
network_mask: Ipv6Addr.from_bigint(net_mask)! network_mask: Ipv6Addr.from_bigint(net_mask)!
host_mask: Ipv6Addr.from_bigint(host_mask)! host_mask: Ipv6Addr.from_bigint(host_mask)!
broadcast_address: Ipv6Addr.from_bigint(broadcast)! broadcast_address: Ipv6Addr.from_bigint(broadcast)!
host_address: host_addr host_address: host_addr
prefix_len: prefix prefix_len: prefix
current: net_addr current: net_addr6.u8_array_fixed()
} }
} }
@ -689,13 +690,15 @@ pub fn (n Ipv6Net) capacity() big.Integer {
// } // }
// ``` // ```
pub fn (mut n Ipv6Net) next() ?Ipv6Addr { pub fn (mut n Ipv6Net) next() ?Ipv6Addr {
if n.current >= n.broadcast_address.bigint() + big.one_int { // Possible optimization: do not calculate `limit` on each fn call (use LRU cache?)
limit := add_128(n.broadcast_address.addr, one_128)
if compare_128(n.current, limit) in [0, 1] {
return none return none
} }
defer { defer {
n.current = n.current + big.one_int n.current = add_128(n.current, one_128)
} }
return Ipv6Addr.from_bigint(n.current)! return Ipv6Addr.from_octets(n.current)!
} }
// first returns the first usable host address in network. // first returns the first usable host address in network.
@ -703,7 +706,7 @@ pub fn (n Ipv6Net) first() Ipv6Addr {
if n.prefix_len in [127, 128] { if n.prefix_len in [127, 128] {
return n.network_address return n.network_address
} }
return Ipv6Addr.from_bigint(n.network_address.bigint() + big.one_int) or { panic(err) } return Ipv6Addr.from_octets(add_128(n.network_address.addr, one_128)) or { panic(err) }
} }
// last returns the last usable host address in network. // last returns the last usable host address in network.
@ -711,7 +714,7 @@ pub fn (n Ipv6Net) last() Ipv6Addr {
if n.prefix_len in [127, 128] { if n.prefix_len in [127, 128] {
return n.broadcast_address return n.broadcast_address
} }
return Ipv6Addr.from_bigint(n.broadcast_address.bigint() - big.one_int) or { panic(err) } return Ipv6Addr.from_octets(sub_128(n.broadcast_address.addr, one_128)) or { panic(err) }
} }
// nth returns the Nth address in network. Supports negative indexes. // nth returns the Nth address in network. Supports negative indexes.

View File

@ -185,6 +185,12 @@ fn test_ipv6_net_format() {
assert net.format(.verbose | .with_host_mask) == 'fe80:ffff:0000:0000:0000:0000:0000:0000/0000:0000:0000:0000:ffff:ffff:ffff:ffff' assert net.format(.verbose | .with_host_mask) == 'fe80:ffff:0000:0000:0000:0000:0000:0000/0000:0000:0000:0000:ffff:ffff:ffff:ffff'
} }
fn test_ipv6_net_first_last() {
net := netaddr.Ipv6Net.from_string('fe80:ffff::/64')!
assert net.first().str() == 'fe80:ffff::1'
assert net.last().str() == 'fe80:ffff::ffff:ffff:ffff:fffe'
}
fn test_ipv6_net_next() { fn test_ipv6_net_next() {
net := netaddr.Ipv6Net.from_string('fe80::/64')! net := netaddr.Ipv6Net.from_string('fe80::/64')!
mut addrs := []netaddr.Ipv6Addr{} mut addrs := []netaddr.Ipv6Addr{}