Repository navigation
Conversation
Merging this PR will not alter performance
|
454fdc6 to
1cc552d
Compare
1cc552d to
a2f09f3
Compare
|
a2f09f3 to
c60ccf8
Compare
S3 rejects single uploads above 5 GiB, and a single connection to S3 only reaches about 20-25 MiB/s on GitHub-hosted runners, so large profile archives were slow or impossible to upload. Archives of 64 MiB and more are now sent as an S3 multipart upload, in about two parts per concurrent upload, each between 16 MiB and 256 MiB. The md5 of every part is computed in the same pass as the archive md5 and sent in the upload metadata (version 12) as `profileMultipart`. The API then answers with `multipartUploadUrls`: the parts are uploaded 8 at a time (overridable with `CODSPEED_UPLOAD_CONCURRENCY`), each with its own retries, then the upload is completed with the part ETags in order. This applies to both on-disk and in-memory (gzip) archives. Walltime profile folders above 5 GiB are no longer gzipped on disk to fit in a single request, and the maximum archive size goes from 5 GiB to 15 GiB. Archives are now hashed while streaming on the blocking thread pool, instead of being read whole into memory on the async runtime. Closes COD-3700 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
c60ccf8 to
b2177c0
Compare
| pub(super) fn is_transient(&self) -> bool { | ||
| matches!( | ||
| self.code.as_deref(), | ||
| Some("InternalError" | "ServiceUnavailable" | "SlowDown" | "RequestTimeout") | ||
| ) |
There was a problem hiding this comment.
Retryable completion errors fail
If S3 returns a retryable error such as Throttling inside a 200 completion response, this four-code list treats it as permanent. The caller then stops retrying, so an upload that could succeed on a later completion attempt fails.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/upload/s3.rs
Line: 95-99
Comment:
**Retryable completion errors fail**
If S3 returns a retryable error such as `Throttling` inside a 200 completion response, this four-code list treats it as permanent. The caller then stops retrying, so an upload that could succeed on a later completion attempt fails.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.There was a problem hiding this comment.
"Throttling" is not a real AWS S3 error, see https://docs.aws.amazon.com/AmazonS3/latest/developerguide/ErrorResponses.html#ErrorCodeList
There was a problem hiding this comment.
You’re right — Throttling is not an S3 error code; S3 uses SlowDown for throttling, which this list already handles. I withdraw the comment.
Upload profile archives of 64 MiB and more as S3 multipart uploads, with parts sent concurrently.
S3 rejects a single upload request above 5 GiB, so large walltime and memory profile archives could not be uploaded (walltime folders above 5 GiB were gzipped on disk to try to fit). Even below that limit, a single connection to S3 only reaches about 20-25 MiB/s on GitHub-hosted runners, so a 1 GiB archive took close to a minute to upload.
How it works
profileMultipart(size,partSize,partMd5s).multipartUploadUrls(partUrls,completeUrl) instead ofuploadUrl. Each part URL is presigned with the part'sContent-MD5, so S3 checks every part. Parts are uploaded 8 at a time, each with its own retries, then the ETags are sent in part order to the completion URL. S3 can report a failed completion with a 200 status, so the response body is also checked for an error.upload::s3module.CODSPEED_UPLOAD_CONCURRENCYoverrides the number of concurrent part uploads.Archives below 64 MiB keep the single upload request, and their metadata is unchanged apart from the version.
Other changes
Measurements
Concurrency sweep on a 6 GiB walltime archive (25 parts of 256 MiB), which led to the default of 8:
ubuntu-latestSmaller archives with the final part layout, concurrency 1 (close to the previous single request) vs 8:
ubuntu-latestubuntu-latestThe backend support for
profileMultipartis not released yet, so the multipart path cannot be verified end to end against production for now.Closes COD-3700