mirror of https://github.com/docker/docs.git
Merge pull request #23084 from estesp/ps-fastpath
Optimize `docker ps` when name/id filters in use
This commit is contained in:
commit
466eb1bab7
|
@ -90,6 +90,56 @@ func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*types.C
|
||||||
return daemon.reduceContainers(config, daemon.transformContainer)
|
return daemon.reduceContainers(config, daemon.transformContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) filterByNameIDMatches(ctx *listContext) []*container.Container {
|
||||||
|
idSearch := false
|
||||||
|
names := ctx.filters.Get("name")
|
||||||
|
ids := ctx.filters.Get("id")
|
||||||
|
if len(names)+len(ids) == 0 {
|
||||||
|
// if name or ID filters are not in use, return to
|
||||||
|
// standard behavior of walking the entire container
|
||||||
|
// list from the daemon's in-memory store
|
||||||
|
return daemon.List()
|
||||||
|
}
|
||||||
|
|
||||||
|
// idSearch will determine if we limit name matching to the IDs
|
||||||
|
// matched from any IDs which were specified as filters
|
||||||
|
if len(ids) > 0 {
|
||||||
|
idSearch = true
|
||||||
|
}
|
||||||
|
|
||||||
|
matches := make(map[string]bool)
|
||||||
|
// find ID matches; errors represent "not found" and can be ignored
|
||||||
|
for _, id := range ids {
|
||||||
|
if fullID, err := daemon.idIndex.Get(id); err == nil {
|
||||||
|
matches[fullID] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for name matches; if ID filtering was used, then limit the
|
||||||
|
// search space to the matches map only; errors represent "not found"
|
||||||
|
// and can be ignored
|
||||||
|
if len(names) > 0 {
|
||||||
|
for id, idNames := range ctx.names {
|
||||||
|
// if ID filters were used and no matches on that ID were
|
||||||
|
// found, continue to next ID in the list
|
||||||
|
if idSearch && !matches[id] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, eachName := range idNames {
|
||||||
|
if ctx.filters.Match("name", eachName) {
|
||||||
|
matches[id] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cntrs := make([]*container.Container, 0, len(matches))
|
||||||
|
for id := range matches {
|
||||||
|
cntrs = append(cntrs, daemon.containers.Get(id))
|
||||||
|
}
|
||||||
|
return cntrs
|
||||||
|
}
|
||||||
|
|
||||||
// reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer.
|
// reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer.
|
||||||
func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
|
func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
|
||||||
containers := []*types.Container{}
|
containers := []*types.Container{}
|
||||||
|
@ -99,7 +149,12 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, container := range daemon.List() {
|
// fastpath to only look at a subset of containers if specific name
|
||||||
|
// or ID matches were provided by the user--otherwise we potentially
|
||||||
|
// end up locking and querying many more containers than intended
|
||||||
|
containerList := daemon.filterByNameIDMatches(ctx)
|
||||||
|
|
||||||
|
for _, container := range containerList {
|
||||||
t, err := daemon.reducePsContainer(container, ctx, reducer)
|
t, err := daemon.reducePsContainer(container, ctx, reducer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != errStopIteration {
|
if err != errStopIteration {
|
||||||
|
|
Loading…
Reference in New Issue