From bcca3ffa0b8630134bf6ec440bbf00df928fefce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Aug 2026 00:57:34 +0000 Subject: [PATCH] Bump code.cloudfoundry.org/locket from 1.7.0 to 1.9.0 --- updated-dependencies: - dependency-name: code.cloudfoundry.org/locket dependency-version: 1.8.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 18 +-- go.sum | 36 +++--- .../grpc/internal/envconfig/envconfig.go | 12 +- .../grpc/internal/mem/buffer_pool.go | 14 +++ .../grpc/internal/transport/handler_server.go | 2 +- .../grpc/internal/transport/http2_client.go | 2 +- .../grpc/internal/transport/http2_server.go | 2 +- .../grpc/internal/transport/transport.go | 110 +++++++++++++++++- .../google.golang.org/grpc/mem/buffer_pool.go | 4 - vendor/google.golang.org/grpc/mem/buffers.go | 6 +- vendor/google.golang.org/grpc/version.go | 2 +- vendor/modules.txt | 18 +-- 12 files changed, 172 insertions(+), 54 deletions(-) diff --git a/go.mod b/go.mod index 198dbe13..0fe45ad2 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.26.2 require ( code.cloudfoundry.org/bbs v1.12.0 code.cloudfoundry.org/bbs/models v1.8.0 - code.cloudfoundry.org/clock v1.83.0 + code.cloudfoundry.org/clock v1.84.0 code.cloudfoundry.org/debugserver v0.111.0 - code.cloudfoundry.org/diego-logging-client v0.120.0 + code.cloudfoundry.org/diego-logging-client v0.121.0 code.cloudfoundry.org/lager/v3 v3.82.0 code.cloudfoundry.org/localip v0.84.0 - code.cloudfoundry.org/locket v1.7.0 + code.cloudfoundry.org/locket v1.9.0 code.cloudfoundry.org/runtimeschema v0.0.0-20240514235758-31be7684c5bf code.cloudfoundry.org/workpool v0.0.0-20250911194158-1489753f182e github.com/cloudfoundry/dropsonde v1.1.0 @@ -24,10 +24,10 @@ require ( code.cloudfoundry.org/bbs/encryption v1.9.0 // indirect code.cloudfoundry.org/bbs/format v1.9.0 // indirect code.cloudfoundry.org/cfhttp/v2 v2.83.0 // indirect - code.cloudfoundry.org/durationjson v0.84.0 // indirect - code.cloudfoundry.org/go-diodes v0.0.0-20260720065427-59f65622c841 // indirect + code.cloudfoundry.org/durationjson v0.86.0 // indirect + code.cloudfoundry.org/go-diodes v0.0.0-20260818081020-5f89c9327272 // indirect code.cloudfoundry.org/go-loggregator/v9 v9.2.1 // indirect - code.cloudfoundry.org/tlsconfig v0.64.0 // indirect + code.cloudfoundry.org/tlsconfig v0.65.0 // indirect filippo.io/edwards25519 v1.2.0 // indirect github.com/Masterminds/semver/v3 v3.5.0 // indirect github.com/bmizerany/pat v0.0.0-20210406213842-e4b6760bdd6f // indirect @@ -45,7 +45,7 @@ require ( github.com/square/certstrap v1.3.0 // indirect github.com/tedsuo/rata v1.0.0 // indirect github.com/vito/go-sse v1.1.3 // indirect - go.step.sm/crypto v0.87.0 // indirect + go.step.sm/crypto v0.89.0 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/crypto v0.55.0 // indirect golang.org/x/mod v0.40.0 // indirect @@ -54,8 +54,8 @@ require ( golang.org/x/sys v0.47.0 // indirect golang.org/x/text v0.41.0 // indirect golang.org/x/tools v0.49.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260810153831-ec0a7760b754 // indirect - google.golang.org/grpc v1.83.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 // indirect + google.golang.org/grpc v1.83.1 // indirect google.golang.org/protobuf v1.36.12 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect ) diff --git a/go.sum b/go.sum index 74e9fd7a..f17a1196 100644 --- a/go.sum +++ b/go.sum @@ -8,28 +8,28 @@ code.cloudfoundry.org/bbs/models v1.8.0 h1:4bN0mNZAKGZUn4ODQ+Zzy2yLlop6LD/fSx7Tl code.cloudfoundry.org/bbs/models v1.8.0/go.mod h1:xHL4SdxSn73DmJPDT3B6h/bt4+keCXsQoyMAS93B6d4= code.cloudfoundry.org/cfhttp/v2 v2.83.0 h1:XP43/VVeA8+3He1Qp4yqXwAwZkgBM2tx3VIX9gYzpzQ= code.cloudfoundry.org/cfhttp/v2 v2.83.0/go.mod h1:OAYoWcMpQzzkMrqGNrL4Lj1u07jelqdtNT56CRu/X8I= -code.cloudfoundry.org/clock v1.83.0 h1:mfvo8W/0rbabUP14xffa/IaGjNVPbROta8kZoG9nuB0= -code.cloudfoundry.org/clock v1.83.0/go.mod h1:7ZvHLD4H0HfcO8WJsGb/CCOTT9bky1ruYUwCP5glzRA= +code.cloudfoundry.org/clock v1.84.0 h1:nYJHcG5WSDSxVYNOp+/GwqVHN5Y0VAMbbRZwetw+RJ4= +code.cloudfoundry.org/clock v1.84.0/go.mod h1:POPXUjWjYxGzHXU/AYe6P0f4rell+a7X5SZG0Q6UxAU= code.cloudfoundry.org/debugserver v0.111.0 h1:G3iQdarMY9xBIvZ9tz6S3neOR4b9ftdLPk7R90LuHtY= code.cloudfoundry.org/debugserver v0.111.0/go.mod h1:Va7ouJLVYkEr7oS+ZEK/L5le/MGwwYP25S8lwILRMyM= -code.cloudfoundry.org/diego-logging-client v0.120.0 h1:OYMi75pV5lNWi3wYd1ZPxGWanBaZnpSOF5x3ov3bvpo= -code.cloudfoundry.org/diego-logging-client v0.120.0/go.mod h1:J5U2p7ydtwP/TLYhH9t2DXgwCb0OrYX7jZ4kyTbaylQ= -code.cloudfoundry.org/durationjson v0.84.0 h1:Q5/fXF44tofrxf8hXbihuNyQ0P/qmwAnyJ8u0ySk+H4= -code.cloudfoundry.org/durationjson v0.84.0/go.mod h1:9xq+k5i7SrYl+YOdUpt7odQcTtGyvAP5a/bwz4MxTJg= -code.cloudfoundry.org/go-diodes v0.0.0-20260720065427-59f65622c841 h1:zvumGkVYJgjVJZo/BCcc2HSMVO2BLvrX0wCg+KLvT20= -code.cloudfoundry.org/go-diodes v0.0.0-20260720065427-59f65622c841/go.mod h1:czNfbIZFq2IWuL5+OYO/zlEzOL3rbWPfOVIuymG9la4= +code.cloudfoundry.org/diego-logging-client v0.121.0 h1:7oH4Xkh5Tbov4xXdXiECykC48rPhjQz/oVEJbrC173s= +code.cloudfoundry.org/diego-logging-client v0.121.0/go.mod h1:aaIDxnHn7Du5PgGwU06O1HvEoizHTRjjHZ2fZkVJpxg= +code.cloudfoundry.org/durationjson v0.86.0 h1:roOUOfjiGuc+cj2HDGz+C5xPyr7TLMVufSI2e2z0zH8= +code.cloudfoundry.org/durationjson v0.86.0/go.mod h1:OS8be7UxH5k7JsPUA1HUlIoNCz0gkogV1HPqFeWd1W4= +code.cloudfoundry.org/go-diodes v0.0.0-20260818081020-5f89c9327272 h1:GAdBWzt881Ulr6ELFZHH8Brii1a9gYJhC3kKYrOJmjY= +code.cloudfoundry.org/go-diodes v0.0.0-20260818081020-5f89c9327272/go.mod h1:S9HJ0GGRD/g86IiyDdweYgKLP7nbdVfxrCVV4aNSFSE= code.cloudfoundry.org/go-loggregator/v9 v9.2.1 h1:S6Lgg5UJbhh2bt2TGQxs6R00CF8PrUA3GFPYDxy56Fk= code.cloudfoundry.org/go-loggregator/v9 v9.2.1/go.mod h1:FTFFruqGeOhVCDFvyLgl8EV8YW63NNwRzLhxJcporu8= code.cloudfoundry.org/lager/v3 v3.82.0 h1:/iTYAOg02MbOaq/Sh4jdka5IUtUYVN1YYR8GHbjMOK0= code.cloudfoundry.org/lager/v3 v3.82.0/go.mod h1:MfEnRvMtBJxBIDRHZKv9s6ssvB5HFnprVLSiwWZlx+s= code.cloudfoundry.org/localip v0.84.0 h1:eVEqnkhQ/5rf3zmcyDeoSmOJYc/EGddQMnpup+l42e0= code.cloudfoundry.org/localip v0.84.0/go.mod h1:ujHdkJs63PwzNjd0xjI0N40TN98PfxNeARRAh96T+Sg= -code.cloudfoundry.org/locket v1.7.0 h1:mw3aqETmPOYmYujUXdmRoOC98FrFtp8y7DlDqKezt2w= -code.cloudfoundry.org/locket v1.7.0/go.mod h1:Ry3jV9bOnUY7cj58CMjAJnqLt428reVD0dJiX38eOK8= +code.cloudfoundry.org/locket v1.9.0 h1:l4PYeWIWhl8XUKqsMU8SOX1wHFRb9k7BtCuvIYJkAwo= +code.cloudfoundry.org/locket v1.9.0/go.mod h1:kk2hvwxkRGUDFeY2kepQiNb7vvpA/OJ3BpH7xrO/D24= code.cloudfoundry.org/runtimeschema v0.0.0-20240514235758-31be7684c5bf h1:sTpfHaU+tgDeRO/fRnyr91gvf1FaJk3ZNiJHiHq4nko= code.cloudfoundry.org/runtimeschema v0.0.0-20240514235758-31be7684c5bf/go.mod h1:Cbw66uMLAXkeK8ZpcTUIJ9nhXNxaN742q1xS/ONrWiQ= -code.cloudfoundry.org/tlsconfig v0.64.0 h1:RfqVhbAyLiF9o5OZpIv7s5wIGY94Orao/EUiiHg4Br4= -code.cloudfoundry.org/tlsconfig v0.64.0/go.mod h1:lBONCe4dGY95PBY4NGMXNDtmayJHeZyOaXZKGcXWNSw= +code.cloudfoundry.org/tlsconfig v0.65.0 h1:mPga0pCfQp9nTHgXizFrfpsWmmcGHIUgD+cYb8KPpmw= +code.cloudfoundry.org/tlsconfig v0.65.0/go.mod h1:orvSwt5ytEO49rjIY+JLGcbIoCCbVbcowHHTbheYToI= code.cloudfoundry.org/workpool v0.0.0-20250911194158-1489753f182e h1:NsULHptleEmqtoC8j6A8J636L9APnGn8YC0c7vocLww= code.cloudfoundry.org/workpool v0.0.0-20250911194158-1489753f182e/go.mod h1:O9HdfntfyDvYRH9nh03XdpnGMbjyZVi8nb2Kh+6hDho= filippo.io/edwards25519 v1.2.0 h1:crnVqOiS4jqYleHd9vaKZ+HKtHfllngJIiOpNpoJsjo= @@ -144,8 +144,8 @@ go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRk go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= -go.step.sm/crypto v0.87.0 h1:+u0pDz1OV9M/SswA6KtcQ3GSrYMMelbL//0W/ceJVYI= -go.step.sm/crypto v0.87.0/go.mod h1:gBr1mpMiKs5804/Yt03uAoOBiw3DFxARZnGUKEUO82M= +go.step.sm/crypto v0.89.0 h1:NPxryE+cZ4XDwXOQY2U6Gu+mOzOihuRLPIsX7WtPzZM= +go.step.sm/crypto v0.89.0/go.mod h1:IEgE6DndnYojbDyHU7eYXpwWzpu4ftkouw7nyI6jsxg= go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -191,10 +191,10 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260810153831-ec0a7760b754 h1:k5CJw9e5ONCcA/u0webKt092npXuY+KeGh3Q8NAVf0g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260810153831-ec0a7760b754/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= -google.golang.org/grpc v1.83.0 h1:JeNZEKJFbQxArAMl+hiytHauacDNqJUllNfmIMmpqnQ= -google.golang.org/grpc v1.83.0/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 h1:cYNAzI2sUwhmCcoj9TxvihSrqsxt6uIkj3rDRhSDmW4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688/go.mod h1:DjtHYE8FKJLivXcBEjGwndXfIC23G0VpXiXKqG179uA= +google.golang.org/grpc v1.83.1 h1:HIO0+BEtBP6soyqvqC8sNUjZ7bTs+0hFQuFF+RAy++Y= +google.golang.org/grpc v1.83.1/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ= google.golang.org/protobuf v1.36.12 h1:pJOKDDOyeXErUroCihFAd5LQuwXBSpVnKGrj5o/fwxc= google.golang.org/protobuf v1.36.12/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= diff --git a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go index 29d332e7..33344812 100644 --- a/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go +++ b/vendor/google.golang.org/grpc/internal/envconfig/envconfig.go @@ -150,8 +150,18 @@ var ( // throttling limit if unforeseen issues arise, and it will be removed in a // future release. // - // TODO: Remove this env var once v1.83.0 is release. + // TODO: Remove this env var once v1.83.0 is released. ControlBufferThrottleLimit = uint64FromEnv("GRPC_GO_EXPERIMENTAL_CONTROL_BUFFER_THROTTLE_LIMIT", 100, 1, 10000) + + // EnableReceiveBufferCompaction enables the compaction of data buffers + // to reduce the number of buffers in the receive buffer. + // + // This environment variable serves as an escape hatch to disable the + // feature if unforeseen issues arise, and it will be removed in a future + // release. + // + // TODO: Remove this env var once v1.85.0 is released. + EnableReceiveBufferCompaction = boolFromEnv("GRPC_GO_EXPERIMENTAL_ENABLE_RECEIVE_BUFFER_COMPACTION", true) ) func boolFromEnv(envVar string, def bool) bool { diff --git a/vendor/google.golang.org/grpc/internal/mem/buffer_pool.go b/vendor/google.golang.org/grpc/internal/mem/buffer_pool.go index 2d83b2ec..00aeca41 100644 --- a/vendor/google.golang.org/grpc/internal/mem/buffer_pool.go +++ b/vendor/google.golang.org/grpc/internal/mem/buffer_pool.go @@ -26,12 +26,26 @@ import ( "slices" "sort" "sync" + + "google.golang.org/grpc/internal" ) const ( goPageSize = 4 * 1024 // 4KiB. N.B. this must be a power of 2. ) +var ( + // BufferPoolingThreshold is the minimum size of a buffer that can be pooled. + // This is used to determine whether to pool buffers or allocate them directly. + BufferPoolingThreshold = 1 << 10 +) + +func init() { + internal.SetBufferPoolingThresholdForTesting = func(threshold int) { + BufferPoolingThreshold = threshold + } +} + var uintSize = bits.UintSize // use a variable for mocking during tests. // bufferPool is a copy of the public bufferPool interface used to avoid diff --git a/vendor/google.golang.org/grpc/internal/transport/handler_server.go b/vendor/google.golang.org/grpc/internal/transport/handler_server.go index a8356c9a..9cd8d28d 100644 --- a/vendor/google.golang.org/grpc/internal/transport/handler_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/handler_server.go @@ -424,7 +424,7 @@ func (ht *serverHandlerTransport) HandleStreams(ctx context.Context, startStream st: ht, headerWireLength: 0, // won't have access to header wire length until golang/go#18997. } - s.Stream.buf.init() + s.Stream.buf.init(ht.bufferPool) s.readRequester = s s.trReader = transportReader{ reader: recvBufferReader{ctx: s.ctx, ctxDone: s.ctx.Done(), recv: &s.buf}, diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_client.go b/vendor/google.golang.org/grpc/internal/transport/http2_client.go index c19b4508..10d19774 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_client.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_client.go @@ -500,7 +500,7 @@ func (t *http2Client) newStream(ctx context.Context, callHdr *CallHdr, handler s headerChan: make(chan struct{}), statsHandler: handler, } - s.Stream.buf.init() + s.Stream.buf.init(t.bufferPool) s.Stream.wq.init(defaultWriteQuota, s.done) s.readRequester = s // The client side stream context should have exactly the same life cycle with the user provided context. diff --git a/vendor/google.golang.org/grpc/internal/transport/http2_server.go b/vendor/google.golang.org/grpc/internal/transport/http2_server.go index be8ae9f9..63c6539a 100644 --- a/vendor/google.golang.org/grpc/internal/transport/http2_server.go +++ b/vendor/google.golang.org/grpc/internal/transport/http2_server.go @@ -407,7 +407,7 @@ func (t *http2Server) operateHeaders(ctx context.Context, frame *http2.MetaHeade st: t, headerWireLength: int(frame.Header().Length), } - s.Stream.buf.init() + s.Stream.buf.init(t.bufferPool) var ( // if false, content-type was missing or invalid isGRPC = false diff --git a/vendor/google.golang.org/grpc/internal/transport/transport.go b/vendor/google.golang.org/grpc/internal/transport/transport.go index d2e49538..5fc901e5 100644 --- a/vendor/google.golang.org/grpc/internal/transport/transport.go +++ b/vendor/google.golang.org/grpc/internal/transport/transport.go @@ -30,11 +30,14 @@ import ( "sync" "sync/atomic" "time" + "unsafe" "golang.org/x/net/http2" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" "google.golang.org/grpc/internal/channelz" + "google.golang.org/grpc/internal/envconfig" + imem "google.golang.org/grpc/internal/mem" "google.golang.org/grpc/internal/transport/internal" "google.golang.org/grpc/keepalive" "google.golang.org/grpc/mem" @@ -45,7 +48,30 @@ import ( "google.golang.org/grpc/tap" ) -const logLevel = 2 +const ( + logLevel = 2 + // recvMsgSize estimates the memory overhead of a recvMsg in the backlog. + // It accounts for the recvMsg struct itself and the slice header of the + // underlying buffer's data. + recvMsgSize = int(unsafe.Sizeof(recvMsg{}) + unsafe.Sizeof([]byte{})) + + // utilizationFactor controls when we consider memory utilization acceptable. + // When backlogHeapSize / payloadSize <= utilizationFactor (meaning at least + // 50% of the heap memory is actual payload data), compaction is skipped. + utilizationFactor = 2 +) + +var ( + // compactionThreshold is approx 57KB (on 64-bit systems). It allows + // accumulating up to 1024 1-byte payloads before triggering compaction. + // + // Because individual payloads <= 1024 bytes are allocated on the heap + // outside mem.BufferPool, waiting for at least 1024 bytes to accumulate + // ensures that compaction coalesces those small heap allocations into a + // single large buffer from mem.BufferPool, enabling buffer reuse while + // avoiding frequent copying for small bursts of frames. + compactionThreshold = imem.BufferPoolingThreshold * (recvMsgSize + 1) +) func init() { internal.TimeNowFunc = func() int64 { return time.Now().UnixNano() } @@ -71,23 +97,31 @@ type recvBuffer struct { c chan recvMsg mu sync.Mutex backlog []recvMsg - err error + // uncompactedSuffixLen tracks the number of consecutive data messages at + // the tail of backlog that have not been compacted. + uncompactedSuffixLen int + // uncompactedBytes tracks the total payload bytes across the trailing + // uncompactedSuffixLen messages. + uncompactedBytes int + err error + bufPool mem.BufferPool } // init allows a recvBuffer to be initialized in-place, which is useful // for resetting a buffer or for avoiding a heap allocation when the buffer // is embedded in another struct. -func (b *recvBuffer) init() { +func (b *recvBuffer) init(pool mem.BufferPool) { b.c = make(chan recvMsg, 1) + b.bufPool = pool } func (b *recvBuffer) put(r recvMsg) { b.mu.Lock() + defer b.mu.Unlock() if b.err != nil { // drop the buffer on the floor. Since b.err is not nil, any subsequent reads // will always return an error, making this buffer inaccessible. r.buffer.Free() - b.mu.Unlock() // An error had occurred earlier, don't accept more // data or errors. return @@ -96,13 +130,70 @@ func (b *recvBuffer) put(r recvMsg) { if len(b.backlog) == 0 { select { case b.c <- r: - b.mu.Unlock() return default: } } b.backlog = append(b.backlog, r) - b.mu.Unlock() + b.compactBacklogLocked(r) +} + +func (b *recvBuffer) compactBacklogLocked(r recvMsg) { + if !envconfig.EnableReceiveBufferCompaction { + return + } + if r.buffer == nil { + b.uncompactedBytes = 0 + b.uncompactedSuffixLen = 0 + return + } + + b.uncompactedSuffixLen++ + b.uncompactedBytes += r.buffer.Len() + backlogHeapSize := b.uncompactedSuffixLen*recvMsgSize + b.uncompactedBytes + + // If the memory overhead is less than 50% of the heap usage (e.g., because + // a large DATA frame arrived), the average message size in the suffix is + // large enough that memory bloat is not a concern. Reset suffix tracking. + if backlogHeapSize <= utilizationFactor*b.uncompactedBytes { + b.uncompactedBytes = 0 + b.uncompactedSuffixLen = 0 + return + } + // Avoid compacting too frequently for short bursts of small frames. + // Wait until we have accumulated at least ~1024 small messages (~57 KB). + if backlogHeapSize <= compactionThreshold { + // Still can accumulate more payloads. + return + } + + // Since the memory utilization is less than 50%, the average payload size + // of each recvMsg must be less than recvMsgSize (approx 56 bytes). + // In the worst case for bytes copied (where the average payload is just + // below recvMsgSize), compaction will occur once every: + // compactionThreshold / (recvMsgSize + avg_payload) = ~520 messages, + // copying ~29KB of data. + + start := 0 + newBuf := b.bufPool.Get(b.uncompactedBytes) + startIdx := len(b.backlog) - b.uncompactedSuffixLen + + for i := startIdx; i < len(b.backlog); i++ { + m := b.backlog[i] + b.backlog[i] = recvMsg{} + start += copy((*newBuf)[start:], m.buffer.ReadOnlyData()) + m.buffer.Free() + } + b.backlog[startIdx] = recvMsg{ + buffer: mem.NewBuffer(newBuf, b.bufPool), + } + b.backlog = b.backlog[:startIdx+1] + // After compaction, the suffix is replaced with a single message containing + // the combined payload. The new utilization is close to 1.0 (overhead of + // one recvMsg relative to the large compacted payload), which is well + // below the utilization factor of 2. + b.uncompactedBytes = 0 + b.uncompactedSuffixLen = 0 } func (b *recvBuffer) load() { @@ -110,6 +201,13 @@ func (b *recvBuffer) load() { if len(b.backlog) > 0 { select { case b.c <- b.backlog[0]: + // backlog[0] is only part of the tracked uncompacted suffix if the + // entire backlog currently consists of the suffix. If an earlier + // compaction or reset occurred, backlog[0] is already compacted. + if envconfig.EnableReceiveBufferCompaction && b.uncompactedSuffixLen == len(b.backlog) { + b.uncompactedSuffixLen-- + b.uncompactedBytes -= b.backlog[0].buffer.Len() + } b.backlog[0] = recvMsg{} b.backlog = b.backlog[1:] default: diff --git a/vendor/google.golang.org/grpc/mem/buffer_pool.go b/vendor/google.golang.org/grpc/mem/buffer_pool.go index 3b02b909..aa121379 100644 --- a/vendor/google.golang.org/grpc/mem/buffer_pool.go +++ b/vendor/google.golang.org/grpc/mem/buffer_pool.go @@ -59,10 +59,6 @@ func init() { internal.SetDefaultBufferPool = func(pool BufferPool) { defaultBufferPool = pool } - - internal.SetBufferPoolingThresholdForTesting = func(threshold int) { - bufferPoolingThreshold = threshold - } } // DefaultBufferPool returns the current default buffer pool. It is a BufferPool diff --git a/vendor/google.golang.org/grpc/mem/buffers.go b/vendor/google.golang.org/grpc/mem/buffers.go index 2b410b16..9b355d44 100644 --- a/vendor/google.golang.org/grpc/mem/buffers.go +++ b/vendor/google.golang.org/grpc/mem/buffers.go @@ -29,6 +29,8 @@ import ( "fmt" "sync" "sync/atomic" + + "google.golang.org/grpc/internal/mem" ) // A Buffer represents a reference counted piece of data (in bytes) that can be @@ -63,8 +65,6 @@ type Buffer interface { } var ( - bufferPoolingThreshold = 1 << 10 - bufferObjectPool = sync.Pool{New: func() any { return new(buffer) }} ) @@ -72,7 +72,7 @@ var ( // equal to the threshold for buffer pooling. This is used to determine whether // to pool buffers or allocate them directly. func IsBelowBufferPoolingThreshold(size int) bool { - return size <= bufferPoolingThreshold + return size <= mem.BufferPoolingThreshold } type buffer struct { diff --git a/vendor/google.golang.org/grpc/version.go b/vendor/google.golang.org/grpc/version.go index 4083c039..64ec3b3c 100644 --- a/vendor/google.golang.org/grpc/version.go +++ b/vendor/google.golang.org/grpc/version.go @@ -19,4 +19,4 @@ package grpc // Version is the current grpc version. -const Version = "1.83.0" +const Version = "1.83.1" diff --git a/vendor/modules.txt b/vendor/modules.txt index 3d00512d..e9334149 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -18,20 +18,20 @@ code.cloudfoundry.org/bbs/models/test/model_helpers # code.cloudfoundry.org/cfhttp/v2 v2.83.0 ## explicit; go 1.25.0 code.cloudfoundry.org/cfhttp/v2 -# code.cloudfoundry.org/clock v1.83.0 +# code.cloudfoundry.org/clock v1.84.0 ## explicit; go 1.25.0 code.cloudfoundry.org/clock # code.cloudfoundry.org/debugserver v0.111.0 ## explicit; go 1.25.0 code.cloudfoundry.org/debugserver -# code.cloudfoundry.org/diego-logging-client v0.120.0 +# code.cloudfoundry.org/diego-logging-client v0.121.0 ## explicit; go 1.25.8 code.cloudfoundry.org/diego-logging-client code.cloudfoundry.org/diego-logging-client/testhelpers -# code.cloudfoundry.org/durationjson v0.84.0 +# code.cloudfoundry.org/durationjson v0.86.0 ## explicit; go 1.25.0 code.cloudfoundry.org/durationjson -# code.cloudfoundry.org/go-diodes v0.0.0-20260720065427-59f65622c841 +# code.cloudfoundry.org/go-diodes v0.0.0-20260818081020-5f89c9327272 ## explicit; go 1.25.0 code.cloudfoundry.org/go-diodes # code.cloudfoundry.org/go-loggregator/v9 v9.2.1 @@ -48,7 +48,7 @@ code.cloudfoundry.org/lager/v3/lagertest # code.cloudfoundry.org/localip v0.84.0 ## explicit; go 1.25.0 code.cloudfoundry.org/localip -# code.cloudfoundry.org/locket v1.7.0 +# code.cloudfoundry.org/locket v1.9.0 ## explicit; go 1.26.0 code.cloudfoundry.org/locket code.cloudfoundry.org/locket/cmd/locket/certauthority @@ -59,7 +59,7 @@ code.cloudfoundry.org/locket/models # code.cloudfoundry.org/runtimeschema v0.0.0-20240514235758-31be7684c5bf ## explicit; go 1.20 code.cloudfoundry.org/runtimeschema/cc_messages -# code.cloudfoundry.org/tlsconfig v0.64.0 +# code.cloudfoundry.org/tlsconfig v0.65.0 ## explicit; go 1.25.8 code.cloudfoundry.org/tlsconfig # code.cloudfoundry.org/workpool v0.0.0-20250911194158-1489753f182e @@ -203,7 +203,7 @@ github.com/tedsuo/rata # github.com/vito/go-sse v1.1.3 ## explicit; go 1.24 github.com/vito/go-sse/sse -# go.step.sm/crypto v0.87.0 +# go.step.sm/crypto v0.89.0 ## explicit; go 1.25.8 go.step.sm/crypto/fingerprint go.step.sm/crypto/internal/bcrypt_pbkdf @@ -300,10 +300,10 @@ golang.org/x/tools/internal/pkgbits golang.org/x/tools/internal/stdlib golang.org/x/tools/internal/typesinternal golang.org/x/tools/internal/versions -# google.golang.org/genproto/googleapis/rpc v0.0.0-20260810153831-ec0a7760b754 +# google.golang.org/genproto/googleapis/rpc v0.0.0-20260819154853-08b0e4226688 ## explicit; go 1.25.0 google.golang.org/genproto/googleapis/rpc/status -# google.golang.org/grpc v1.83.0 +# google.golang.org/grpc v1.83.1 ## explicit; go 1.25.0 google.golang.org/grpc google.golang.org/grpc/attributes