Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redfish stream multipart uploads #345

Merged
merged 5 commits into from
Sep 11, 2023
Merged

Redfish stream multipart uploads #345

merged 5 commits into from
Sep 11, 2023

Conversation

joelrebel
Copy link
Member

What does this PR implement/change/remove?

The Redfish provider currently reads the firmware files into memory before a multipart upload,
this results in high memory consumption for the client and can be problematic for cases
where firmware installs have to be performed simultaneously.

This change was part of bmclib v1 #279
but was somehow missed from being included in v2.

Tested with Dell R6515's, R7640.

heap profile - with streaming uploads

(pprof) top 20
Showing nodes accounting for 2059.99kB, 100% of 2059.99kB total
Showing top 20 nodes out of 29
      flat  flat%   sum%        cum   cum%
  520.04kB 25.24% 25.24%  1034.42kB 50.21%  encoding/json.(*Decoder).refill
  514.38kB 24.97% 50.21%   514.38kB 24.97%  compress/flate.NewReader
  513.56kB 24.93% 75.15%   513.56kB 24.93%  regexp/syntax.init
  512.01kB 24.85%   100%   512.01kB 24.85%  sync.(*Map).Swap
         0     0%   100%   514.38kB 24.97%  compress/gzip.(*Reader).Reset
         0     0%   100%   514.38kB 24.97%  compress/gzip.(*Reader).readHeader
         0     0%   100%   514.38kB 24.97%  compress/gzip.NewReader
         0     0%   100%  1546.43kB 75.07%  encoding/json.(*Decoder).Decode
         0     0%   100%  1034.42kB 50.21%  encoding/json.(*Decoder).readValue
         0     0%   100%   512.01kB 24.85%  encoding/json.(*decodeState).object
         0     0%   100%   512.01kB 24.85%  encoding/json.(*decodeState).unmarshal
         0     0%   100%   512.01kB 24.85%  encoding/json.(*decodeState).value
         0     0%   100%   512.01kB 24.85%  encoding/json.Unmarshal
         0     0%   100%   512.01kB 24.85%  encoding/json.cachedTypeFields
         0     0%   100%   512.01kB 24.85%  encoding/json.typeEncoder
         0     0%   100%   512.01kB 24.85%  encoding/json.typeFields
         0     0%   100%  1032.05kB 50.10%  github.com/stmcginnis/gofish/common.(*Entity).Get
         0     0%   100%  1032.05kB 50.10%  github.com/stmcginnis/gofish/common.CollectCollection.func1
         0     0%   100%   514.38kB 24.97%  github.com/stmcginnis/gofish/common.CollectList
         0     0%   100%   514.38kB 24.97%  github.com/stmcginnis/gofish/common.GetCollection

heap profile - without streaming uploads

(pprof) top 30
Showing nodes accounting for 240MB, 99.58% of 241MB total
Dropped 16 nodes (cum <= 1.21MB)
      flat  flat%   sum%        cum   cum%
     240MB 99.58% 99.58%      240MB 99.58%  bytes.growSlice
         0     0% 99.58%      240MB 99.58%  bytes.(*Buffer).Write
         0     0% 99.58%      240MB 99.58%  bytes.(*Buffer).grow
         0     0% 99.58%   240.50MB 99.79%  github.com/bmc-toolbox/bmclib/v2.(*Client).FirmwareInstall
         0     0% 99.58%   240.50MB 99.79%  github.com/bmc-toolbox/bmclib/v2/bmc.FirmwareInstallFromInterfaces
         0     0% 99.58%   240.50MB 99.79%  github.com/bmc-toolbox/bmclib/v2/bmc.firmwareInstall
         0     0% 99.58%   240.50MB 99.79%  github.com/bmc-toolbox/bmclib/v2/providers/redfish.(*Conn).FirmwareInstall
         0     0% 99.58%   240.50MB 99.79%  github.com/bmc-toolbox/bmclib/v2/providers/redfish.(*Conn).runRequestWithMultipartPayload
         0     0% 99.58%      240MB 99.58%  io.Copy (inline)
         0     0% 99.58%      240MB 99.58%  io.copyBuffer
         0     0% 99.58%   240.50MB 99.79%  main.main
         0     0% 99.58%      240MB 99.58%  mime/multipart.(*part).Write
         0     0% 99.58%      241MB   100%  runtime.main

Checklist

  • Tests added
  • Similar commits squashed

Description for changelog/release notes

- Redfish streaming multipart uploads

These changes were already part of bmclib v1 but missed out from being included in v2,
#279
@codecov
Copy link

codecov bot commented Aug 16, 2023

Codecov Report

Patch coverage: 50.00% and no project coverage change.

Comparison is base (a1b87e2) 42.67% compared to head (08172f2) 42.68%.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #345   +/-   ##
=======================================
  Coverage   42.67%   42.68%           
=======================================
  Files          44       44           
  Lines        3691     3730   +39     
=======================================
+ Hits         1575     1592   +17     
- Misses       1937     1951   +14     
- Partials      179      187    +8     
Files Changed Coverage Δ
providers/redfish/firmware.go 46.31% <50.00%> (-0.71%) ⬇️

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

providers/redfish/firmware.go Outdated Show resolved Hide resolved

size = finfo.Size()

} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any clue what other kinds of readers might show up here? It might be nice to see if the implementation of reader might have a .Len method so we can avoid unnecessary reads.

type Lenner interface {
	Len() int
}
...

if file, ok := reader.(*os.File); ok {
...
} else if lenner, ok := reader.(Lenner); ok {
...
} else {
// read the file to get size
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, this might need some rethinking - since we also require the file name here,

  if file, ok := reader.(*os.File); ok {
    // Add update file fields
    if _, err = form.CreateFormFile(key, filepath.Base(file.Name())); err != nil {
      return 0, body, err
    }
    ...
  }  

providers/redfish/firmware.go Outdated Show resolved Hide resolved
@joelrebel joelrebel requested a review from mmlb August 25, 2023 15:23
providers/redfish/firmware.go Outdated Show resolved Hide resolved
providers/redfish/firmware.go Outdated Show resolved Hide resolved
@joelrebel
Copy link
Member Author

@mmlb whenever you're back, PTAL :)

@joelrebel joelrebel requested a review from mmlb September 5, 2023 08:53
ofaurax
ofaurax previously approved these changes Sep 5, 2023
Copy link
Collaborator

@ofaurax ofaurax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Waiting for @mmlb but I give my approval since it's needed for #346

…t instead

This makes the code easier to read and maintain.

As of now we limit the method to expect an os.File as an io.Reader,
once its clear theres other implementations of io.Readers required we
can accept those and figure how to determine the file size for the
multipart payload
Copy link
Collaborator

@mmlb mmlb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree that this looks much better! I think if we drop io.Reader for the updateParameters it will similarly make it simpler too.

providers/redfish/firmware.go Outdated Show resolved Hide resolved
This makes the UpdateParameters handling easier to grok and maintain
@joelrebel joelrebel requested a review from mmlb September 11, 2023 09:08
Copy link
Collaborator

@mmlb mmlb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@joelrebel joelrebel merged commit f99e587 into main Sep 11, 2023
@joelrebel joelrebel deleted the redfish-stream-uploads branch September 11, 2023 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants