Skip to content

Performance: reconsider sync.Pool for gzip #2126

Description

@howardjohn

sync.Pool has a somewhat surprising behavior that it has processor-local copies (https://victoriametrics.com/blog/go-sync-pool/). So on large machines (mine has GOMAXPROCS=32 default), we can end up with 32 copies of items stored in sync.Pool - even without concurrent usage.

Prometheus uses a pool for gzip:

gz := gzipPool.Get().(*gzip.Writer)
. With 32 copies of the gzip writer, we end up with ~10mb heap usage. Which isn't crazy but is a pretty substantial amount for an otherwise very small application doing very little allocations/GC, and serving even a tiny number of metrics.

The reason sync.Pool does this is to improve throughput by avoiding synchronization. However, in a scraping setup I would think that its very uncommon to have much concurrency (maybe you have a couple of scrapers, but I'd imagine the median is 1 scraper)

Below shows my application's memory usage after disabling gzip due to this:

Image

So at least in my specific case, it seems like it might be more optimal to use a sync.Pool-like structure that doesn't have this per-processor copying mechanism.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions