Skip to content

Commit

Permalink
[QT-602] Further optimize scenario listing and sampling
Browse files Browse the repository at this point in the history
As we move to expand the variant list to tens and even hundreds of
thousands of scenarios and variants in vault-enterprise, we ran into a
few issues:
* We hit our maximim gRPC message size when listing all the scenarios
* Listing scenarios with extremely large matricies was too slow

We make the following changes to help address those problems
* gRPC max send and receive are now configurable in the CLI and have 5x
  larger defaults.
* We identified a few hot spots in the program with profiling and
  further optimized them to reduce allocations and speed up comparisons.
* We introduce a three-step build for artifacts. First we build the
  program with default compiler optimizations and profile the program.
  Then we rebuild it again using profile guided optimization. We then
  profile the program again and built it for a third time using profiles
  from our default and guided stages.

Signed-off-by: Ryan Cragun <[email protected]>
  • Loading branch information
ryancragun committed Sep 13, 2023
1 parent 03cd231 commit 6fce568
Show file tree
Hide file tree
Showing 18 changed files with 518 additions and 138 deletions.
35 changes: 35 additions & 0 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: build
description: build enos

inputs:
goarch:
description: the GOARCH value
required: true
goos:
description: the GOOS value
required: true
version:
description: the version of the package
required: true

outputs:
artifact-name:
description: where the built artifact is located
value: ${{ steps.build.outputs.artifact-name }}

runs:
using: composite
steps:
- name: Build
id: build
env:
ARTIFACT_NAME: enos_${{ inputs.product-version }}_${{ inputs.goos }}_${{ inputs.goarch }}.zip
GOARCH: ${{ inputs.goarch }}
GOOS: ${{ inputs.goos }}
GOPRIVATE: 'github.com/hashicorp/*'
shell: bash
run: |
mkdir -p dist out
make
echo "artifact-name="${{ env.ARTIFACT_NAME }}" >> "$GITHUB_OUTPUT"
zip -r -j out/"${{ env.ARTIFACT_NAME }}"
37 changes: 37 additions & 0 deletions .github/actions/profile-build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: profile-build
description: profile enos build

inputs:
build-path:
description: where the enos artifact to profile is
default: dist/enos
profile-out:
description: where to write the union cpu profile
default: cpu.pprof
merge-to-default:
description: merge all cpu profiles to default.pgo arter profiling
required: false
default: true

runs:
using: composite
steps:
- name: profile
shell: bash
run: |
${{ inputs.build-path }} scenario list --format json --chdir ./acceptance/scenarios/build_pgo/ | jq '.scenarios | length'
mv cpu.pprof cpu.pprof.scenario.list
${{ inputs.build-path }} scenario sample observe complex --max 10 --chdir ./acceptance/scenarios/build_pgo/
mv cpu.pprof cpu.pprof.sample.observe
go tool pprof -proto cpu.pprof.scenario.list -proto cpu.pprof.sample.observe > ${{ inputs.profile-out }}
- if: inputs.merge-to-default
name: merge-to-default
shell: bash
run: |
if test -f default.pgo; then
cp default.pgo default.pprof
go tool pprof -proto ${{ inputs.profile-out }} -proto default.pprof > default.pgo
exit 0
fi
cp ${{ inputs.profile-out }} default.pgo
90 changes: 46 additions & 44 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,90 +1,92 @@
---
name: build
on:
# Run the build workflow manually from GitHub Actions menu
workflow_dispatch:
# Run the build workflow on merge to main
push:
branches:
- main
# branches:
# - main # TODO: REMOVE BEFORE MERGE

env:
PKG_NAME: "enos"

