From 74f0d78beb2dc68ea7ca19df996bf95a6f625f81 Mon Sep 17 00:00:00 2001 From: Paul Nasrat Date: Fri, 11 Apr 2014 16:39:58 -0400 Subject: [PATCH] Enable construction of TruncIndex from id array. Fixes #5166 Current graph.restore is essentially O(n^2 log n) due to how suffixarray creation works. Rather than create/append/create new this supports creation from a seed array of ids. Functional testing shows this eliminates the hang on Creating image graph reported on list. Docker-DCO-1.1-Signed-off-by: Paul Nasrat (github: pnasrat) Upstream-commit: 4f169c2db512d2ea9ed5729df375896a1ee90347 Component: engine --- components/engine/graph/graph.go | 6 ++++-- components/engine/runtime/runtime.go | 2 +- components/engine/utils/utils.go | 11 ++++++++--- components/engine/utils/utils_test.go | 3 ++- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/components/engine/graph/graph.go b/components/engine/graph/graph.go index 9ebfc3daa6..eeac8ecd27 100644 --- a/components/engine/graph/graph.go +++ b/components/engine/graph/graph.go @@ -40,7 +40,7 @@ func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) { graph := &Graph{ Root: abspath, - idIndex: utils.NewTruncIndex(), + idIndex: utils.NewTruncIndex([]string{}), driver: driver, } if err := graph.restore(); err != nil { @@ -54,12 +54,14 @@ func (graph *Graph) restore() error { if err != nil { return err } + var ids = []string{} for _, v := range dir { id := v.Name() if graph.driver.Exists(id) { - graph.idIndex.Add(id) + ids = append(ids, id) } } + graph.idIndex = utils.NewTruncIndex(ids) utils.Debugf("Restored %d elements", len(dir)) return nil } diff --git a/components/engine/runtime/runtime.go b/components/engine/runtime/runtime.go index 98903cfa08..d612b48de0 100644 --- a/components/engine/runtime/runtime.go +++ b/components/engine/runtime/runtime.go @@ -779,7 +779,7 @@ func NewRuntimeFromDirectory(config *daemonconfig.Config, eng *engine.Engine) (* containers: list.New(), graph: g, repositories: repositories, - idIndex: utils.NewTruncIndex(), + idIndex: utils.NewTruncIndex([]string{}), sysInfo: sysInfo, volumes: volumes, config: config, diff --git a/components/engine/utils/utils.go b/components/engine/utils/utils.go index 1fe2e87b4f..8b6db8c464 100644 --- a/components/engine/utils/utils.go +++ b/components/engine/utils/utils.go @@ -426,12 +426,17 @@ type TruncIndex struct { bytes []byte } -func NewTruncIndex() *TruncIndex { - return &TruncIndex{ - index: suffixarray.New([]byte{' '}), +func NewTruncIndex(ids []string) (idx *TruncIndex) { + idx = &TruncIndex{ ids: make(map[string]bool), bytes: []byte{' '}, } + for _, id := range ids { + idx.ids[id] = true + idx.bytes = append(idx.bytes, []byte(id+" ")...) + } + idx.index = suffixarray.New(idx.bytes) + return } func (idx *TruncIndex) Add(id string) error { diff --git a/components/engine/utils/utils_test.go b/components/engine/utils/utils_test.go index 177d3667e1..4781871267 100644 --- a/components/engine/utils/utils_test.go +++ b/components/engine/utils/utils_test.go @@ -138,7 +138,8 @@ func TestRaceWriteBroadcaster(t *testing.T) { // Test the behavior of TruncIndex, an index for querying IDs from a non-conflicting prefix. func TestTruncIndex(t *testing.T) { - index := NewTruncIndex() + ids := []string{} + index := NewTruncIndex(ids) // Get on an empty index if _, err := index.Get("foobar"); err == nil { t.Fatal("Get on an empty index should return an error")