The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/1637

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
This improves performance about as much as we can realistically do it,
less than 100ms per container when retrieving all network information,
cgroup and disk usage.

To get any faster, simply not requesting the information by using -c is
the way to go.

Closes #671

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
From d5ae86f05f3e2f2453905c20289c56860bc0f595 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Tue, 23 Feb 2016 18:15:56 -0500
Subject: [PATCH] list: Query containers by batch of 10
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This improves performance about as much as we can realistically do it,
less than 100ms per container when retrieving all network information,
cgroup and disk usage.

To get any faster, simply not requesting the information by using -c is
the way to go.

Closes #671

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxc/list.go | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 96 insertions(+), 18 deletions(-)

diff --git a/lxc/list.go b/lxc/list.go
index cbac604..e5b5aff 100644
--- a/lxc/list.go
+++ b/lxc/list.go
@@ -6,6 +6,7 @@ import (
        "regexp"
        "sort"
        "strings"
+       "sync"
 
        "github.com/olekukonko/tablewriter"
 
@@ -152,39 +153,116 @@ func (c *listCmd) shouldShow(filters []string, state 
*shared.ContainerInfo) bool
 }
 
 func (c *listCmd) listContainers(d *lxd.Client, cinfos []shared.ContainerInfo, 
filters []string, columns []Column) error {
-       var err error
-
        headers := []string{}
        for _, column := range columns {
                headers = append(headers, column.Name)
        }
 
-       data := [][]string{}
+       cStates := map[string]*shared.ContainerState{}
+       cStatesLock := sync.Mutex{}
+       cStatesQueue := make(chan string, 1)
+       cStatesWg := sync.WaitGroup{}
+
+       cSnapshots := map[string][]shared.SnapshotInfo{}
+       cSnapshotsLock := sync.Mutex{}
+       cSnapshotsQueue := make(chan string, 1)
+       cSnapshotsWg := sync.WaitGroup{}
+
+       threads := 10
+       if len(cinfos) < threads {
+               threads = len(cinfos)
+       }
+
+       for i := 0; i < threads; i++ {
+               cStatesWg.Add(1)
+               go func() {
+                       for {
+                               cName, more := <-cStatesQueue
+                               if !more {
+                                       break
+                               }
+
+                               state, err := d.ContainerState(cName)
+                               if err != nil {
+                                       continue
+                               }
+
+                               cStatesLock.Lock()
+                               cStates[cName] = state
+                               cStatesLock.Unlock()
+                       }
+                       cStatesWg.Done()
+               }()
+
+               cSnapshotsWg.Add(1)
+               go func() {
+                       for {
+                               cName, more := <-cSnapshotsQueue
+                               if !more {
+                                       break
+                               }
+
+                               snaps, err := d.ListSnapshots(cName)
+                               if err != nil {
+                                       continue
+                               }
+
+                               cSnapshotsLock.Lock()
+                               cSnapshots[cName] = snaps
+                               cSnapshotsLock.Unlock()
+                       }
+                       cSnapshotsWg.Done()
+               }()
+       }
+
        for _, cInfo := range cinfos {
                if !c.shouldShow(filters, &cInfo) {
                        continue
                }
 
-               var cState *shared.ContainerState
-               var cSnapshots []shared.SnapshotInfo
-
-               col := []string{}
                for _, column := range columns {
-                       if column.NeedsState && cState == nil {
-                               cState, err = d.ContainerState(cInfo.Name)
-                               if err != nil {
-                                       return err
+                       if column.NeedsState && cInfo.StatusCode != 
shared.Stopped {
+                               _, ok := cStates[cInfo.Name]
+                               if ok {
+                                       continue
                                }
+
+                               cStatesLock.Lock()
+                               cStates[cInfo.Name] = nil
+                               cStatesLock.Unlock()
+
+                               cStatesQueue <- cInfo.Name
                        }
 
-                       if column.NeedsSnapshots && cSnapshots == nil {
-                               cSnapshots, err = d.ListSnapshots(cInfo.Name)
-                               if err != nil {
-                                       return err
+                       if column.NeedsSnapshots {
+                               _, ok := cSnapshots[cInfo.Name]
+                               if ok {
+                                       continue
                                }
+
+                               cSnapshotsLock.Lock()
+                               cSnapshots[cInfo.Name] = nil
+                               cSnapshotsLock.Unlock()
+
+                               cSnapshotsQueue <- cInfo.Name
                        }
+               }
+       }
 
-                       col = append(col, column.Data(cInfo, cState, 
cSnapshots))
+       close(cStatesQueue)
+       close(cSnapshotsQueue)
+       cStatesWg.Wait()
+       cSnapshotsWg.Wait()
+
+       data := [][]string{}
+       for _, cInfo := range cinfos {
+               if !c.shouldShow(filters, &cInfo) {
+                       continue
+               }
+
+               col := []string{}
+               for _, column := range columns {
+                       col = append(col, column.Data(cInfo, 
cStates[cInfo.Name], cSnapshots[cInfo.Name]))
                }
                data = append(data, col)
        }
@@ -273,7 +351,7 @@ func (c *listCmd) statusColumnData(cInfo 
shared.ContainerInfo, cState *shared.Co
 }
 
 func (c *listCmd) IP4ColumnData(cInfo shared.ContainerInfo, cState 
*shared.ContainerState, cSnaps []shared.SnapshotInfo) string {
-       if cInfo.StatusCode == shared.Running || cInfo.StatusCode == 
shared.Frozen {
+       if cInfo.StatusCode != shared.Stopped {
                ipv4s := []string{}
                for netName, net := range cState.Network {
                        if net.Type == "loopback" {
@@ -293,7 +371,7 @@ func (c *listCmd) IP4ColumnData(cInfo shared.ContainerInfo, 
cState *shared.Conta
 }
 
 func (c *listCmd) IP6ColumnData(cInfo shared.ContainerInfo, cState 
*shared.ContainerState, cSnaps []shared.SnapshotInfo) string {
-       if cInfo.StatusCode == shared.Running || cInfo.StatusCode == 
shared.Frozen {
+       if cInfo.StatusCode != shared.Stopped {
                ipv6s := []string{}
                for netName, net := range cState.Network {
                        if net.Type == "loopback" {
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to