Remove pre-defined networks from package init

This moves the initialization of the pre-defined networks to where it's
used instead of in package init.
This reason for this change is having this be populated in `init()`
causes it to always consume cpu, and memory (4.3MB of memory), to
populate even if the package is unused (like for instnace, in a re-exec).

Here is a memory profile of docker/docker just after starting the daemon of the
top 10 largest memory consumers:

Before:
```
      flat  flat%   sum%        cum   cum%
         0     0%     0%    11.89MB 95.96%  runtime.goexit
         0     0%     0%     6.79MB 54.82%  runtime.main
         0     0%     0%     5.79MB 46.74%  main.init
         0     0%     0%     4.79MB 38.67%  github.com/docker/docker/api/server/router/network.init
         0     0%     0%     4.79MB 38.67%  github.com/docker/libnetwork.init
         0     0%     0%     4.29MB 34.63%  github.com/docker/libnetwork/ipam.init
         0     0%     0%     4.29MB 34.63%  github.com/docker/libnetwork/ipams/builtin.init
         0     0%     0%     4.29MB 34.63%  github.com/docker/libnetwork/ipamutils.init
         0     0%     0%     4.29MB 34.63%  github.com/docker/libnetwork/ipamutils.init.1
    4.29MB 34.63% 34.63%     4.29MB 34.63%  github.com/docker/libnetwork/ipamutils.initGranularPredefinedNetworks
```

After:
```
      flat  flat%   sum%        cum   cum%
         0     0%     0%  4439.37kB 89.66%  runtime.goexit
         0     0%     0%  4439.37kB 89.66%  runtime.main
         0     0%     0%  3882.11kB 78.40%  github.com/docker/docker/cli.(*Cli).Run
         0     0%     0%  3882.11kB 78.40%  main.main
 3882.11kB 78.40% 78.40%  3882.11kB 78.40%  reflect.callMethod
         0     0% 78.40%  3882.11kB 78.40%  reflect.methodValueCall
         0     0% 78.40%   557.26kB 11.25%  github.com/docker/docker/api/server.init
  557.26kB 11.25% 89.66%   557.26kB 11.25%  html.init
         0     0% 89.66%   557.26kB 11.25%  html/template.init
         0     0% 89.66%   557.26kB 11.25%  main.init
```

Now, of course the docker daemon will still need to consume this memory, but
at least now re-execs and such won't have to re-init these variables.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2016-04-04 09:50:26 -04:00
parent d0cfd9b3dd
commit 22801e071f
6 changed files with 27 additions and 4 deletions

View file

@ -15,6 +15,10 @@ import (
"github.com/docker/libnetwork/types"
)
func init() {
ipamutils.InitNetworks()
}
func getIPv4Data(t *testing.T) []driverapi.IPAMData {
ipd := driverapi.IPAMData{AddressSpace: "full"}
nw, _, err := ipamutils.ElectInterfaceAddresses("")

View file

@ -46,6 +46,7 @@ func randomLocalStore() (datastore.DataStore, error) {
}
func getAllocator() (*Allocator, error) {
ipamutils.InitNetworks()
ds, err := randomLocalStore()
if err != nil {
return nil, err

View file

@ -8,6 +8,7 @@ import (
"github.com/docker/libnetwork/datastore"
"github.com/docker/libnetwork/ipam"
"github.com/docker/libnetwork/ipamapi"
"github.com/docker/libnetwork/ipamutils"
)
// Init registers the built-in ipam service with libnetwork
@ -28,6 +29,9 @@ func Init(ic ipamapi.Callback, l, g interface{}) error {
return fmt.Errorf("incorrect global datastore passed to built-in ipam init")
}
}
ipamutils.InitNetworks()
a, err := ipam.NewAllocator(localDs, globalDs)
if err != nil {
return err

View file

@ -1,7 +1,10 @@
// Package ipamutils provides utililty functions for ipam management
package ipamutils
import "net"
import (
"net"
"sync"
)
var (
// PredefinedBroadNetworks contains a list of 31 IPv4 private networks with host size 16 and 12
@ -10,11 +13,16 @@ var (
// PredefinedGranularNetworks contains a list of 64K IPv4 private networks with host size 8
// (10.x.x.x/24) which do not overlap with the networks in `PredefinedBroadNetworks`
PredefinedGranularNetworks []*net.IPNet
initNetworksOnce sync.Once
)
func init() {
PredefinedBroadNetworks = initBroadPredefinedNetworks()
PredefinedGranularNetworks = initGranularPredefinedNetworks()
// InitNetworks initializes the pre-defined networks used by the built-in IP allocator
func InitNetworks() {
initNetworksOnce.Do(func() {
PredefinedBroadNetworks = initBroadPredefinedNetworks()
PredefinedGranularNetworks = initGranularPredefinedNetworks()
})
}
func initBroadPredefinedNetworks() []*net.IPNet {

View file

@ -22,6 +22,8 @@ func ElectInterfaceAddresses(name string) (*net.IPNet, []*net.IPNet, error) {
err error
)
InitNetworks()
defer osl.InitOSContext()()
link, _ := netlink.LinkByName(name)

View file

@ -9,6 +9,10 @@ import (
"github.com/vishvananda/netlink"
)
func init() {
InitNetworks()
}
func TestGranularPredefined(t *testing.T) {
for _, nw := range PredefinedGranularNetworks {
if ones, bits := nw.Mask.Size(); bits != 32 || ones != 24 {