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 (#3092)

* Reduce memory utilization in downstream projects creating multiple Alertmanager instances

* Wrap the error instead of citing it

Signed-off-by: Marco Pracucci <marco@pracucci.com>
  • Loading branch information
pracucci committed Oct 6, 2022
1 parent 2c04c5a commit 78b5a27
Showing 1 changed file with 30 additions and 2 deletions.
32 changes: 30 additions & 2 deletions api/v2/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ func NewAPI(
}

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

// Create new service API.
Expand Down Expand Up @@ -672,3 +672,31 @@ func parseFilter(filter []string) ([]*labels.Matcher, error) {
}
return matchers, nil
}

var (
swaggerSpecCacheMx sync.Mutex
swaggerSpecCache *loads.Document
)

// 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) {
swaggerSpecCacheMx.Lock()
defer swaggerSpecCacheMx.Unlock()

// Check if a cached version exists.
if swaggerSpecCache != nil {
return swaggerSpecCache, 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)
}

swaggerSpecCache = swaggerSpec
return swaggerSpec, nil
}

0 comments on commit 78b5a27

Please sign in to comment.