jobs:
get-product-version:
product-metadata:
runs-on: linux
outputs:
product-version: ${{ steps.get-product-version.outputs.product-version }}
filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
product-version: ${{ steps.product-metadata.outputs.product-version }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: get product version
id: get-product-version
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- id: product-metadata
run: |
make version
echo "product-version=$(make version)" >> $GITHUB_OUTPUT
generate-metadata-file:
needs: get-product-version
runs-on: linux
outputs:
filepath: ${{ steps.generate-metadata-file.outputs.filepath }}
steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Generate metadata file
id: generate-metadata-file
echo "product-version=$(make version)" >> "$GITHUB_OUTPUT"
- id: generate-metadata-file
uses: hashicorp/actions-generate-metadata@main
with:
version: ${{ needs.get-product-version.outputs.product-version }}
version: ${{ steps.product-metadata.outputs.product-version }}
product: ${{ env.PKG_NAME }}
- name: Upload Metadata
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
- uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: metadata.json
path: ${{ steps.generate-metadata-file.outputs.filepath }}

build:
needs: get-product-version
needs: product-metadata
runs-on: linux
strategy:
matrix:
goos: [linux, darwin]
goarch: [amd64, arm64]
fail-fast: true
name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build
name: Go ${{ matrix.goos }} ${{ matrix.goarch }} build
env:
GOPRIVATE: 'github.com/hashicorp/*'
TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
outputs:
artifact-name: ${{ steps.Build.outputs.artifact-name }}
artifact-name: ${{ steps.build.outputs.artifact-name }}
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version-file: .go-version
- name: Build
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
run: |
mkdir dist out
make
zip -r -j out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/
echo "artifact-name=${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip" >> $GITHUB_OUTPUT
# We do a three stage build with two profiling steps for max pgo benefit.
- uses: ./.github/actions/build
name: build-no-pgo
with:
goarch: ${{ matrix.goarch }}
goos: ${{ matrix.goos }}
version: ${ needs.product-metadata.outputs.product-version }}
- uses: ./.github/actions/profile-build
- uses: ./.github/actions/build
name: build-with-pgo
with:
goarch: ${{ matrix.goarch }}
goos: ${{ matrix.goos }}
version: ${ needs.product-metadata.outputs.product-version }}
- uses: ./.github/actions/profile-build
- uses: ./.github/actions/build
name: build
id: build
with:
goarch: ${{ matrix.goarch }}
goos: ${{ matrix.goos }}
version: ${ needs.product-metadata.outputs.product-version }}
- name: Upload Artifacts
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
name: ${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
path: out/${{ env.PKG_NAME }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
name: ${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
path: out/${{ env.PKG_NAME }}_${{ needs.product-metadata.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
retention-days: 1
- if: ${{ matrix.goos == 'linux' }}
uses: hashicorp/actions-packaging-linux@v1
with:
name: ${{ github.event.repository.name }}
description: "enos CLI package"
arch: ${{ matrix.goarch }}
version: ${{ needs.get-product-version.outputs.product-version }}
version: ${{ needs.product-metadata.outputs.product-version }}
maintainer: "HashiCorp"
homepage: "https://github.com/hashicorp/enos"
license: "MPL-2.0"
Expand All @@ -94,8 +96,8 @@ jobs:
- name: Set Package Names
if: ${{ matrix.goos == 'linux' }}
run: |
echo "RPM_PACKAGE=$(basename out/*.rpm)" >> $GITHUB_ENV
echo "DEB_PACKAGE=$(basename out/*.deb)" >> $GITHUB_ENV
echo "RPM_PACKAGE=$(basename out/*.rpm)" >> "$GITHUB_ENV"
echo "DEB_PACKAGE=$(basename out/*.deb)" >> "$GITHUB_ENV"
- name: Upload RHEL Packages
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
if: ${{ matrix.goos == 'linux' }}
Expand All @@ -112,15 +114,15 @@ jobs:
build-docker:
name: Docker ${{ matrix.arch }} build
needs:
- get-product-version
- product-metadata
- build
runs-on: linux
strategy:
matrix:
arch: ["arm64", "amd64"]
env:
repo: ${{github.event.repository.name}}
version: ${{needs.get-product-version.outputs.product-version}}
version: ${{needs.product-metadata.outputs.product-version}}
GOPRIVATE: 'github.com/hashicorp/*'
TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
steps:
Expand All @@ -136,9 +138,9 @@ jobs:
validate-artifact:
name: Validate Artifact
needs: [build, get-product-version]
needs: [build, product-metadata]
uses: hashicorp/enos/.github/workflows/validate.yml@main
with:
artifact-name: "enos_${{ needs.get-product-version.outputs.product-version }}_linux_amd64.zip"
artifact-name: "enos_${{ needs.product-metadata.outputs.product-version }}_linux_amd64.zip"
secrets:
ENOS_CI_SSH_PRIVATE_KEY: ${{ secrets.ENOS_CI_SSH_PRIVATE_KEY }}
2 changes: 1 addition & 1 deletion .github/workflows/create_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:
PRERELEASE="--prerelease"
TAG=v${{ env.VERSION }}-pre+$( echo ${{ env.SHA }} | head -c 5 )
fi
gh release create $TAG --target ${{ env.SHA }} --generate-notes $PRERELEASE ./.bob/artifacts/*.zip
gh release create "$TAG" --target ${{ env.SHA }} --generate-notes "$PRERELEASE" ./.bob/artifacts/*.zip
# If not a pre-release, generate an updated Homebrew formula definition file
# and open a PR on hashicorp/homebrew-internal with the updated file
Expand Down
13 changes: 6 additions & 7 deletions .github/workflows/pr_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,13 @@ jobs:
id: get-product-version
run: |
make version
echo "product-version=$(make version)" >> $GITHUB_OUTPUT
- name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build
echo "product-version=$(make version)" >> "$GITHUB_OUTPUT"
- uses: ./.github/actions/build
id: build
run: |
mkdir dist out
make build-race
zip -r -j out/${{ env.PKG_NAME }}_${{ steps.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/
echo "artifact-name=${{ env.PKG_NAME }}_${{ steps.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip" >> $GITHUB_OUTPUT
with:
goarch: ${{ matrix.goarch }}
goos: ${{ matrix.goos }}
version: ${{ steps.get-product-version.outputs.product-version }}
- name: Upload
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
with:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ terraform.rc
/acceptance/support/private_key.pem

**/.enos/*

*.pprof
116 changes: 116 additions & 0 deletions acceptance/scenarios/build_pgo/enos-sample.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
module "upgrade" {
source = "./modules/upgrade"
}

module "replication" {
source = "./modules/replication"
}

scenario "upgrade" {
matrix {
arch = ["amd64", "arm64"]
artifact_source = ["local", "crt", "artifactory"]
artifact_type = ["bundle", "package"]
backend = ["consul", "raft"]
consul_version = ["1.12.3", "1.13.6", "1.14.9", "1.15.5", "1.16.1"]
distro = ["ubuntu", "rhel"]
edition = ["ce", "ent", "ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
initial_version = ["1.8.12", "1.9.10", "1.10.11", "1.11.12", "1.12.11", "1.13.6", "1.14.2"]
seal = ["awskms", "shamir"]

# Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}

# HSM and FIPS 140-2 are only supported on amd64
exclude {
arch = ["arm64"]
edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
}

# FIPS 140-2 editions began at 1.10
exclude {
edition = ["ent.fips1402", "ent.hsm.fips1402"]
initial_version = ["1.8.12", "1.9.10"]
}
}

step "upgrade" {
module = module.upgrade
}

variables {
az = matrix.distro
}
}

scenario "replication" {
matrix {
arch = ["amd64", "arm64"]
artifact_source = ["local", "crt", "artifactory"]
artifact_type = ["bundle", "package"]
backend = ["consul", "raft"]
consul_version = ["1.12.3", "1.13.6", "1.14.9", "1.15.5", "1.16.1"]
distro = ["ubuntu", "rhel"]
edition = ["ce", "ent", "ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
initial_version = ["1.8.12", "1.9.10", "1.10.11", "1.11.12", "1.12.11", "1.13.6", "1.14.2"]
seal = ["awskms", "shamir"]

# Our local builder always creates bundles
exclude {
artifact_source = ["local"]
artifact_type = ["package"]
}

# HSM and FIPS 140-2 are only supported on amd64
exclude {
arch = ["arm64"]
edition = ["ent.fips1402", "ent.hsm", "ent.hsm.fips1402"]
}

# FIPS 140-2 editions began at 1.10
exclude {
edition = ["ent.fips1402", "ent.hsm.fips1402"]
initial_version = ["1.8.12", "1.9.10"]
}
}

step "replication" {
module = module.replication
}

variables {
az = matrix.distro
}
}

sample "complex" {
attributes = {
aws-region = ["us-west-1", "us-west-2"]
continue-on-error = false
}

subset "upgrade_consul" {
scenario_name = "upgrade"

attributes = {
continue-on-error = true
}

matrix {
arch = ["amd64", "arm64"]
backend = ["consul"]
}
}

subset "upgrade_raft" {
scenario_name = "replication"

matrix {
arch = ["amd64", "arm64"]
backend = ["raft"]
}
}
}
Loading

0 comments on commit 6fce568

Please sign in to comment.