<kbd id="5sdj3"></kbd>
<th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>

    使用 GitHub Actions 構(gòu)建 Golang PGO

    共 31529字,需瀏覽 64分鐘

     ·

    2024-04-24 19:53

    今年 2 月,我宣布 Dolt 版本現(xiàn)已構(gòu)建為配置文件引導(dǎo)優(yōu)化 (pgo) 二進(jìn)制文件,利用 Golang 1.20 的強(qiáng)大功能將 Dolt 的讀取性能提高 5.3%。

    在我宣布這一消息之前,我們的一位常駐 Golang 專(zhuān)家 Zach 試驗(yàn)并測(cè)試了 Golang 的 pgo 功能,并寫(xiě)下了他在使用 Dolt 構(gòu)建后觀(guān)察到的性能提升,該配置文件首先針對(duì) Dolt 運(yùn)行我們的 Sysbench 基準(zhǔn)測(cè)試。從那時(shí)起,我們知道我們必須將這些性能提升納入我們發(fā)布的二進(jìn)制文件中,因此我們重新設(shè)計(jì)了 Dolt 的發(fā)布流程來(lái)構(gòu)建 pgo 版本。

    今天,我將介紹 Dolt 的一般發(fā)布流程,該流程使用 GitHub Actions,并且我將詳細(xì)介紹發(fā)布流程的所有階段。我還將回顧一下我們?cè)陂_(kāi)始發(fā)布 pgo 版本的過(guò)程中所做的更改。希望這能讓您收集一些可用于將 pgo 構(gòu)建到您自己的 Golang 版本中的見(jiàn)解!

    讓我們開(kāi)始吧。

    Dolt 通過(guò) GitHub Actions 發(fā)布

    Dolt 利用 GitHub Actions 執(zhí)行許多自動(dòng)化任務(wù),其中之一是創(chuàng)建和發(fā)布版本。

    GitHub Actions 使用稱(chēng)為工作流的文件來(lái)定義作業(yè),它將執(zhí)行工作流文件中定義的工作。這些作業(yè)部署到運(yùn)行器或主機(jī)上,您可以自行托管或允許 GitHub 為您托管。

    自托管運(yùn)行器由您在 GitHub Actions 外部配置和維護(hù)。GitHub 托管的運(yùn)行器可免費(fèi)用于公共存儲(chǔ)庫(kù),全部由 GitHub 托管和維護(hù),但它們具有特定的存儲(chǔ)、內(nèi)存和 CPU 限制,具體取決于您的訂閱級(jí)別。對(duì)于 Dolt,我們使用免費(fèi)的 GitHub 托管運(yùn)行器。

    從高層次來(lái)看,Dolt 發(fā)布流程需要實(shí)現(xiàn)一些目標(biāo)。

    首先,也是最重要的,該過(guò)程需要為新版本的 Dolt 創(chuàng)建標(biāo)簽和發(fā)布,并將 Dolt 的預(yù)編譯二進(jìn)制文件上傳到發(fā)布資產(chǎn)。

    其次,發(fā)布過(guò)程需要針對(duì)這個(gè)新版本的 Dolt 運(yùn)行我們的 Sysbench 基準(zhǔn)測(cè)試,并將結(jié)果通過(guò)電子郵件發(fā)送給我們的 DoltHub 團(tuán)隊(duì)。

    第三,與本博客不太相關(guān),該流程需要啟動(dòng)我們?cè)诎l(fā)布期間需要執(zhí)行的任何其他輔助任務(wù),例如創(chuàng)建依賴(lài)于多個(gè)存儲(chǔ)庫(kù)的拉取請(qǐng)求描述的 Dolt 發(fā)行說(shuō)明、將版本發(fā)布到各種包管理器這樣就可以輕松地從它們安裝,將新的 Docker 鏡像推送到 DockerHub,或者升級(jí)我們擁有的各種存儲(chǔ)庫(kù)中的 Dolt 依賴(lài)項(xiàng)。

    因此,考慮到這些目標(biāo),我們提出了一套 GitHub Actions 工作流程,利用repository_dispatch 事件,以便我們可以實(shí)現(xiàn)每個(gè)目標(biāo)。讓我們看一個(gè)圖表,該圖表顯示了此設(shè)計(jì)的原理,然后我們將深入了解工作流程的細(xì)節(jié)。

    在上圖中,您將看到兩個(gè)上下文:GitHub Actions 上下文和 Kubernetes (K8s) 上下文。我們首先討論 GitHub Actions 上下文。

    對(duì)于 Dolt 的原始發(fā)布流程,我們使用了三個(gè)工作流程:“發(fā)布 Dolt”工作流程、“部署 K8s Sysbench 基準(zhǔn)測(cè)試作業(yè)”工作流程和“電子郵件團(tuán)隊(duì)”工作流程。

    “發(fā)布 Dolt”工作流程啟動(dòng)整個(gè) Dolt 發(fā)布流程,并由我們的工程團(tuán)隊(duì)在準(zhǔn)備發(fā)布新版本 Dolt 時(shí)手動(dòng)運(yùn)行。這是工作流程的簡(jiǎn)化版本,引用了上圖中顯示的步驟。

    name: Release Dolt
    on: workflow_dispatch: inputs: version: description: 'SemVer format release tag, i.e. 0.24.5' required: true
    jobs: format-version: runs-on: ubuntu-22.04 outputs: version: ${{ steps.format_version.outputs.version }} steps: - name: Format Input id: format_version run: | version="${{ github.event.inputs.version }}" if [[ $version == v* ]]; then version="${version:1}" fi echo "version=$version" >> $GITHUB_OUTPUT
    create-release: needs: format-version name: Create release runs-on: ubuntu-22.04 outputs: release_id: ${{ steps.create_release.outputs.id }} steps: - name: Checkout code uses: actions/checkout@v3 - name: Set up Go 1.x uses: actions/setup-go@v3 with: go-version: ^1.21 - name: Update dolt version command run: sed -i -e 's/ Version = ".*"/ Version = "'"$NEW_VERSION"'"/' "$FILE" env: FILE: ${{ format('{0}/go/cmd/dolt/dolt.go', github.workspace) }} NEW_VERSION: ${{ needs.format-version.outputs.version }} - name: Set minver TBD to version run: sed -i -e 's/minver:"TBD"/minver:"'"$NEW_VERSION"'"/' "$FILE" env: FILE: ${{ format('{0}/go/cmd/dolt/commands/sqlserver/yaml_config.go', github.workspace) }} NEW_VERSION: ${{ needs.format-version.outputs.version }} - name: update minver_validation.txt working-directory: ./go run: go run -mod=readonly ./utils/genminver_validation/ $FILE env: FILE: ${{ format('{0}/go/cmd/dolt/commands/sqlserver/testdata/minver_validation.txt', github.workspace) }} - uses: EndBug/[email protected] with: message: ${{ format('[ga-bump-release] Update Dolt version to {0} and release v{0}', needs.format-version.outputs.version) }} add: ${{ format('["{0}/go/cmd/dolt/dolt.go", "{0}/go/cmd/dolt/commands/sqlserver/yaml_config.go", "{0}/go/cmd/dolt/commands/sqlserver/testdata/minver_validation.txt"]', github.workspace) }} cwd: "." pull: "--ff" - name: Build Binaries id: build_binaries run: | latest=$(git rev-parse HEAD) echo "commitish=$latest" >> $GITHUB_OUTPUT GO_BUILD_VERSION=1.21 go/utils/publishrelease/buildbinaries.sh - name: Create Release id: create_release uses: dolthub/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: v${{ needs.format-version.outputs.version }} release_name: ${{ needs.format-version.outputs.version }} draft: false prerelease: false commitish: ${{ steps.build_binaries.outputs.commitish }} - name: Upload Linux AMD64 Distro id: upload-linux-amd64-distro uses: dolthub/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: go/out/dolt-linux-amd64.tar.gz asset_name: dolt-linux-amd64.tar.gz asset_content_type: application/zip... - name: Upload Install Script id: upload-install-script uses: dolthub/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: go/out/install.sh asset_name: install.sh asset_content_type: text/plain
    trigger-performance-benchmark-email: needs: [format-version, create-release] runs-on: ubuntu-22.04 steps: - name: Trigger Performance Benchmarks uses: peter-evans/[email protected] with: token: ${{ secrets.REPO_ACCESS_TOKEN }} event-type: release-dolt client-payload: '{"version": "${{ needs.format-version.outputs.version }}", "actor": "${{ github.actor }}"}'

    此工作流是使用workflow_dispatch 事件手動(dòng)觸發(fā)的,并且需要新的版本號(hào)作為輸入。從那里,它對(duì)版本輸入進(jìn)行一些快速格式化,然后將此新版本寫(xiě)入并提交到 Dolt 的 main 分支,以便發(fā)布的二進(jìn)制文件將從 dolt version 命令輸出此新版本。

    在“構(gòu)建二進(jìn)制文件”步驟中, create-release 作業(yè)運(yùn)行 buildbinaries.sh 腳本,該腳本使用運(yùn)行 go build 命令的 Golang Docker 容器從源代碼構(gòu)建 Dolt。

    我們使用 Docker 容器來(lái)構(gòu)建 Dolt,以便堆棧跟蹤的路徑輸出是通用 Linux go 路徑,而不是引用運(yùn)行器或我們的一臺(tái)個(gè)人計(jì)算機(jī)上的 go 安裝的路徑(這發(fā)生在 Dolt ?? 的早期版本中)。

    接下來(lái),“創(chuàng)建版本”步驟創(chuàng)建標(biāo)簽并在 GitHub 上發(fā)布版本。它還提供了一個(gè) upload_url ,用于 create-release 作業(yè)的所有后續(xù)步驟,將已編譯的二進(jìn)制文件上傳到新的 GitHub 版本。

    此工作流程的最后部分是在所有先前作業(yè)完成后運(yùn)行的另一個(gè)作業(yè)。該作業(yè)稱(chēng)為 trigger-performance-benchmark-email 。它使用我們?cè)谄涫袌?chǎng)上找到的 GitHub Action 來(lái)發(fā)出 repository_dispatch 事件,該事件啟動(dòng)單獨(dú)的 Dolt 工作流程。如果我們回顧一下我們的圖表,我們就可以看到這一點(diǎn)。

    我們的圖表顯示了“發(fā)布 Dolt”工作流程的最后一步,該工作流程指向另一個(gè)名為“部署 K8s Sysbench 基準(zhǔn)測(cè)試作業(yè)”的工作流程。這是由 trigger-performance-benchmark-email 工作流作業(yè)啟動(dòng)的工作流。

    此工作流以及其他類(lèi)似工作流被設(shè)計(jì)為部分異步分派,以便它不會(huì)僅與“Release Dolt”工作流緊密耦合。

    事實(shí)上,各種工作流程將使用 repository_dispatch 事件觸發(fā)此工作流程,因?yàn)槲覀冃枰诓煌瑫r(shí)間運(yùn)行性能基準(zhǔn)測(cè)試,而不僅僅是在發(fā)布期間運(yùn)行。有趣的是,這個(gè)工作流程本身啟動(dòng)了另一個(gè)異步流程,我們可以在箭頭所示的圖中看到它 - 它部署了一個(gè)運(yùn)行我們的 Sysbench 基準(zhǔn)測(cè)試的 K8s 作業(yè)。

    事實(shí)上,我們已經(jīng)寫(xiě)了很多關(guān)于 Dolt 使用 Sysbench 對(duì) Dolt 和 MySQL 進(jìn)行基準(zhǔn)測(cè)試來(lái)比較它們的性能的文章,但我認(rèn)為我們沒(méi)有討論具體如何做到這一點(diǎn)的實(shí)現(xiàn)細(xì)節(jié)。這個(gè)博客對(duì)我來(lái)說(shuō)是一個(gè)很好的回顧,所以我會(huì)暫時(shí)回顧一下。在開(kāi)始之前,讓我們簡(jiǎn)要了解一下“部署 K8s Sysbench 基準(zhǔn)測(cè)試作業(yè)”工作流程。

    name: Benchmark Latency
    on: repository_dispatch: types: [ benchmark-latency ]
    jobs: performance: runs-on: ubuntu-22.04 name: Benchmark Performance strategy: matrix: dolt_fmt: [ "__DOLT__" ] steps: - name: Checkout uses: actions/checkout@v3 - uses: azure/[email protected] with: version: 'v1.23.6' - name: Install aws-iam-authenticator run: | curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.8/2020-09-18/bin/linux/amd64/aws-iam-authenticator && \ chmod +x ./aws-iam-authenticator && \ sudo cp ./aws-iam-authenticator /usr/local/bin/aws-iam-authenticator aws-iam-authenticator version - name: Configure AWS Credentials uses: aws-actions/[email protected] with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 - name: Create and Auth kubeconfig run: | echo "$CONFIG" > kubeconfig KUBECONFIG=kubeconfig kubectl config set-credentials github-actions-dolt --exec-api-version=client.authentication.k8s.io/v1alpha1 --exec-command=aws-iam-authenticator --exec-arg=token --exec-arg=-i --exec-arg=eks-cluster-1 KUBECONFIG=kubeconfig kubectl config set-context github-actions-dolt-context --cluster=eks-cluster-1 --user=github-actions-dolt --namespace=performance-benchmarking KUBECONFIG=kubeconfig kubectl config use-context github-actions-dolt-context env: CONFIG: ${{ secrets.CORP_KUBECONFIG }} - name: Create Sysbench Performance Benchmarking K8s Job run: ./.github/scripts/performance-benchmarking/run-benchmarks.sh env: FROM_SERVER: ${{ github.event.client_payload.from_server }} FROM_VERSION: ${{ github.event.client_payload.from_version }} TO_SERVER: ${{ github.event.client_payload.to_server }} TO_VERSION: ${{ github.event.client_payload.to_version }} MODE: ${{ github.event.client_payload.mode }} ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }} ACTOR: ${{ github.event.client_payload.actor }} ACTOR_EMAIL: ${{ github.event.client_payload.actor_email }} REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} KUBECONFIG: "./kubeconfig" INIT_BIG_REPO: ${{ github.event.client_payload.init_big_repo }} NOMS_BIN_FORMAT: ${{ matrix.dolt_fmt }} TEMPLATE_SCRIPT: ${{ github.event.client_payload.template_script }} - name: Create TPCC Performance Benchmarking K8s Job run: ./.github/scripts/performance-benchmarking/run-benchmarks.sh env: FROM_SERVER: ${{ github.event.client_payload.from_server }} FROM_VERSION: ${{ github.event.client_payload.from_version }} TO_SERVER: ${{ github.event.client_payload.to_server }} TO_VERSION: ${{ github.event.client_payload.to_version }} MODE: ${{ github.event.client_payload.mode }} ISSUE_NUMBER: ${{ github.event.client_payload.issue_number }} ACTOR: ${{ github.event.client_payload.actor }} ACTOR_EMAIL: ${{ github.event.client_payload.actor_email }} REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} KUBECONFIG: "./kubeconfig" INIT_BIG_REPO: ${{ github.event.client_payload.init_big_repo }} NOMS_BIN_FORMAT: ${{ matrix.dolt_fmt }} WITH_TPCC: "true" TEMPLATE_SCRIPT: ${{ github.event.client_payload.template_script }}

    這個(gè)工作流程雖然簡(jiǎn)短,但有點(diǎn)忙碌,它根據(jù) K8s 集群對(duì) kubectl 客戶(hù)端進(jìn)行身份驗(yàn)證,我們?cè)谄渲羞\(yùn)行 Sysbench 基準(zhǔn)測(cè)試,并提供運(yùn)行名為 run-benchmarks.sh 的腳本所需的環(huán)境變量。該腳本使用這些變量的值編寫(xiě) K8s 作業(yè)配置文件,然后應(yīng)用它,從而在我們的 K8s 集群中部署基準(zhǔn)測(cè)試作業(yè)。

    此時(shí),您可能想知道為什么我們選擇在 K8s 集群中運(yùn)行 Dolt 基準(zhǔn)測(cè)試,而不是僅僅使用 GitHub Actions 及其運(yùn)行程序來(lái)對(duì) Dolt 進(jìn)行基準(zhǔn)測(cè)試。這有幾個(gè)原因。

    第一,GitHub 托管的運(yùn)行程序有非常具體的限制,至少對(duì)于免費(fèi)層來(lái)說(shuō)是這樣,并且為了對(duì)我們的數(shù)據(jù)庫(kù)進(jìn)行基準(zhǔn)測(cè)試,我們不一定希望受到這些限制。

    此外,當(dāng)我們進(jìn)行基準(zhǔn)測(cè)試運(yùn)行時(shí),我們無(wú)法知道或控制 GitHub 托管的運(yùn)行器上正在運(yùn)行哪些其他進(jìn)程或軟件,這可能會(huì)以不可預(yù)測(cè)的方式對(duì)運(yùn)行結(jié)果產(chǎn)生負(fù)面影響。

    雖然當(dāng)然可以在 GitHub Actions 中使用自托管運(yùn)行器來(lái)規(guī)避這兩個(gè)問(wèn)題,在這種情況下,我們可以?xún)H使用 GitHub Actions 對(duì) Dolt 進(jìn)行基準(zhǔn)測(cè)試,但我們已經(jīng)在 K8s 集群中提供了可輕松配置的主機(jī),因此我們選擇只需使用它們即可。

    事實(shí)上, applying 我們的 K8s 基準(zhǔn)測(cè)試作業(yè)將使用 K8s 集群自動(dòng)縮放器配置一個(gè)新的基準(zhǔn)測(cè)試主機(jī),這非??帷?/span>

    無(wú)論如何,暫時(shí)回到我們的圖表,我們看到在驗(yàn)證 kubectl 客戶(hù)端之后,“部署 Sysbench 基準(zhǔn)測(cè)試作業(yè)”工作流程部署 K8s 作業(yè),并且該流程移動(dòng)到 K8s 上下文,并且“K8s Sysbench 基準(zhǔn)測(cè)試作業(yè)”正在運(yùn)行。

    現(xiàn)在從技術(shù)上講,原始 Dolt 發(fā)布過(guò)程的這一部分更多的是發(fā)布后步驟。在 GitHub 上創(chuàng)建新的 Dolt 版本不需要運(yùn)行基準(zhǔn)測(cè)試作業(yè),它只是為我們的團(tuán)隊(duì)提供有關(guān)該版本延遲的報(bào)告。但重要的是要了解我們最初發(fā)布過(guò)程的這一部分,這樣我們對(duì) Dolt 發(fā)布過(guò)程的 pgo 更新才會(huì)更有意義,但稍后會(huì)詳細(xì)介紹。

    在該圖的 K8s 上下文中,我們可以看到基準(zhǔn)測(cè)試作業(yè)執(zhí)行了幾個(gè)步驟。它根據(jù)提供的提交 SHA 構(gòu)建 Dolt 二進(jìn)制文件。在本例中,它是來(lái)自 Dolt main HEAD 的 SHA。

    接下來(lái),它針對(duì)已編譯的 Dolt 版本運(yùn)行 Sysbench 測(cè)試,然后將 Sysbench 運(yùn)行結(jié)果上傳到 AWS S3 存儲(chǔ)桶。最后,它觸發(fā)位于 Dolt 存儲(chǔ)庫(kù)中的不同 GitHub Actions 工作流程,稱(chēng)為“電子郵件團(tuán)隊(duì)”工作流程。

    為了執(zhí)行所有這些基準(zhǔn)測(cè)試以及上傳和觸發(fā),我們編寫(xiě)了一個(gè)內(nèi)部工具,可用于針對(duì) MySQL 版本對(duì) Dolt 版本進(jìn)行基準(zhǔn)測(cè)試。

    該工具使用我們?cè)?Dolt 存儲(chǔ)庫(kù)中維護(hù)的一些庫(kù)代碼,但我將提供內(nèi)部工具和庫(kù)代碼中的一些相關(guān)片段,以便您了解我們?nèi)绾螌?shí)現(xiàn)這些代碼來(lái)運(yùn)行基準(zhǔn)測(cè)試。

    我們的內(nèi)部基準(zhǔn)測(cè)試工具代碼本質(zhì)上是以下 go 函數(shù):

    func compare(ctx context.Context,  fromServer,  toServer runner.ServerType,  fromVersion,  toVersion,  fromProfile,  toProfile,  dir,  doltCommand,  doltgresCommand,  mysqlExec,  mysqlProtocol,  mysqlSocketPath,  postgresExec,  initDbExec,  nomsBinFormat,  resultsDir,  resultsPrefix,  resultsFilename,  scriptDir,  schema,  outputFormat string,  defaultRuns int,  initBigRepo,  useDoltHubLuaScriptsRepo,  writeResultsToFile bool,  queries []string) (string, error) {  config := benchmark.NewComparisonBenchmarkingConfig(    fromServer,    toServer,    fromVersion,    toVersion,    fromProfile,    toProfile,    dir,    doltCommand,    doltgresCommand,    mysqlExec,    mysqlProtocol,    mysqlSocketPath,    postgresExec,    initDbExec,    nomsBinFormat,    scriptDir,    defaultRuns,    initBigRepo,    useDoltHubLuaScriptsRepo)
    sr := benchmark.NewSysbenchComparer(config)
    err := sr.Run(ctx) if err != nil { return "", err }
    fromServerConfig, err := config.GetFromServerConfig(ctx) if err != nil { return "", err }
    toServerConfig, err := config.GetToServerConfig(ctx) if err != nil { return "", err }
    resultsDbName := fmt.Sprintf("sysbench-%s", benchmark.ComparisonDbFilename)
    db := benchmark.NewSqlite3ResultsDb(fromServerConfig, toServerConfig, dir, schema, resultsDir, resultsPrefix, resultsFilename, resultsDbName, outputFormat, queries, writeResultsToFile) uploadDir, err := db.QueryResults(ctx) if err != nil { return "", err }
    return uploadDir, nil}

    compare 用于將一個(gè)數(shù)據(jù)庫(kù)版本與另一個(gè)版本的 Sysbench 結(jié)果進(jìn)行比較。從函數(shù)的參數(shù)可以看出,這個(gè)工具不僅用于Dolt和MySQL,還用于對(duì)我們最新產(chǎn)品DoltgreSQL及其競(jìng)爭(zhēng)對(duì)手PostgreSQL進(jìn)行基準(zhǔn)測(cè)試。

    compare 函數(shù)引用 fromServerConfig ,這是“from”數(shù)據(jù)庫(kù)服務(wù)器的配置,并引用 toServerConfig ,這是“from”數(shù)據(jù)庫(kù)服務(wù)器的配置“到”數(shù)據(jù)庫(kù)服務(wù)器。從語(yǔ)義上講,這里該工具將并排比較“源”數(shù)據(jù)庫(kù)和“目標(biāo)”數(shù)據(jù)庫(kù),以便于分析。在 Dolt 發(fā)布過(guò)程中,MySQL 將是“源”服務(wù)器,Dolt 將是“目標(biāo)”服務(wù)器。

    您可能還注意到,我們?cè)诖斯ぞ咧惺褂?sqlite3,如 benchmark.NewSqlite3ResultsDb 所引用,它是 Dolt v1.0.0 之前的遺留工件,但它在這里仍然具有一些獨(dú)特的價(jià)值。

    在后臺(tái),使用 sr.Run() 運(yùn)行基準(zhǔn)測(cè)試后,我們將結(jié)果加載到 sqlite3 數(shù)據(jù)庫(kù)中,并對(duì)其運(yùn)行一些查詢(xún)以獲得每個(gè)數(shù)據(jù)庫(kù)服務(wù)器的比較結(jié)果。與 Dolt 相比,使用 sqlite3 的一個(gè)好處是, sqlite3 使用簡(jiǎn)單的標(biāo)志以多種格式返回查詢(xún)輸出,如 --html ,這使我們不必編寫(xiě)查詢(xún)結(jié)果轉(zhuǎn)換邏輯。

    從 db.QueryResults() 返回的 uploadDir 包含比較查詢(xún)的結(jié)果以及要上傳到 S3 的 sqlite3 數(shù)據(jù)庫(kù)的副本。這些結(jié)果很快就會(huì)被“電子郵件團(tuán)隊(duì)”工作流程下載,我們很快就會(huì)看到。

    當(dāng)實(shí)際運(yùn)行 Sysbench 基準(zhǔn)測(cè)試時(shí), benchmark.NewSysbenchComparer(config) 只是我們?cè)?Dolt 存儲(chǔ)庫(kù)中維護(hù)的一些基準(zhǔn)測(cè)試庫(kù)代碼中的 Run 函數(shù)的包裝結(jié)構(gòu)。

    func Run(config *Config) error {  err := config.Validate()  if err != nil {    return err  }
    ctx := context.Background()
    err = sysbenchVersion(ctx) if err != nil { return err }
    cwd, err := os.Getwd() if err != nil { return err }
    for _, serverConfig := range config.Servers { var results Results var b Benchmarker switch serverConfig.Server { case Dolt: fmt.Println("Running dolt sysbench tests") b = NewDoltBenchmarker(cwd, config, serverConfig) case Doltgres: fmt.Println("Running doltgres sysbench tests") b = NewDoltgresBenchmarker(cwd, config, serverConfig) case MySql: fmt.Println("Running mysql sysbench tests") b = NewMysqlBenchmarker(cwd, config, serverConfig) case Postgres: fmt.Println("Running postgres sysbench tests") b = NewPostgresBenchmarker(cwd, config, serverConfig) default: panic(fmt.Sprintf("unexpected server type: %s", serverConfig.Server)) }
    results, err = b.Benchmark(ctx) if err != nil { return err }
    fmt.Printf("Successfuly finished %s\n", serverConfig.Server)
    err = WriteResults(serverConfig, results) if err != nil { return err }
    fmt.Printf("Successfuly wrote results for %s\n", serverConfig.Server) } return nil}

    此函數(shù)根據(jù)它看到的服務(wù)器類(lèi)型創(chuàng)建一個(gè) Benchmarker ,然后調(diào)用 Benchmark() ,后者針對(duì)該服務(wù)器運(yùn)行 Sysbench 測(cè)試。下面是 Dolt Benchmarker 的 Benchmark() 實(shí)現(xiàn)的示例:

    func (b *doltBenchmarkerImpl) Benchmark(ctx context.Context) (Results, error) {  err := b.checkInstallation(ctx)  if err != nil {    return nil, err  }
    err = b.updateGlobalConfig(ctx) if err != nil { return nil, err }
    testRepo, err := b.initDoltRepo(ctx) if err != nil { return nil, err }
    serverParams, err := b.serverConfig.GetServerArgs() if err != nil { return nil, err }
    server := NewServer(ctx, testRepo, b.serverConfig, syscall.SIGTERM, serverParams) err = server.Start(ctx) if err != nil { return nil, err }
    tests, err := GetTests(b.config, b.serverConfig, nil) if err != nil { return nil, err }
    results := make(Results, 0) for i := 0; i < b.config.Runs; i++ { for _, test := range tests { tester := NewSysbenchTester(b.config, b.serverConfig, test, stampFunc) r, err := tester.Test(ctx) if err != nil { server.Stop(ctx) return nil, err } results = append(results, r) } }
    err = server.Stop(ctx) if err != nil { return nil, err }
    return results, os.RemoveAll(testRepo)}

    在 Benchmark() 調(diào)用期間,此實(shí)現(xiàn)將檢查 Dolt 安裝,更新一些全局 Dolt 配置,獲取用于啟動(dòng) Dolt SQL 服務(wù)器的參數(shù),啟動(dòng)服務(wù)器,獲取將要運(yùn)行的 Sysbench 測(cè)試,然后通過(guò)調(diào)用 tester.Test() 運(yùn)行這些測(cè)試。

    完成后,它返回 results 并清除寫(xiě)入磁盤(pán)的內(nèi)容。

    而且,正如我們?cè)趦?nèi)部工具的 compare 功能中所看到的,這些結(jié)果被加載到 sqlite3 中并上傳到 S3,以便可以通過(guò)電子郵件發(fā)送給 DoltHub 團(tuán)隊(duì)。但是,我們?nèi)匀蝗鄙僖徊?,即在?nèi)部基準(zhǔn)測(cè)試工具完成上傳結(jié)果后,通過(guò) repository_dispatch 事件觸發(fā)“電子郵件團(tuán)隊(duì)”工作流程。

    因此,我們內(nèi)部工具的最后一部分包括:

    err := d.DispatchEmailReportEvent(ctx, *toVersion, *nomsBinFormat, *bucket, key)if err != nil {    log.Fatal(err)}

    DispatchEmailReportEvent() 方法位于我們編寫(xiě)的 Dispatcher 接口上。它只是向 GitHub Actions Workflow REST API 發(fā)出 HTTP 請(qǐng)求,該 API 發(fā)出 repository_dispatch 事件,觸發(fā)“電子郵件團(tuán)隊(duì)”工作流運(yùn)行。那么讓我們接下來(lái)看看。

    與“部署 K8s Sysbench 基準(zhǔn)測(cè)試作業(yè)”工作流程一樣,“電子郵件團(tuán)隊(duì)”工作流程除了 Dolt 發(fā)布流程之外還被多個(gè)流程使用,因此這就是我們使用 repository_dispatch 事件觸發(fā)它的原因。工作流程文件如下:

    name: Email Team Members
    on: repository_dispatch: types: [ email-report ]
    jobs: email-team: runs-on: ubuntu-22.04 name: Email Team Members steps: - uses: actions/checkout@v3 - name: Configure AWS Credentials uses: aws-actions/[email protected] with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 - name: Get Results id: get-results run: aws s3api get-object --bucket="$BUCKET" --key="$KEY" results.log env: KEY: ${{ github.event.client_payload.key }} BUCKET: ${{ github.event.client_payload.bucket }} - name: Get Addresses id: get-addresses run: | addresses="$TEAM" if [ ! -z "$RECIPIENT" ]; then addresses="[\"$RECIPIENT\"]" fi echo "addresses=$addresses" >> $GITHUB_OUTPUT env: RECIPIENT: ${{ github.event.client_payload.email_recipient }} TEAM: '["${{ secrets.PERF_REPORTS_EMAIL_ADDRESS }}"]' - name: Send Email uses: ./.github/actions/ses-email-action with: template: ${{ github.event.client_payload.template }} region: us-west-2 version: ${{ github.event.client_payload.version }} format: ${{ github.event.client_payload.noms_bin_format }} toAddresses: ${{ steps.get-addresses.outputs.addresses }} dataFile: ${{ format('{0}/results.log', github.workspace) }}

    如圖所示,此工作流程的摘要是下載 Dolt 版本的 Sysbench 結(jié)果,然后通過(guò)電子郵件將其發(fā)送給我們的團(tuán)隊(duì);沒(méi)什么瘋狂的。

    這就是 Dolt 的發(fā)布過(guò)程?;蛘哌@就是 Dolt 的發(fā)布過(guò)程。現(xiàn)在我將回顧一下我們?nèi)绾胃麓肆鞒桃栽诎l(fā)布時(shí)開(kāi)始構(gòu)建 Dolt 的 pgo 二進(jìn)制文件。

    PGO 通過(guò) GitHub Actions 發(fā)布

    對(duì)于那些不熟悉 pgo 構(gòu)建的人,他們需要 -pgo 標(biāo)志以及在 go build 命令期間提供的 Golang 配置文件的路徑。這部分其實(shí)很簡(jiǎn)單。但在此之前,您需要?jiǎng)?chuàng)建要用于優(yōu)化構(gòu)建的配置文件,這需要我們更新一些基準(zhǔn)庫(kù)代碼和內(nèi)部工具代碼,以便它們既可以生成配置文件并接受配置文件作為輸入。讓我更詳細(xì)地解釋一下。

    在我們的基準(zhǔn)測(cè)試庫(kù)代碼中,我們使用另一個(gè)名為 dolt_builder 的 Dolt 實(shí)用程序來(lái)實(shí)際從源代碼構(gòu)建 Dolt 二進(jìn)制文件。要使用此工具,您只需提供要從中構(gòu)建 Dolt 的提交 SHA 或標(biāo)記,它就會(huì)為您構(gòu)建它。因此,我們?cè)诤芏嗟胤绞褂眠@個(gè)工具來(lái)輕松地同時(shí)構(gòu)建多個(gè)版本的 Dolt。

    因此,我們做的第一件事就是更新這個(gè)工具以接受可用于構(gòu)建 Dolt 的 Golang 配置文件:

    // goBuild builds the dolt binary and returns the path to the binaryfunc goBuild(ctx context.Context, source, dest, profilePath string) (string, error) {  goDir := filepath.Join(source, "go")  doltFileName := "dolt"  if runtime.GOOS == "windows" {    doltFileName = "dolt.exe"  }
    args := make([]string, 0) args = append(args, "build")
    if profilePath != "" { args = append(args, fmt.Sprintf("-pgo=%s", profilePath)) }
    toBuild := filepath.Join(dest, doltFileName) args = append(args, "-o", toBuild, filepath.Join(goDir, "cmd", "dolt"))
    build := ExecCommand(ctx, "go", args...) build.Dir = goDir err := build.Run() if err != nil { return "", err } return toBuild, nil}

    我們做的下一件事是更新基準(zhǔn)庫(kù)代碼以在“分析”模式下運(yùn)行。在默認(rèn)模式下,如上所述,此代碼調(diào)用 Benchmark() 并返回結(jié)果。在新的“分析”模式中,代碼在 Profiler 接口上調(diào)用 Profile() :

    ...    case Dolt:      // handle a profiling run      sc, ok := serverConfig.(ProfilingServerConfig)      if ok {        if string(sc.GetServerProfile()) != "" {          fmt.Println("Profiling dolt while running sysbench tests")          p := NewDoltProfiler(cwd, config, sc)          return p.Profile(ctx)        }      }...

    Profile() 的工作方式與 Benchmark() 類(lèi)似,但會(huì)創(chuàng)建一個(gè)在運(yùn)行 Sysbench 基準(zhǔn)測(cè)試時(shí)獲取的 golang 配置文件。這使我們能夠輕松生成可在新發(fā)布流程中使用的 Dolt 配置文件。

    我們還更新了此庫(kù)代碼以接受配置文件作為輸入。這樣我們就可以向它提供一個(gè)配置文件,它又將其提供給 dolt_builder 以創(chuàng)建 pgo 二進(jìn)制文件,然后運(yùn)行 Sysbench 并輸出這些結(jié)果。

    為了澄清,我們基本上更新了這個(gè)庫(kù)代碼,以便我們可以在一種模式下運(yùn)行它來(lái)生成 Golang 配置文件,然后在默認(rèn)模式下運(yùn)行它以獲得正常的基準(zhǔn)測(cè)試結(jié)果,但它也接受 Golang 配置文件作為輸入,并用它來(lái)構(gòu)建 Dolt 和 go build -pgo 。希望這對(duì)你來(lái)說(shuō)有意義,因?yàn)閷?duì)我來(lái)說(shuō)描述有點(diǎn)棘手??。

    接下來(lái),我們需要更新使用所有這些庫(kù)代碼的內(nèi)部工具,以擁有“分析”模式并接受 Golang 配置文件作為輸入。我們對(duì)新發(fā)布流程的計(jì)劃是在分析模式下運(yùn)行內(nèi)部工具一次,以創(chuàng)建 Golang 配置文件。然后,在默認(rèn)模式下再次運(yùn)行內(nèi)部工具,但向其提供 Golang 配置文件,這將針對(duì) pgo 構(gòu)建的 Dolt 生成基準(zhǔn)測(cè)試結(jié)果。

    因此,與 compare 函數(shù)一樣,我們能夠?qū)?nbsp;profile 函數(shù)添加到生成 Dolt 版本的 Golang cpu 配置文件的內(nèi)部工具中。

    func profile(ctx context.Context, dir, profileDir, resultsDir, resultsPrefix, version, profile, doltCommand, scriptsDir string, useDoltHubLuaScriptsRepo bool) (string, error) {  config := benchmark.NewProfilingConfig(    dir,    profileDir,    version,    profile,    doltCommand,    scriptsDir,    useDoltHubLuaScriptsRepo)  toUpload := filepath.Join(resultsDir, resultsPrefix)  sr := benchmark.NewSysbenchProfiler(config, toUpload, profileDir)  return toUpload, sr.Run(ctx)}

    此函數(shù)像 compare 一樣返回其 toUpload 目錄,但這次它包含要上傳到 S3 的配置文件。

    對(duì)代碼進(jìn)行這些更改后,我們準(zhǔn)備更新 GitHub Actions 工作流程以開(kāi)始創(chuàng)建 Dolt 的 pgo 版本。下面的圖表顯示了使用 GitHub Actions 的新 Dolt 發(fā)布流程。

    從新的發(fā)布工作流程圖中可以看到,我們添加了一些新的 GitHub Actions 工作流程,但它們與原始工作流程類(lèi)似。讓我們更仔細(xì)地看看它們。

    對(duì)于新的 Dolt 發(fā)布流程,我們運(yùn)行的第一個(gè)工作流程稱(chēng)為“發(fā)布 Dolt(配置文件)”,實(shí)際上并不創(chuàng)建 GitHub 版本或構(gòu)建任何 Dolt 二進(jìn)制文件。

    相反,它的唯一功能是觸發(fā)第二個(gè)工作流程,稱(chēng)為“部署 K8s Sysbench 分析作業(yè)”。

    name: Release Dolt (Profile)
    on: workflow_dispatch: inputs: version: description: 'SemVer format release tag, i.e. 0.24.5' required: true
    jobs: format-version: runs-on: ubuntu-22.04 outputs: version: ${{ steps.format_version.outputs.version }} steps: - name: Format Input id: format_version run: | version="${{ github.event.inputs.version }}" if [[ $version == v* ]]; then version="${version:1}" fi echo "version=$version" >> $GITHUB_OUTPUT
    profile-benchmark-dolt: runs-on: ubuntu-22.04 needs: format-version name: Trigger Benchmark Profile K8s Workflows steps: - uses: actions/checkout@v4 with: ref: main - name: Get sha id: get_sha run: | sha=$(git rev-parse --short HEAD) echo "sha=$sha" >> $GITHUB_OUTPUT - uses: peter-evans/repository-dispatch@v3 with: token: ${{ secrets.REPO_ACCESS_TOKEN }} event-type: profile-dolt client-payload: '{"from_version": "${{ steps.get_sha.outputs.sha }}", "future_version": "${{ needs.format-version.outputs.version }}", "mode": "release", "actor": "${{ github.actor }}", "actor_email": "[email protected]", "template_script": "./.github/scripts/performance-benchmarking/get-dolt-profile-job-json.sh"}'

    “部署 K8s Sysbench 分析作業(yè)”的工作原理與“部署 K8s Sysbench 基準(zhǔn)測(cè)試作業(yè)”幾乎相同,不同之處在于它將以“分析”模式運(yùn)行的基準(zhǔn)測(cè)試作業(yè)部署到 K8s 集群,以便我們使用 HEAD 的 。

    name: Profile Dolt while Benchmarking
    on: repository_dispatch: types: [ profile-dolt ]
    jobs: performance: runs-on: ubuntu-22.04 name: Profile Dolt while Benchmarking steps: - name: Checkout uses: actions/checkout@v4 - uses: azure/setup-kubectl@v4 with: version: 'v1.23.6' - name: Install aws-iam-authenticator run: | curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.8/2020-09-18/bin/linux/amd64/aws-iam-authenticator && \ chmod +x ./aws-iam-authenticator && \ sudo cp ./aws-iam-authenticator /usr/local/bin/aws-iam-authenticator aws-iam-authenticator version - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: us-west-2 - name: Create and Auth kubeconfig run: | echo "$CONFIG" > kubeconfig KUBECONFIG=kubeconfig kubectl config set-credentials github-actions-dolt --exec-api-version=client.authentication.k8s.io/v1alpha1 --exec-command=aws-iam-authenticator --exec-arg=token --exec-arg=-i --exec-arg=eks-cluster-1 KUBECONFIG=kubeconfig kubectl config set-context github-actions-dolt-context --cluster=eks-cluster-1 --user=github-actions-dolt --namespace=performance-benchmarking KUBECONFIG=kubeconfig kubectl config use-context github-actions-dolt-context env: CONFIG: ${{ secrets.CORP_KUBECONFIG }} - name: Create Profile Benchmarking K8s Job run: ./.github/scripts/performance-benchmarking/run-benchmarks.sh env: PROFILE: "true" FUTURE_VERSION: ${{ github.event.client_payload.future_version }} FROM_VERSION: ${{ github.event.client_payload.from_version }} MODE: ${{ github.event.client_payload.mode }} ACTOR: ${{ github.event.client_payload.actor }} ACTOR_EMAIL: ${{ github.event.client_payload.actor_email }} REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }} KUBECONFIG: "./kubeconfig" INIT_BIG_REPO: ${{ github.event.client_payload.init_big_repo }} NOMS_BIN_FORMAT: "__DOLT__" TEMPLATE_SCRIPT: ${{ github.event.client_payload.template_script }}

    一旦基準(zhǔn)測(cè)試 K8s 作業(yè)在“分析”模式下運(yùn)行,我們就可以在更新的圖表中看到它執(zhí)行的步驟。我們還看到此作業(yè)的輸出是一個(gè)新的 Golang 配置文件,已上傳到 S3,可供我們流程的其余步驟用于創(chuàng)建 pgo 構(gòu)建。

    在分析 K8s 作業(yè)結(jié)束時(shí),上傳配置文件后,它會(huì)觸發(fā)“Release Dolt”工作流程。這個(gè)工作流程的工作原理與原來(lái)的“Release Dolt”工作流程基本相同,只是它的第一步是下載分析作業(yè)上傳的 Golang 配置文件。

    ...  create-pgo-release:    needs: format-version    runs-on: ubuntu-22.04    name: Release PGO Dolt    outputs:      release_id: ${{ steps.create_release.outputs.id }}    steps:      - uses: actions/checkout@v4        with:          ref: main      - name: Set up Go 1.x        uses: actions/setup-go@v5        with:          go-version-file: go/go.mod      - name: Configure AWS Credentials        uses: aws-actions/configure-aws-credentials@v4        with:          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}          aws-region: us-west-2      - name: Get Results        id: get-results        run: aws s3api get-object --bucket="$BUCKET" --key="$KEY" dolt-cpu-profile.pprof        env:          KEY: ${{ github.event.inputs.profile_key || github.event.client_payload.profile_key }}          BUCKET: ${{ github.event.inputs.profile_bucket || github.event.client_payload.bucket }}...

    然后,它將下載的配置文件(此處稱(chēng)為 dolt-cpu-profile.pprof )提供給 buildbinaries.sh 腳本,該腳本運(yùn)行 go build -pgo=./dolt-cpu-profile.pprof ,編譯新的 Dolt 二進(jìn)制文件。然后,與工作流程的原始版本一樣,它創(chuàng)建一個(gè) GitHub 版本并將這些二進(jìn)制文件作為版本資產(chǎn)上傳。

    在完成之前,此工作流程中的最后一項(xiàng)作業(yè)將啟動(dòng)另一項(xiàng)基準(zhǔn)測(cè)試 K8s 作業(yè),只是這次為該作業(yè)提供用于構(gòu)建 Dolt 二進(jìn)制文件的 Golang 配置文件的 S3 密鑰。

    ...  trigger-performance-benchmark-email:    needs: [format-version, create-pgo-release]    runs-on: ubuntu-22.04    steps:      - name: Trigger Performance Benchmarks        uses: peter-evans/repository-dispatch@v3        with:          token: ${{ secrets.REPO_ACCESS_TOKEN }}          event-type: release-dolt          client-payload: '{"version": "${{ needs.format-version.outputs.version }}", "actor": "${{ github.actor }}", "profile_key": "${{ github.event.inputs.profile_key || github.event.client_payload.profile_key }}"}'

    這會(huì)再次將基準(zhǔn)測(cè)試作業(yè)部署到我們的 K8s 集群,但現(xiàn)在該作業(yè)將從 S3 下載 Golang 配置文件,并使用它構(gòu)建 Dolt 的 pgo 二進(jìn)制文件,以用于基準(zhǔn)測(cè)試和生成結(jié)果。

    從 K8s 上下文中的圖表中我們可以看到,第二個(gè)基準(zhǔn)測(cè)試作業(yè)的最后一步啟動(dòng)了“電子郵件團(tuán)隊(duì)”工作流程,以便我們的團(tuán)隊(duì)獲得現(xiàn)在 pgo 的 Dolt 的基準(zhǔn)測(cè)試結(jié)果。

    我們已經(jīng)做到了!我們現(xiàn)在正在發(fā)布 Dolt 的 pgo 版本。

    結(jié)論

    正如您所看到的,更新發(fā)布過(guò)程以生成 pgo 二進(jìn)制文件涉及一些復(fù)雜性,至少對(duì)我們來(lái)說(shuō)是這樣。但我們所看到的性能提升絕對(duì)值得付出努力。

    我希望您發(fā)現(xiàn)這對(duì)您自己的努力有幫助,我們鼓勵(lì)您也嘗試更新您的版本。如果您愿意,我們很想聽(tīng)聽(tīng)。過(guò)來(lái)并在我們的 Discord 上分享您的經(jīng)驗(yàn)。


    瀏覽 172
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)
    評(píng)論
    圖片
    表情
    推薦
    點(diǎn)贊
    評(píng)論
    收藏
    分享

    手機(jī)掃一掃分享

    分享
    舉報(bào)

    <kbd id="5sdj3"></kbd>
    <th id="5sdj3"></th>

  • <dd id="5sdj3"><form id="5sdj3"></form></dd>
    <td id="5sdj3"><form id="5sdj3"><big id="5sdj3"></big></form></td><del id="5sdj3"></del>

  • <dd id="5sdj3"></dd>
    <dfn id="5sdj3"></dfn>
  • <th id="5sdj3"></th>
    <tfoot id="5sdj3"><menuitem id="5sdj3"></menuitem></tfoot>

  • <td id="5sdj3"><form id="5sdj3"><menu id="5sdj3"></menu></form></td>
  • <kbd id="5sdj3"><form id="5sdj3"></form></kbd>
    操逼毛片视频 | 一级A毛片2021 | 青青草成人免费视频 | 久操视频在线观看 | 欧美黄色小视频 |