Преглед изворни кода

Use ordered array instead of heap for sb.endpoints

Signed-off-by: Christoph Ziebuhr <chris@codefrickler.de>
Christoph Ziebuhr пре 7 година
родитељ
комит
40923e7353
4 измењених фајлова са 32 додато и 43 уклоњено
  1. 1 4
      libnetwork/controller.go
  2. 1 4
      libnetwork/endpoint.go
  3. 28 31
      libnetwork/sandbox.go
  4. 2 4
      libnetwork/sandbox_store.go

+ 1 - 4
libnetwork/controller.go

@@ -44,7 +44,6 @@ create network namespaces and allocate interfaces for containers to use.
 package libnetwork
 
 import (
-	"container/heap"
 	"fmt"
 	"net"
 	"path/filepath"
@@ -1085,7 +1084,7 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S
 		sb = &sandbox{
 			id:                 sandboxID,
 			containerID:        containerID,
-			endpoints:          epHeap{},
+			endpoints:          []*endpoint{},
 			epPriority:         map[string]int{},
 			populatedEndpoints: map[string]struct{}{},
 			config:             containerConfig{},
@@ -1094,8 +1093,6 @@ func (c *controller) NewSandbox(containerID string, options ...SandboxOption) (S
 		}
 	}
 
-	heap.Init(&sb.endpoints)
-
 	sb.processOptions(options...)
 
 	c.Lock()

+ 1 - 4
libnetwork/endpoint.go

@@ -1,7 +1,6 @@
 package libnetwork
 
 import (
-	"container/heap"
 	"encoding/json"
 	"fmt"
 	"net"
@@ -514,9 +513,7 @@ func (ep *endpoint) sbJoin(sb *sandbox, options ...EndpointOption) (err error) {
 	// Current endpoint providing external connectivity for the sandbox
 	extEp := sb.getGatewayEndpoint()
 
-	sb.Lock()
-	heap.Push(&sb.endpoints, ep)
-	sb.Unlock()
+	sb.addEndpoint(ep)
 	defer func() {
 		if err != nil {
 			sb.removeEndpoint(ep)

+ 28 - 31
libnetwork/sandbox.go

@@ -1,10 +1,10 @@
 package libnetwork
 
 import (
-	"container/heap"
 	"encoding/json"
 	"fmt"
 	"net"
+	"sort"
 	"strings"
 	"sync"
 	"time"
@@ -63,8 +63,6 @@ func (sb *sandbox) processOptions(options ...SandboxOption) {
 	}
 }
 
-type epHeap []*endpoint
-
 type sandbox struct {
 	id                 string
 	containerID        string
@@ -75,7 +73,7 @@ type sandbox struct {
 	resolver           Resolver
 	resolverOnce       sync.Once
 	refCnt             int
-	endpoints          epHeap
+	endpoints          []*endpoint
 	epPriority         map[string]int
 	populatedEndpoints map[string]struct{}
 	joinLeaveDone      chan struct{}
@@ -360,13 +358,31 @@ func (sb *sandbox) getConnectedEndpoints() []*endpoint {
 	return eps
 }
 
+func (sb *sandbox) addEndpoint(ep *endpoint) {
+	sb.Lock()
+	defer sb.Unlock()
+
+	l := len(sb.endpoints)
+	i := sort.Search(l, func(j int) bool {
+		return ep.Less(sb.endpoints[j])
+	})
+
+	sb.endpoints = append(sb.endpoints, nil)
+	copy(sb.endpoints[i+1:], sb.endpoints[i:])
+	sb.endpoints[i] = ep
+}
+
 func (sb *sandbox) removeEndpoint(ep *endpoint) {
 	sb.Lock()
 	defer sb.Unlock()
 
+	sb.removeEndpointRaw(ep)
+}
+
+func (sb *sandbox) removeEndpointRaw(ep *endpoint) {
 	for i, e := range sb.endpoints {
 		if e == ep {
-			heap.Remove(&sb.endpoints, i)
+			sb.endpoints = append(sb.endpoints[:i], sb.endpoints[i+1:]...)
 			return
 		}
 	}
@@ -940,7 +956,7 @@ func (sb *sandbox) clearNetworkResources(origEp *endpoint) error {
 		return nil
 	}
 
-	heap.Remove(&sb.endpoints, index)
+	sb.removeEndpointRaw(ep)
 	for _, e := range sb.endpoints {
 		if len(e.Gateway()) > 0 {
 			gwepAfter = e
@@ -1165,19 +1181,14 @@ func OptionIngress() SandboxOption {
 	}
 }
 
-func (eh epHeap) Len() int { return len(eh) }
-
-func (eh epHeap) Less(i, j int) bool {
+func (epi *endpoint) Less(epj *endpoint) bool {
 	var (
 		cip, cjp int
 		ok       bool
 	)
 
-	ci, _ := eh[i].getSandbox()
-	cj, _ := eh[j].getSandbox()
-
-	epi := eh[i]
-	epj := eh[j]
+	ci, _ := epi.getSandbox()
+	cj, _ := epj.getSandbox()
 
 	if epi.endpointInGWNetwork() {
 		return false
@@ -1207,40 +1218,26 @@ func (eh epHeap) Less(i, j int) bool {
 	}
 
 	if ci != nil {
-		cip, ok = ci.epPriority[eh[i].ID()]
+		cip, ok = ci.epPriority[epi.ID()]
 		if !ok {
 			cip = 0
 		}
 	}
 
 	if cj != nil {
-		cjp, ok = cj.epPriority[eh[j].ID()]
+		cjp, ok = cj.epPriority[epj.ID()]
 		if !ok {
 			cjp = 0
 		}
 	}
 
 	if cip == cjp {
-		return eh[i].network.Name() < eh[j].network.Name()
+		return epi.network.Name() < epj.network.Name()
 	}
 
 	return cip > cjp
 }
 
-func (eh epHeap) Swap(i, j int) { eh[i], eh[j] = eh[j], eh[i] }
-
-func (eh *epHeap) Push(x interface{}) {
-	*eh = append(*eh, x.(*endpoint))
-}
-
-func (eh *epHeap) Pop() interface{} {
-	old := *eh
-	n := len(old)
-	x := old[n-1]
-	*eh = old[0 : n-1]
-	return x
-}
-
 func (sb *sandbox) NdotsSet() bool {
 	return sb.ndotsSet
 }

+ 2 - 4
libnetwork/sandbox_store.go

@@ -1,7 +1,6 @@
 package libnetwork
 
 import (
-	"container/heap"
 	"encoding/json"
 	"sync"
 
@@ -215,7 +214,7 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
 			id:                 sbs.ID,
 			controller:         sbs.c,
 			containerID:        sbs.Cid,
-			endpoints:          epHeap{},
+			endpoints:          []*endpoint{},
 			populatedEndpoints: map[string]struct{}{},
 			dbIndex:            sbs.dbIndex,
 			isStub:             true,
@@ -242,7 +241,6 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
 			sb.processOptions(opts...)
 			sb.restorePath()
 			create = !sb.config.useDefaultSandBox
-			heap.Init(&sb.endpoints)
 		}
 		sb.osSbox, err = osl.NewSandbox(sb.Key(), create, isRestore)
 		if err != nil {
@@ -272,7 +270,7 @@ func (c *controller) sandboxCleanup(activeSandboxes map[string]interface{}) {
 				logrus.Errorf("failed to restore endpoint %s in %s for container %s due to %v", eps.Eid, eps.Nid, sb.ContainerID(), err)
 				continue
 			}
-			heap.Push(&sb.endpoints, ep)
+			sb.addEndpoint(ep)
 		}
 
 		if _, ok := activeSandboxes[sb.ID()]; !ok {