Comment 9 for bug 1594924

Revision history for this message
James Tunnicliffe (dooferlad) wrote :

github.com/juju/juju/resource/state/resource.go contains:

func (u *unitSetter) Read(p []byte) (n int, err error) {
 n, err = u.ReadCloser.Read(p)
 here.Is(n)
 if err == io.EOF {
  // record that the unit is now using this version of the resource
  if err := u.persist.SetUnitResource(u.unit.Name(), u.resource); err != nil {
   msg := "Failed to record that unit %q is using resource %q revision %v"
   logger.Errorf(msg, u.unit.Name(), u.resource.Name,
                                      u.resource.RevisionString())
  }
 } else {
  u.progress += int64(n)
  // TODO(ericsnow) Don't do this every time?
  if err := u.persist.SetUnitResourceProgress(u.unit.Name(), u.pending, u.progress); err != nil {
   logger.Errorf("failed to track progress: %v", err)
  }
 }
 return n, err
}

That u.persist.SetUnitResourceProgress involves a database transaction and is called every 8kb of data, so for a large file there is massive contention on the database. Comment it out and the file is read at the expected rate (can read 800M to /dev/null in ~2 seconds).

I will propose a change that updates the progress once a second. Looks like the entire HTTP request takes about 5 seconds for an 800MB file.