From 6132c4d5482a62358ee9166e2655cc876f3b4575 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Wed, 25 Jan 2023 09:21:14 +0100 Subject: [PATCH] ps: do not sync container Do not sync containers with the runtime and the database when listing containers. It turns out to be extremely expensive and unnecessary. The sync was needed since listing all containers from the database did not populate their state. Doing that, however, is much faster since we already have a connection to the database. This change makes listing 200 containers 2 times faster than before. [NO NEW TESTS NEEDED] Signed-off-by: Valentin Rothberg --- libpod/boltdb_state.go | 36 ++------------------------------- libpod/boltdb_state_internal.go | 32 +++++++++++++++++++++++++++++ libpod/container_api.go | 4 ---- 3 files changed, 34 insertions(+), 38 deletions(-) diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index de9e88c737..d5976f540c 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -815,8 +815,6 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { return fmt.Errorf("container %s is in namespace %q, does not match our namespace %q: %w", ctr.ID(), ctr.config.Namespace, s.namespace, define.ErrNSMismatch) } - newState := new(ContainerState) - ctrID := []byte(ctr.ID()) db, err := s.getDBCon() @@ -825,43 +823,13 @@ func (s *BoltState) UpdateContainer(ctr *Container) error { } defer s.deferredCloseDBCon(db) - err = db.View(func(tx *bolt.Tx) error { + return db.View(func(tx *bolt.Tx) error { ctrBucket, err := getCtrBucket(tx) if err != nil { return err } - - ctrToUpdate := ctrBucket.Bucket(ctrID) - if ctrToUpdate == nil { - ctr.valid = false - return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr) - } - - newStateBytes := ctrToUpdate.Get(stateKey) - if newStateBytes == nil { - return fmt.Errorf("container %s does not have a state key in DB: %w", ctr.ID(), define.ErrInternal) - } - - if err := json.Unmarshal(newStateBytes, newState); err != nil { - return fmt.Errorf("unmarshalling container %s state: %w", ctr.ID(), err) - } - - // backwards compat, previously we used a extra bucket for the netns so try to get it from there - netNSBytes := ctrToUpdate.Get(netNSKey) - if netNSBytes != nil && newState.NetNS == "" { - newState.NetNS = string(netNSBytes) - } - - return nil + return s.getContainerStateDB(ctrID, ctr, ctrBucket) }) - if err != nil { - return err - } - - // New state compiled successfully, swap it into the current state - ctr.state = newState - - return nil } // SaveContainer saves a container's current state in the database diff --git a/libpod/boltdb_state_internal.go b/libpod/boltdb_state_internal.go index 48aa0acc49..25f40835bc 100644 --- a/libpod/boltdb_state_internal.go +++ b/libpod/boltdb_state_internal.go @@ -428,11 +428,43 @@ func (s *BoltState) getContainerConfigFromDB(id []byte, config *ContainerConfig, return nil } +func (s *BoltState) getContainerStateDB(id []byte, ctr *Container, ctrsBkt *bolt.Bucket) error { + newState := new(ContainerState) + ctrToUpdate := ctrsBkt.Bucket(id) + if ctrToUpdate == nil { + ctr.valid = false + return fmt.Errorf("container %s does not exist in database: %w", ctr.ID(), define.ErrNoSuchCtr) + } + + newStateBytes := ctrToUpdate.Get(stateKey) + if newStateBytes == nil { + return fmt.Errorf("container %s does not have a state key in DB: %w", ctr.ID(), define.ErrInternal) + } + + if err := json.Unmarshal(newStateBytes, newState); err != nil { + return fmt.Errorf("unmarshalling container %s state: %w", ctr.ID(), err) + } + + // backwards compat, previously we used a extra bucket for the netns so try to get it from there + netNSBytes := ctrToUpdate.Get(netNSKey) + if netNSBytes != nil && newState.NetNS == "" { + newState.NetNS = string(netNSBytes) + } + + // New state compiled successfully, swap it into the current state + ctr.state = newState + return nil +} + func (s *BoltState) getContainerFromDB(id []byte, ctr *Container, ctrsBkt *bolt.Bucket) error { if err := s.getContainerConfigFromDB(id, ctr.config, ctrsBkt); err != nil { return err } + if err := s.getContainerStateDB(id, ctr, ctrsBkt); err != nil { + return err + } + // Get the lock lock, err := s.runtime.lockManager.RetrieveLock(ctr.config.LockID) if err != nil { diff --git a/libpod/container_api.go b/libpod/container_api.go index a2aac96e7a..ab7985629c 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -829,10 +829,6 @@ func (c *Container) Batch(batchFunc func(*Container) error) error { c.lock.Lock() defer c.lock.Unlock() - if err := c.syncContainer(); err != nil { - return err - } - newCtr := new(Container) newCtr.config = c.config newCtr.state = c.state