1
0
mirror of https://github.com/golang/go synced 2024-11-26 18:06:55 -07:00

syscall: add a sync.Pool for a NetlinkRIB scratch buffer

The syscall.NetlinkRIB signature means it necessarily allocates but
this changes makes it allocate a bit less. For example, in the net
package:

    name                           old time/op    new time/op    delta
    Interfaces-8                     59.1µs ± 3%    57.3µs ± 2%   -3.02%  (p=0.000 n=10+10)
    InterfaceByIndex-8               53.1µs ± 5%    50.6µs ± 2%   -4.81%  (p=0.000 n=10+10)
    InterfaceByName-8                59.3µs ± 2%    57.4µs ± 1%   -3.29%  (p=0.000 n=10+10)
    InterfaceAddrs-8                  105µs ± 1%     101µs ± 1%   -4.22%  (p=0.000 n=10+9)
    InterfacesAndAddrs-8             38.2µs ± 3%    36.3µs ± 2%   -4.98%  (p=0.000 n=10+10)
    InterfacesAndMulticastAddrs-8     152µs ± 2%     154µs ± 6%     ~     (p=0.105 n=10+10)

    name                           old alloc/op   new alloc/op   delta
    Interfaces-8                     22.8kB ± 0%    18.7kB ± 0%  -17.90%  (p=0.000 n=10+9)
    InterfaceByIndex-8               16.2kB ± 0%    12.1kB ± 0%  -25.22%  (p=0.000 n=10+10)
    InterfaceByName-8                22.8kB ± 0%    18.8kB ± 0%  -17.85%  (p=0.000 n=10+10)
    InterfaceAddrs-8                 36.6kB ± 0%    28.5kB ± 0%  -22.28%  (p=0.000 n=10+10)
    InterfacesAndAddrs-8             9.60kB ± 0%    5.51kB ± 0%  -42.59%  (p=0.000 n=10+7)
    InterfacesAndMulticastAddrs-8     141kB ± 0%     141kB ± 0%     ~     (all equal)

    name                           old allocs/op  new allocs/op  delta
    Interfaces-8                       53.0 ± 0%      52.0 ± 0%   -1.89%  (p=0.000 n=10+10)
    InterfaceByIndex-8                 28.0 ± 0%      27.0 ± 0%   -3.57%  (p=0.000 n=10+10)
    InterfaceByName-8                  54.0 ± 0%      53.0 ± 0%   -1.85%  (p=0.000 n=10+10)
    InterfaceAddrs-8                    155 ± 0%       153 ± 0%   -1.29%  (p=0.000 n=10+10)
    InterfacesAndAddrs-8               38.0 ± 0%      37.0 ± 0%   -2.63%  (p=0.000 n=10+10)
    InterfacesAndMulticastAddrs-8      77.0 ± 0%      77.0 ± 0%     ~     (all equal)

Signed-off-by: Brad Fitzpatrick <bradfitz@golang.org>
Change-Id: Ic3278b2c000af78d7ed816645463c3b7ff0c90ca
Reviewed-on: https://go-review.googlesource.com/c/go/+/485455
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
This commit is contained in:
Brad Fitzpatrick 2023-04-17 13:32:03 -07:00
parent fd8acb5d4a
commit e875cbd9aa
2 changed files with 19 additions and 3 deletions

View File

@ -300,6 +300,7 @@ func checkMulticastStats(ifStats *ifStats, uniStats, multiStats *routeStats) err
} }
func BenchmarkInterfaces(b *testing.B) { func BenchmarkInterfaces(b *testing.B) {
b.ReportAllocs()
testHookUninstaller.Do(uninstallTestHooks) testHookUninstaller.Do(uninstallTestHooks)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@ -310,6 +311,7 @@ func BenchmarkInterfaces(b *testing.B) {
} }
func BenchmarkInterfaceByIndex(b *testing.B) { func BenchmarkInterfaceByIndex(b *testing.B) {
b.ReportAllocs()
testHookUninstaller.Do(uninstallTestHooks) testHookUninstaller.Do(uninstallTestHooks)
ifi := loopbackInterface() ifi := loopbackInterface()
@ -324,6 +326,7 @@ func BenchmarkInterfaceByIndex(b *testing.B) {
} }
func BenchmarkInterfaceByName(b *testing.B) { func BenchmarkInterfaceByName(b *testing.B) {
b.ReportAllocs()
testHookUninstaller.Do(uninstallTestHooks) testHookUninstaller.Do(uninstallTestHooks)
ifi := loopbackInterface() ifi := loopbackInterface()
@ -338,6 +341,7 @@ func BenchmarkInterfaceByName(b *testing.B) {
} }
func BenchmarkInterfaceAddrs(b *testing.B) { func BenchmarkInterfaceAddrs(b *testing.B) {
b.ReportAllocs()
testHookUninstaller.Do(uninstallTestHooks) testHookUninstaller.Do(uninstallTestHooks)
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
@ -348,6 +352,7 @@ func BenchmarkInterfaceAddrs(b *testing.B) {
} }
func BenchmarkInterfacesAndAddrs(b *testing.B) { func BenchmarkInterfacesAndAddrs(b *testing.B) {
b.ReportAllocs()
testHookUninstaller.Do(uninstallTestHooks) testHookUninstaller.Do(uninstallTestHooks)
ifi := loopbackInterface() ifi := loopbackInterface()
@ -362,6 +367,7 @@ func BenchmarkInterfacesAndAddrs(b *testing.B) {
} }
func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) { func BenchmarkInterfacesAndMulticastAddrs(b *testing.B) {
b.ReportAllocs()
testHookUninstaller.Do(uninstallTestHooks) testHookUninstaller.Do(uninstallTestHooks)
ifi := loopbackInterface() ifi := loopbackInterface()

View File

@ -6,7 +6,10 @@
package syscall package syscall
import "unsafe" import (
"sync"
"unsafe"
)
// Round the length of a netlink message up to align it properly. // Round the length of a netlink message up to align it properly.
func nlmAlignOf(msglen int) int { func nlmAlignOf(msglen int) int {
@ -47,6 +50,11 @@ func newNetlinkRouteRequest(proto, seq, family int) []byte {
return rr.toWireFormat() return rr.toWireFormat()
} }
var pageBufPool = &sync.Pool{New: func() any {
b := make([]byte, Getpagesize())
return &b
}}
// NetlinkRIB returns routing information base, as known as RIB, which // NetlinkRIB returns routing information base, as known as RIB, which
// consists of network facility information, states and parameters. // consists of network facility information, states and parameters.
func NetlinkRIB(proto, family int) ([]byte, error) { func NetlinkRIB(proto, family int) ([]byte, error) {
@ -72,10 +80,12 @@ func NetlinkRIB(proto, family int) ([]byte, error) {
return nil, EINVAL return nil, EINVAL
} }
var tab []byte var tab []byte
rbNew := make([]byte, Getpagesize())
rbNew := pageBufPool.Get().(*[]byte)
defer pageBufPool.Put(rbNew)
done: done:
for { for {
rb := rbNew rb := *rbNew
nr, _, err := Recvfrom(s, rb, 0) nr, _, err := Recvfrom(s, rb, 0)
if err != nil { if err != nil {
return nil, err return nil, err