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 daf6cdf
Show file tree
Hide file tree
Showing 20 changed files with 583 additions and 151 deletions.
44 changes: 44 additions & 0 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: build
description: build enos

inputs:
bundle:
description: bundle the enos binary into a zip archive
default: true
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 }}
artifact-path:
description: where the built artifact is located
value: ${{ steps.build.outputs.artifact-path }}

runs:
using: composite
steps:
- name: Build
id: build
env:
ARTIFACT_NAME: ${{ env.PKG_NAME}}_${{ inputs.version }}_${{ inputs.goos }}_${{ inputs.goarch }}.zip
GOARCH: ${{ inputs.goarch }}
GOOS: ${{ inputs.goos }}
shell: bash
run: |
mkdir -p dist out
make
echo "artifact-name=${{ env.ARTIFACT_NAME }}" >> "$GITHUB_OUTPUT"
echo "artifact-path=out/${{ env.ARTIFACT_NAME }}" >> "$GITHUB_OUTPUT"
- if: ${{ inputs.bundle == 'true' }}
name: Bundle
shell: bash
run: zip -r -j ${{ steps.build.outputs.artifact-path }} dist/
50 changes: 50 additions & 0 deletions .github/actions/profile-build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
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 after profiling
default: true
upload-profile:
description: upload default.pgo after profiling
default: true

outputs:
profile-path:
value: default.pgo

runs:
using: composite
steps:
- name: profile
shell: bash
run: |
${{ inputs.build-path }} scenario list --format json --chdir ./acceptance/scenarios/build_pgo/ --profile | jq '.scenarios | length'
mv cpu.pprof cpu.pprof.scenario.list
${{ inputs.build-path }} scenario sample observe complex --max 10 --chdir ./acceptance/scenarios/build_pgo/ --profile
mv cpu.pprof cpu.pprof.sample.observe
go tool pprof -proto cpu.pprof.scenario.list cpu.pprof.sample.observe > ${{ inputs.profile-out }}
- if: ${{ inputs.merge-to-default == 'true' }}
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
- if: ${{ inputs.upload-profile == 'true' }}
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: default.pgo
path: default.pgo
retention-days: 1
if-no-files-found: error
130 changes: 81 additions & 49 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,90 +1,122 @@
---
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@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
- 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@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: metadata.json
path: ${{ steps.generate-metadata-file.outputs.filepath }}

profile-binary:
runs-on: linux
name: Profile enos binary
env:
GOPRIVATE: 'github.com/hashicorp/*'
TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
outputs:
profile-path: ${{ steps.final-profile.outputs.profile-path }}
steps:
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version-file: .go-version
- id: product-metadata
run: |
make version
echo "product-version=$(make version)" >> "$GITHUB_OUTPUT"
- uses: ./.github/actions/build
name: Standard build
with:
bundle: false
goarch: amd64
goos: linux
version: ${{ steps.product-metadata.outputs.product-version }}
- uses: ./.github/actions/profile-build
name: Profile standard build
with:
upload-profile: false
- uses: ./.github/actions/build
name: PGO build
with:
bundle: false
goarch: amd64
goos: linux
version: ${{ steps.product-metadata.outputs.product-version }}
- uses: ./.github/actions/profile-build
id: final-profile
name: Profile PGO build

build:
needs: get-product-version
needs:
- product-metadata
- profile-binary
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/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
- 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
- uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
id: download
with:
name: ${{ needs.profile-binary.outputs.profile-path }}
- 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
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
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: ${{ steps.build.outputs.artifact-name }}
path: ${{ steps.build.outputs.artifact-path }}
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,16 +126,16 @@ 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
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ matrix.goos == 'linux' }}
with:
name: ${{ env.RPM_PACKAGE }}
path: out/${{ env.RPM_PACKAGE }}
- name: Upload Debian Packages
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
if: ${{ matrix.goos == 'linux' }}
with:
name: ${{ env.DEB_PACKAGE }}
Expand All @@ -112,19 +144,19 @@ 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:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
- uses: hashicorp/actions-docker-build@v1
with:
version: ${{env.version}}
Expand All @@ -136,9 +168,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 }}
4 changes: 2 additions & 2 deletions .github/workflows/create_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0

# Set up bob CLI
- name: Setup bob CLI
Expand Down 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
17 changes: 8 additions & 9 deletions .github/workflows/pr_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,23 @@ jobs:
GOARCH: ${{ matrix.goarch }}
CI: true
steps:
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
with:
go-version-file: .go-version
- name: Get Product Version
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
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with:
name: ${{ env.PKG_NAME }}_${{ steps.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
path: out/${{ env.PKG_NAME }}_${{ steps.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/update_homebrew_formula.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
# Checkout Enos repo and place it in the specified relative path within the runner's main directory,
# in order to accommodate checking out multiple repos.
- name: Checkout enos repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
with:
path: enos-checkout
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
Expand Down Expand Up @@ -100,7 +100,7 @@ jobs:
# in order to accommodate checking out multiple repos.
# A token with sufficient permissions for the target repo is required.
- name: Checkout homebrew-internal
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
with:
repository: ${{ env.TARGET_REPO }}
path: ${{ env.TARGET_REPO_FILEPATH }}
Expand Down
Loading

0 comments on commit daf6cdf

Please sign in to comment.