Skip to content

Commit be7f160

Browse files
committed
Optimize low-bar network performance
1 parent 79cb315 commit be7f160

94 files changed

Lines changed: 15615 additions & 1765 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CODESTYLE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ A routing key is a value that decides *which* instance of something a message be
8383
Send and receive sit on opposite sides of the backpressure contract. **Senders block**: a packet/frame send is allowed to wait (buffer full, contract wait, write timeout) because blocking the producer is how backpressure propagates toward the source. **Receivers buffer and drop**: a packet/frame receive callback must never block, because by the time data reaches the receive side there is no producer left to slow down — there is only the delivery pipeline, and stalling it stalls everyone behind the stall.
8484

8585
- **A receive callback that hands off must use a 0 timeout on the handoff.** Enqueue non-blocking; if the queue is full, drop (and count the drop). Never propagate a downstream wait back into the delivery path.
86+
- **A bounded carrier adapter may separate admission from forwarding.** The carrier reader must still offer into that adapter with a zero-wait send and drop immediately on refusal. One adapter-owned forwarding worker may wait on its consumer, because the carrier reader is insulated by the queue; the queue must have independent hard message and byte bounds, cancellation must join the worker, and every queued pooled buffer must be returned before lifecycle completion. Do not share that waiting worker across independent carrier readers.
87+
- **A reliable byte-stream fragment cannot be dropped and skipped.** If a shared receiver multiplexes reliable logical streams and one bounded handoff refuses immediately, close that complete connection/generation so its owner can reconnect. Waiting creates cross-stream head-of-line blocking; continuing after a dropped byte fragment silently corrupts framing.
8688
- **Do not call a blocking send from inside a receive callback.** A send blocks by design, which makes it exactly the thing a receive callback must not contain. Hand the data to a queue owned by a sender goroutine instead, with a 0-timeout enqueue as above.
8789
- **Dropping is correct.** The transmission control running on top of the transport (TCP in the tunnel, the transfer protocol's ack/resend) exists to discover the achievable rate; a dropped packet is the signal it feeds on. Buffering "to be safe" hides the signal and converts loss into latency; blocking converts it into a stall.
8890
- The failure shape when this rule is broken is **head-of-line blocking across unrelated flows**: receive delivery is fanned out from shared pumps (a dispatch shard serves many flows; a client receive loop serves every sequence from a source), so one blocked callback parks every flow sharing the pump. One dead destination whose return send blocks for its full write timeout can starve delivery for all live destinations for that entire window — observed as flows that look dead on arrival while their peer is provably alive.

LOWBAR.md

Lines changed: 1145 additions & 0 deletions
Large diffs are not rendered by default.

connectctl/main.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"io"
2222
"log"
2323
"net/http"
24+
"sync/atomic"
2425

2526
// "encoding/base64"
2627
"bytes"
@@ -51,6 +52,17 @@ type sinkReceive struct {
5152
provideMode protocol.ProvideMode
5253
}
5354

55+
// Performs the sink's callback-to-printer handoff without stalling the
56+
// client's shared receive pump.
57+
func enqueueSinkReceive(receives chan<- *sinkReceive, receive *sinkReceive) bool {
58+
select {
59+
case receives <- receive:
60+
return true
61+
default:
62+
return false
63+
}
64+
}
65+
5466
// snapshotSinkReceive formats borrowed receive frames before the callback
5567
// returns. The decoder may immediately clear and reuse the Frame objects.
5668
func snapshotSinkReceive(
@@ -708,17 +720,31 @@ func sink(opts docopt.Opts) {
708720
// go platformTransport.Run(routeManager)
709721
}
710722

711-
receives := make(chan *sinkReceive)
723+
const receiveBufferSize = 256
724+
receives := make(chan *sinkReceive, receiveBufferSize)
725+
var receiveDropCount atomic.Uint64
712726

713727
client.AddReceiveCallback(func(source connect.TransferPath, frames []*protocol.Frame, peer connect.Peer) {
714-
receives <- snapshotSinkReceive(source, frames, peer)
728+
if !enqueueSinkReceive(receives, snapshotSinkReceive(source, frames, peer)) {
729+
receiveDropCount.Add(1)
730+
}
715731
})
716732

717733
// FIXME reassemble the chunks. Only a complete message counts as 1 against the message count
718-
for i := 0; messageCount < 0 || i < messageCount; i += 1 {
734+
reportDrops := func() {
735+
if dropCount := receiveDropCount.Swap(0); 0 < dropCount {
736+
Err.Printf("sink receive buffer full; dropped %d callback delivery(s)", dropCount)
737+
}
738+
}
739+
defer reportDrops()
740+
for receiveCount := 0; messageCount < 0 || receiveCount < messageCount; {
719741
select {
720742
case receive := <-receives:
721743
fmt.Printf("[%s %s] %s\n", receive.source, receive.provideMode, receive.frameSummary)
744+
receiveCount += 1
745+
reportDrops()
746+
case <-time.After(time.Second):
747+
reportDrops()
722748
}
723749
}
724750
}

connectctl/main_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,21 @@ func TestSnapshotSinkReceiveDoesNotRetainBorrowedFrames(t *testing.T) {
3030
t.Fatalf("frame summary changed after borrowed frame reuse: got %q want %q", snapshot.frameSummary, wantSummary)
3131
}
3232
}
33+
34+
// A full printer queue drops immediately instead of blocking the shared
35+
// client receive pump.
36+
func TestEnqueueSinkReceiveDropsWhenFull(t *testing.T) {
37+
receives := make(chan *sinkReceive, 1)
38+
first := &sinkReceive{frameSummary: "first"}
39+
second := &sinkReceive{frameSummary: "second"}
40+
41+
if !enqueueSinkReceive(receives, first) {
42+
t.Fatal("first receive was not admitted")
43+
}
44+
if enqueueSinkReceive(receives, second) {
45+
t.Fatal("second receive was admitted to a full queue")
46+
}
47+
if got := <-receives; got != first {
48+
t.Fatalf("queued receive = %p, want %p", got, first)
49+
}
50+
}

contention_bench_test.go

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package connect
88
import (
99
"context"
1010
"runtime"
11+
"sync"
1112
"sync/atomic"
1213
"testing"
1314
"time"
@@ -144,11 +145,7 @@ func BenchmarkMultiClientEgressParallel(b *testing.B) {
144145
defer cancel()
145146

146147
providerClientId := NewId()
147-
settings := DefaultClientSettings()
148-
settings.SendBufferSettings.SequenceBufferSize = 0
149-
settings.SendBufferSettings.AckBufferSize = 0
150-
settings.ReceiveBufferSettings.SequenceBufferSize = 0
151-
settings.ForwardBufferSettings.SequenceBufferSize = 0
148+
settings := DefaultClientSettingsWithBufferSize(256)
152149
providerClient := NewClient(ctx, providerClientId, NewNoContractClientOob(), settings)
153150
defer providerClient.Cancel()
154151

@@ -162,6 +159,7 @@ func BenchmarkMultiClientEgressParallel(b *testing.B) {
162159
if err != nil {
163160
b.Fatal(err)
164161
}
162+
defer natClient.Close()
165163

166164
clientId := NewId()
167165
source := SourceId(clientId)
@@ -207,18 +205,55 @@ func BenchmarkMultiClientBidirectional(b *testing.B) {
207205
defer cancel()
208206

209207
providerClientId := NewId()
210-
settings := DefaultClientSettings()
211-
settings.SendBufferSettings.SequenceBufferSize = 0
212-
settings.SendBufferSettings.AckBufferSize = 0
213-
settings.ReceiveBufferSettings.SequenceBufferSize = 0
214-
settings.ForwardBufferSettings.SequenceBufferSize = 0
208+
settings := DefaultClientSettingsWithBufferSize(256)
215209
providerClient := NewClient(ctx, providerClientId, NewNoContractClientOob(), settings)
216210
defer providerClient.Cancel()
217211

212+
type providerEcho struct {
213+
packet []byte
214+
destination Id
215+
transferKey TransferKey
216+
}
217+
providerEchoes := make(chan providerEcho, 1024)
218+
var providerEchoWaitGroup sync.WaitGroup
219+
workerCount := min(runtime.GOMAXPROCS(0), 4)
220+
for range workerCount {
221+
providerEchoWaitGroup.Add(1)
222+
go func() {
223+
defer providerEchoWaitGroup.Done()
224+
for {
225+
select {
226+
case <-ctx.Done():
227+
for {
228+
select {
229+
case echo := <-providerEchoes:
230+
MessagePoolReturn(echo.packet)
231+
default:
232+
return
233+
}
234+
}
235+
case echo := <-providerEchoes:
236+
success, _ := providerClient.sendRawWithTimeoutDetailed(
237+
protocol.MessageType_IpIpPacketFromProvider,
238+
echo.packet,
239+
echo.destination,
240+
nil,
241+
0,
242+
time.Second,
243+
echo.transferKey,
244+
)
245+
if !success {
246+
MessagePoolReturn(echo.packet)
247+
}
248+
}
249+
}
250+
}()
251+
}
218252
// the provider echoes each received packet back with the path reversed, so
219253
// the echo lands on the originating flow's update (the steady-state ingress
220-
// path).
221-
providerClient.AddReceiveCallback(func(source TransferPath, frames []*protocol.Frame, peer Peer) {
254+
// path). The shared receive callback only performs a bounded zero-wait
255+
// handoff; fixed workers own the blocking transfer sends.
256+
providerReceiveUnsub := providerClient.AddReceiveCallback(func(source TransferPath, frames []*protocol.Frame, peer Peer) {
222257
for _, frame := range frames {
223258
packet, err := ipPacketToProviderBytes(frame)
224259
if err != nil {
@@ -231,16 +266,23 @@ func BenchmarkMultiClientBidirectional(b *testing.B) {
231266
}
232267
reversed := ipPath.ReverseValue()
233268
echo := ipOosPacket(&reversed, payload)
234-
providerClient.sendRawWithTimeoutDetailed(
235-
protocol.MessageType_IpIpPacketFromProvider,
236-
echo,
237-
source.SourceId,
238-
nil,
239-
0,
240-
-1,
241-
)
269+
select {
270+
case providerEchoes <- providerEcho{
271+
packet: echo,
272+
destination: source.SourceId,
273+
transferKey: peer.TransferKey,
274+
}:
275+
default:
276+
MessagePoolReturn(echo)
277+
}
242278
}
243279
})
280+
defer func() {
281+
providerReceiveUnsub()
282+
cancel()
283+
providerClient.Cancel()
284+
providerEchoWaitGroup.Wait()
285+
}()
244286

245287
var receiveCount atomic.Int64
246288
natClient, err := testingNewMultiClient(
@@ -253,6 +295,7 @@ func BenchmarkMultiClientBidirectional(b *testing.B) {
253295
if err != nil {
254296
b.Fatal(err)
255297
}
298+
defer natClient.Close()
256299

257300
clientId := NewId()
258301
source := SourceId(clientId)

frame_protobuf.go

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,14 @@ func marshalSendPackTransferFrame(m *sendPackFrame) []byte {
322322
// carrying an Ack. The inner ack frame is not session-stamped (wrapping, when
323323
// it happens, adds the role/companion hint to the outer encrypted frame).
324324
type sendAckFrame struct {
325-
path TransferPath
326-
messageId Id
327-
sequenceId Id
328-
selective bool
329-
tagSendTime uint64
330-
tagSet bool
325+
path TransferPath
326+
messageId Id
327+
sequenceId Id
328+
selective bool
329+
tagSendTime uint64
330+
tagSet bool
331+
missingContractId *Id
332+
compactContractRecovery bool
331333
}
332334

333335
func (m *sendAckFrame) sizeAck() int {
@@ -342,6 +344,12 @@ func (m *sendAckFrame) sizeAck() int {
342344
tagBody := sizeTagBody(m.tagSendTime)
343345
n += protoSizeTag(4) + protoSizeVarint(uint64(tagBody)) + tagBody
344346
}
347+
if m.missingContractId != nil {
348+
n += protoSizeTag(5) + protoSizeVarint(16) + 16
349+
}
350+
if m.compactContractRecovery {
351+
n += protoSizeTag(6) + 1
352+
}
345353
return n
346354
}
347355

@@ -357,6 +365,13 @@ func (m *sendAckFrame) appendAck(b []byte) []byte {
357365
b = protoAppendVarint(b, uint64(sizeTagBody(m.tagSendTime)))
358366
b = appendTagBody(b, m.tagSendTime)
359367
}
368+
if m.missingContractId != nil {
369+
b = appendIdField(b, 5, *m.missingContractId)
370+
}
371+
if m.compactContractRecovery {
372+
b = protoAppendTag(b, 6, protoWireVarint)
373+
b = append(b, 1)
374+
}
360375
return b
361376
}
362377

@@ -1286,6 +1301,26 @@ func decodeAck(b []byte) (*protocol.Ack, bool) {
12861301
return nil, false
12871302
}
12881303
ack.Tag = tg
1304+
case 5: // missing_contract_id (bytes)
1305+
if typ != protowire.BytesType {
1306+
return nil, false
1307+
}
1308+
v, vn := protowire.ConsumeBytes(b)
1309+
if vn < 0 {
1310+
return nil, false
1311+
}
1312+
b = b[vn:]
1313+
ack.MissingContractId = copyProtoBytes(v)
1314+
case 6: // compact_contract_recovery
1315+
if typ != protowire.VarintType {
1316+
return nil, false
1317+
}
1318+
v, vn := protowire.ConsumeVarint(b)
1319+
if vn < 0 {
1320+
return nil, false
1321+
}
1322+
b = b[vn:]
1323+
ack.CompactContractRecovery = protowire.DecodeBool(v)
12891324
default:
12901325
fn := protowire.ConsumeFieldValue(num, typ, b)
12911326
if fn < 0 {

0 commit comments

Comments
 (0)