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 <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2023-01-25 09:21:14 +01:00
parent 4cd7f6354b
commit 6132c4d548
3 changed files with 34 additions and 38 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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