Skip to content
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

perf: ⚡️ run apply namespaces in apply pipeline concurrently #644

Merged
merged 1 commit into from
Oct 17, 2024

Conversation

jaskaransarkaria
Copy link
Contributor

@jaskaransarkaria jaskaransarkaria commented Oct 16, 2024

Continue chunking and batching namespaces across different pipelines but within those pipelines run the applies concurrently.

This PR covers:

  • if the pipeline fails a namespace apply, then fail silently but collect all the errored namespaces and log them so we can inspect them if we need
  • rewrite the namespace apply so we can take advantage of go routines and speed up apply pipelines
  • remove duplicate call to plan
  • explicitly pass a namespace arg to destroyNamespace, planNamespace and applyNamespace to fix a bug where incorrectly structs were accessed during parallel runs
  • move contains fn from deleteutils to util
  • project test coverage increased from 68.5% -> 72.0%

performance results:

https://concourse.cloud-platform.service.justice.gov.uk/teams/main/pipelines/environments-live/jobs/apply-namespace-parallel-test/builds/2 (one errored namespace can be found at the bottom of the log)

duration	34m 43s Which cuts the build time in more than half (compared to the same run on current apply live 1h 20m)

build peaked (running on worker-3) Another apply pipeline was running at the same time on the same worker, but another was running on worker 1 at the same time

concourse-worker-0               19m          3170Mi
concourse-worker-1               18m          5180Mi
concourse-worker-2               566m         3791Mi
concourse-worker-3               3418m        5885Mi

Note current pod limits are (if we raise the limits go will utilise those extra resources):

    Limits:
      cpu:     4
      memory:  8Gi
    Requests:
      cpu:     1
      memory:  1Gi

@@ -157,12 +157,6 @@ func (m *ApplierImpl) TerraformInitAndPlan(namespace, directory string) (*tfjson
return nil, "", errors.New("unable to do Terraform Plan: " + err.Error())
}

// ignore if any changes or no changes.
_, err = terraform.Plan(context.Background())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated plan see line 152 above

return err
}
done := make(chan bool)
defer close(done)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

close the channel which cascades down through the child go routines and in turn closes them to prevent memory leaks

done := make(chan bool)
defer close(done)

chunkStream := util.Generator(done, chunkFolder...)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

convert array into a channel


routineResults := a.parallelApplyNamespace(done, chunkStream)

results := util.FanIn(done, routineResults...)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

combine multiple channel results back into a single channel

results := make(chan string)
go func() {
defer close(results)
for dir := range dirStream {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a new go routine run each apply for each namespace

return nil
}

func (a *Apply) parallelApplyNamespace(done <-chan bool, dirStream <-chan string) []<-chan string {
numRoutines := runtime.NumCPU()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run as many go routines as we have cores, this proves to be a conservative number of routines because of how lightweight and cheap they are. We should monitor performance in concourse and adjust here if necessary.

@jaskaransarkaria jaskaransarkaria force-pushed the parallelise-apply-pipe branch 2 times, most recently from 8090894 to 6db65c3 Compare October 17, 2024 08:48
@jaskaransarkaria jaskaransarkaria merged commit 69d5605 into main Oct 17, 2024
22 checks passed
@jaskaransarkaria jaskaransarkaria deleted the parallelise-apply-pipe branch October 17, 2024 14:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants