-
Notifications
You must be signed in to change notification settings - Fork 59
feat(EC-1816): add multi-component stress benchmark #3331
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
base: main
Are you sure you want to change the base?
Changes from all commits
136bb38
c555ff0
ef36c36
bd9ea39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #!/bin/bash | ||
| # Copyright The Conforma Contributors | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| # Creates the files in the data directory that should contain all the data | ||
| # needed to run the benchmark. Tries to pull a pre-built data archive from Quay | ||
| # first, falling back to building from upstream using the ../offliner for images | ||
| # and plain git clone for the git data dependency. Uses the same | ||
| # golden-container image as the simple benchmark -- the stress benchmark | ||
| # duplicates it across components at runtime. | ||
| set -o errexit | ||
| set -o nounset | ||
| set -o pipefail | ||
|
|
||
| quay_ref="quay.io/conforma/benchmark-data:stress-v1" | ||
|
|
||
| if command -v oras &>/dev/null && oras pull "${quay_ref}" -o . 2>/dev/null; then | ||
| echo "Downloaded data.tar.gz from ${quay_ref}" | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "Quay pull failed or oras not available, regenerating from upstream..." | ||
|
|
||
| offliner="$(git rev-parse --show-toplevel)/benchmark/offliner" | ||
|
|
||
| dir="$(mktemp -d)" | ||
| trap 'rm -rf "${dir}"' EXIT | ||
|
|
||
| ( | ||
| cd "${dir}" | ||
|
|
||
| imgs=( | ||
| quay.io/redhat-user-workloads/rhtap-contract-tenant/golden-container/golden-container@sha256:166e38c156fa81d577a7ba7a948b68c79005a06e302779d1bebc7d31e8bea315 | ||
| quay.io/konflux-ci/tekton-catalog/data-acceptable-bundles@sha256:1e70b8f672388838f20a7d45e145e31e99dab06cefa1c5514d6ce41c8bbea1b0 | ||
| quay.io/enterprise-contract/ec-release-policy@sha256:64617f0c45689ef7152c5cfbd4cd5709a3126e4ab7482eb6acd994387fe2d4ba | ||
| ) | ||
|
|
||
| for img in "${imgs[@]}"; do | ||
| go run -C "${offliner}" . "${img}" "${dir}/data/registry/data" | ||
| done | ||
|
|
||
| git clone --no-checkout https://github.com/release-engineering/rhtap-ec-policy.git data/git/rhtap-ec-policy.git | ||
| ) | ||
|
|
||
| tar czf data.tar.gz -C "${dir}" . | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #!/bin/bash | ||
| # Copyright The Conforma Contributors | ||
| # | ||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| # you may not use this file except in compliance with the License. | ||
| # You may obtain a copy of the License at | ||
| # | ||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
| # | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| # Pushes the local data.tar.gz to Quay as an OCI artifact. Requires prior | ||
| # authentication via `oras login quay.io`. | ||
| set -o errexit | ||
| set -o nounset | ||
| set -o pipefail | ||
|
|
||
| quay_ref="quay.io/conforma/benchmark-data:stress-v1" | ||
|
|
||
| if [[ ! -f data.tar.gz ]]; then | ||
| echo "data.tar.gz not found, run prepare_data.sh first" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| oras push "${quay_ref}" data.tar.gz | ||
| echo "Pushed data.tar.gz to ${quay_ref}" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,178 @@ | ||
| // Copyright The Conforma Contributors | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||
| // you may not use this file except in compliance with the License. | ||
| // You may obtain a copy of the License at | ||
| // | ||
| // http://www.apache.org/licenses/LICENSE-2.0 | ||
| // | ||
| // Unless required by applicable law or agreed to in writing, software | ||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| // See the License for the specific language governing permissions and | ||
| // limitations under the License. | ||
| // | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| // Stress benchmark validating a multi-component snapshot with a configurable | ||
| // number of workers, simulating real-world release pipeline workloads. The | ||
| // component count and worker count are controlled via the EC_STRESS_COMPONENTS | ||
| // and EC_STRESS_WORKERS environment variables respectively. Uses the same | ||
| // golden-container image data as the simple benchmark, duplicated across | ||
| // components to create memory pressure. The prepare_data.sh script can be used | ||
| // to re-populate the data directory. | ||
| package main | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "os" | ||
| "path" | ||
| "strconv" | ||
|
|
||
| "golang.org/x/benchmarks/driver" | ||
|
|
||
| "github.com/conforma/cli/benchmark/internal/registry" | ||
| "github.com/conforma/cli/benchmark/internal/suite" | ||
| "github.com/conforma/cli/benchmark/internal/untar" | ||
| ) | ||
|
coderabbitai[bot] marked this conversation as resolved.
dheerajodha marked this conversation as resolved.
|
||
|
|
||
| const ( | ||
| defaultComponents = 10 | ||
| defaultWorkers = 35 | ||
|
dheerajodha marked this conversation as resolved.
|
||
| ) | ||
|
|
||
| func main() { | ||
| driver.Main("Stress", benchmark) | ||
| } | ||
|
|
||
| func envInt(name string, fallback int) int { | ||
| v, ok := os.LookupEnv(name) | ||
| if !ok { | ||
| return fallback | ||
|
dheerajodha marked this conversation as resolved.
|
||
| } | ||
| n, err := strconv.Atoi(v) | ||
| if err != nil { | ||
| panic(fmt.Sprintf("invalid %s value %q: %v", name, v, err)) | ||
|
dheerajodha marked this conversation as resolved.
|
||
| } | ||
| if n < 1 { | ||
| panic(fmt.Sprintf("%s must be >= 1, got %d", name, n)) | ||
| } | ||
| return n | ||
| } | ||
|
|
||
| func setup() (string, suite.Closer) { | ||
| dir, err := untar.UnTar("data.tar.gz") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| closer, err := registry.Launch(path.Join(dir, "data/registry/data")) | ||
| if err != nil { | ||
|
dheerajodha marked this conversation as resolved.
|
||
| panic(err) | ||
| } | ||
|
|
||
| return dir, func() { | ||
| closer() | ||
| os.RemoveAll(dir) | ||
| } | ||
| } | ||
|
|
||
| type component struct { | ||
| Name string `json:"name"` | ||
| ContainerImage string `json:"containerImage"` | ||
| Source *source `json:"source,omitempty"` | ||
| } | ||
|
|
||
| type source struct { | ||
| Git gitSource `json:"git"` | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [low] edge-case The buildSnapshot function names components as 'golden-container-0', 'golden-container-1', etc. When EC_STRESS_COMPONENTS=1, this produces 'golden-container-0', while the simple benchmark names its single component 'golden-container' (no index suffix). Functionally correct but worth noting for result comparison consistency between benchmarks. |
||
| } | ||
|
|
||
| type gitSource struct { | ||
| URL string `json:"url"` | ||
| Revision string `json:"revision"` | ||
| } | ||
|
|
||
| type snapshot struct { | ||
| Components []component `json:"components"` | ||
|
dheerajodha marked this conversation as resolved.
|
||
| } | ||
|
|
||
| func buildSnapshot(n int) string { | ||
| s := snapshot{Components: make([]component, n)} | ||
| for i := range s.Components { | ||
| s.Components[i] = component{ | ||
| Name: fmt.Sprintf("golden-container-%d", i), | ||
| ContainerImage: "quay.io/redhat-user-workloads/rhtap-contract-tenant/golden-container/golden-container@sha256:166e38c156fa81d577a7ba7a948b68c79005a06e302779d1bebc7d31e8bea315", | ||
| Source: &source{ | ||
| Git: gitSource{ | ||
| URL: "https://github.com/enterprise-contract/golden-container.git", | ||
| Revision: "8327c1ce7472b017b9396fe26d5d5e1ed0eb61cc", | ||
| }, | ||
| }, | ||
| } | ||
| } | ||
|
|
||
| data, err := json.Marshal(s) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| return string(data) | ||
|
dheerajodha marked this conversation as resolved.
|
||
| } | ||
|
|
||
| func benchmark() driver.Result { | ||
| dir, closer := setup() | ||
| defer closer() | ||
|
|
||
| components := envInt("EC_STRESS_COMPONENTS", defaultComponents) | ||
| workers := envInt("EC_STRESS_WORKERS", defaultWorkers) | ||
|
|
||
| return driver.Benchmark(run(dir, components, workers)) | ||
| } | ||
|
|
||
| func ec(dir string, components, workers int) func() { | ||
| snap := buildSnapshot(components) | ||
|
|
||
| policy := fmt.Sprintf(`{ | ||
| "publicKey": "-----BEGIN PUBLIC KEY-----\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZP/0htjhVt2y0ohjgtIIgICOtQtA\nnaYJRuLprwIv6FDhZ5yFjYUEtsmoNcW7rx2KM6FOXGsCX3BNc7qhHELT+g==\n-----END PUBLIC KEY-----", | ||
| "sources": [ | ||
| { | ||
| "data": [ | ||
| "git::file://%s/data/git/rhtap-ec-policy.git//data?ref=a524ee2f2f7774f6f360eb64c4cb24004de52aae", | ||
| "oci::quay.io/konflux-ci/tekton-catalog/data-acceptable-bundles@sha256:1e70b8f672388838f20a7d45e145e31e99dab06cefa1c5514d6ce41c8bbea1b0" | ||
| ], | ||
| "policy": [ | ||
| "oci::quay.io/enterprise-contract/ec-release-policy@sha256:64617f0c45689ef7152c5cfbd4cd5709a3126e4ab7482eb6acd994387fe2d4ba" | ||
| ], | ||
| "config": { | ||
| "include": [ | ||
| "@redhat" | ||
| ] | ||
| } | ||
| } | ||
| ] | ||
| }`, dir) | ||
|
|
||
| return func() { | ||
| if err := suite.Execute([]string{ | ||
| "validate", | ||
| "image", | ||
| "--images", | ||
| snap, | ||
| "--policy", | ||
| policy, | ||
| "--ignore-rekor", | ||
| "--workers", | ||
| strconv.Itoa(workers), | ||
| "--effective-time", | ||
| "2024-12-10T00:00:00Z", | ||
| }); err != nil { | ||
| panic(err) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func run(dir string, components, workers int) func(n uint64) { | ||
| return func(n uint64) { | ||
| driver.Parallel(n, 1, ec(dir, components, workers)) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.