Skip to content

Commit

Permalink
Reduce memory utilization in downstream projects creating multiple Al…
Browse files Browse the repository at this point in the history
…ertmanager instances (#3114)

* Reduce memory utilization in downstream projects creating multiple Alertmanager instances

Signed-off-by: Marco Pracucci <marco@pracucci.com>
  • Loading branch information
pracucci committed Oct 26, 2022
1 parent 28c3df0 commit 33bba95
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 12 deletions.
21 changes: 13 additions & 8 deletions api/v2/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

"github.com/go-kit/log"
"github.com/go-kit/log/level"
"github.com/go-openapi/analysis"
"github.com/go-openapi/loads"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
Expand Down Expand Up @@ -101,7 +102,7 @@ func NewAPI(
}

// Load embedded swagger file.
swaggerSpec, err := getSwaggerSpec()
swaggerSpec, swaggerSpecAnalysis, err := getSwaggerSpec()
if err != nil {
return nil, err
}
Expand All @@ -113,7 +114,9 @@ func NewAPI(
// the API itself via RoutesHandler. See:
// https://github.com/go-swagger/go-swagger/issues/1779
openAPI.Middleware = func(b middleware.Builder) http.Handler {
return middleware.Spec("", swaggerSpec.Raw(), openAPI.Context().RoutesHandler(b))
// Manually create the context so that we can use the singleton swaggerSpecAnalysis.
swaggerContext := middleware.NewRoutableContextWithAnalyzedSpec(swaggerSpec, swaggerSpecAnalysis, openAPI, nil)
return middleware.Spec("", swaggerSpec.Raw(), swaggerContext.RoutesHandler(b))
}

openAPI.AlertGetAlertsHandler = alert_ops.GetAlertsHandlerFunc(api.getAlertsHandler)
Expand Down Expand Up @@ -674,29 +677,31 @@ func parseFilter(filter []string) ([]*labels.Matcher, error) {
}

var (
swaggerSpecCacheMx sync.Mutex
swaggerSpecCache *loads.Document
swaggerSpecCacheMx sync.Mutex
swaggerSpecCache *loads.Document
swaggerSpecAnalysisCache *analysis.Spec
)

// getSwaggerSpec loads and caches the swagger spec. If a cached version already exists,
// it returns the cached one. The reason why we cache it is because some downstream projects
// (e.g. Grafana Mimir) creates many Alertmanager instances in the same process, so they would
// incur in a significant memory penalty if we would reload the swagger spec each time.
func getSwaggerSpec() (*loads.Document, error) {
func getSwaggerSpec() (*loads.Document, *analysis.Spec, error) {
swaggerSpecCacheMx.Lock()
defer swaggerSpecCacheMx.Unlock()

// Check if a cached version exists.
if swaggerSpecCache != nil {
return swaggerSpecCache, nil
return swaggerSpecCache, swaggerSpecAnalysisCache, nil
}

// Load embedded swagger file.
swaggerSpec, err := loads.Analyzed(restapi.SwaggerJSON, "")
if err != nil {
return nil, fmt.Errorf("failed to load embedded swagger file: %w", err)
return nil, nil, fmt.Errorf("failed to load embedded swagger file: %w", err)
}

swaggerSpecCache = swaggerSpec
return swaggerSpec, nil
swaggerSpecAnalysisCache = analysis.New(swaggerSpec.Spec())
return swaggerSpec, swaggerSpecAnalysisCache, nil
}
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ require (
github.com/cenkalti/backoff/v4 v4.1.3
github.com/cespare/xxhash/v2 v2.1.2
github.com/go-kit/log v0.2.1
github.com/go-openapi/analysis v0.21.4
github.com/go-openapi/errors v0.20.3
github.com/go-openapi/loads v0.21.2
github.com/go-openapi/runtime v0.24.1
github.com/go-openapi/runtime v0.24.3-0.20221021160911-4425b20330b2
github.com/go-openapi/spec v0.20.7
github.com/go-openapi/strfmt v0.21.3
github.com/go-openapi/swag v0.22.3
Expand Down Expand Up @@ -54,7 +55,6 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXym
github.com/go-openapi/loads v0.21.1/go.mod h1:/DtAMXXneXFjbQMGEtbamCZb+4x7eGwkvZCvBmwUG+g=
github.com/go-openapi/loads v0.21.2 h1:r2a/xFIYeZ4Qd2TnGpWDIQNcP80dIaZgf704za8enro=
github.com/go-openapi/loads v0.21.2/go.mod h1:Jq58Os6SSGz0rzh62ptiu8Z31I+OTHqmULx5e/gJbNw=
github.com/go-openapi/runtime v0.24.1 h1:Sml5cgQKGYQHF+M7yYSHaH1eOjvTykrddTE/KtQVjqo=
github.com/go-openapi/runtime v0.24.1/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk=
github.com/go-openapi/runtime v0.24.3-0.20221021160911-4425b20330b2 h1:Vr08+BrsrnvcgikSlS273dkijppZ/M+fL/TMfc/LEJM=
github.com/go-openapi/runtime v0.24.3-0.20221021160911-4425b20330b2/go.mod h1:AKurw9fNre+h3ELZfk6ILsfvPN+bvvlaU/M9q/r9hpk=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
github.com/go-openapi/spec v0.20.7 h1:1Rlu/ZrOCCob0n+JKKJAWhNWMPW8bOZRg8FJaY+0SKI=
Expand Down

0 comments on commit 33bba95

Please sign in to comment.