@@ -22,47 +22,30 @@ const maxCachedBufSize = 256 * 1024
2222// In other words, we can't write and read simultaneously on the same connection.
2323// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
2424// Also highly optimized for this particular use case.
25- // This buffer is backed by two byte slices in a double-buffering scheme
2625type buffer struct {
27- buf []byte // buf is a byte buffer who's length and capacity are equal.
28- nc net.Conn
29- idx int
30- length int
31- timeout time.Duration
32- dbuf [2 ][]byte // dbuf is an array with the two byte slices that back this buffer
33- flipcnt uint // flipccnt is the current buffer counter for double-buffering
26+ buf []byte // read buffer.
27+ cachedBuf []byte // buffer that will be reused. len(cachedBuf) <= maxCachedBufSize.
28+ nc net.Conn
29+ timeout time.Duration
3430}
3531
3632// newBuffer allocates and returns a new buffer.
3733func newBuffer (nc net.Conn ) buffer {
38- fg := make ([]byte , defaultBufSize )
3934 return buffer {
40- buf : fg ,
41- nc : nc ,
42- dbuf : [2 ][]byte {fg , nil },
35+ cachedBuf : make ([]byte , defaultBufSize ),
36+ nc : nc ,
4337 }
4438}
4539
46- // busy returns true if the buffer contains some read data .
40+ // busy returns true if the read buffer is not empty .
4741func (b * buffer ) busy () bool {
48- return b . length > 0
42+ return len ( b . buf ) > 0
4943}
5044
51- // flip replaces the active buffer with the background buffer
52- // this is a delayed flip that simply increases the buffer counter;
53- // the actual flip will be performed the next time we call `buffer.fill`
54- func (b * buffer ) flip () {
55- b .flipcnt += 1
56- }
57-
58- // fill reads into the buffer until at least _need_ bytes are in it
45+ // fill reads into the read buffer until at least _need_ bytes are in it.
5946func (b * buffer ) fill (need int ) error {
60- n := b .length
61- // fill data into its double-buffering target: if we've called
62- // flip on this buffer, we'll be copying to the background buffer,
63- // and then filling it with network data; otherwise we'll just move
64- // the contents of the current buffer to the front before filling it
65- dest := b .dbuf [b .flipcnt & 1 ]
47+ // we'll move the contents of the current buffer to dest before filling it.
48+ dest := b .cachedBuf
6649
6750 // grow buffer if necessary to fit the whole packet.
6851 if need > len (dest ) {
@@ -72,18 +55,13 @@ func (b *buffer) fill(need int) error {
7255 // if the allocated buffer is not too large, move it to backing storage
7356 // to prevent extra allocations on applications that perform large reads
7457 if len (dest ) <= maxCachedBufSize {
75- b .dbuf [ b . flipcnt & 1 ] = dest
58+ b .cachedBuf = dest
7659 }
7760 }
7861
79- // if we're filling the fg buffer, move the existing data to the start of it.
80- // if we're filling the bg buffer, copy over the data
81- if n > 0 {
82- copy (dest [:n ], b .buf [b .idx :])
83- }
84-
85- b .buf = dest
86- b .idx = 0
62+ // move the existing data to the start of the buffer.
63+ n := len (b .buf )
64+ copy (dest [:n ], b .buf )
8765
8866 for {
8967 if b .timeout > 0 {
@@ -92,63 +70,58 @@ func (b *buffer) fill(need int) error {
9270 }
9371 }
9472
95- nn , err := b .nc .Read (b . buf [n :])
73+ nn , err := b .nc .Read (dest [n :])
9674 n += nn
9775
98- switch err {
99- case nil :
100- if n < need {
101- continue
102- }
103- b .length = n
104- return nil
76+ if err == nil && n < need {
77+ continue
78+ }
10579
106- case io .EOF :
107- if n >= need {
108- b .length = n
109- return nil
110- }
111- return io .ErrUnexpectedEOF
80+ b .buf = dest [:n ]
11281
113- default :
114- return err
82+ if err == io .EOF {
83+ if n < need {
84+ err = io .ErrUnexpectedEOF
85+ } else {
86+ err = nil
87+ }
11588 }
89+ return err
11690 }
11791}
11892
11993// returns next N bytes from buffer.
12094// The returned slice is only guaranteed to be valid until the next read
12195func (b * buffer ) readNext (need int ) ([]byte , error ) {
122- if b . length < need {
96+ if len ( b . buf ) < need {
12397 // refill
12498 if err := b .fill (need ); err != nil {
12599 return nil , err
126100 }
127101 }
128102
129- offset := b .idx
130- b .idx += need
131- b .length -= need
132- return b .buf [offset :b .idx ], nil
103+ data := b .buf [:need ]
104+ b .buf = b .buf [need :]
105+ return data , nil
133106}
134107
135108// takeBuffer returns a buffer with the requested size.
136109// If possible, a slice from the existing buffer is returned.
137110// Otherwise a bigger buffer is made.
138111// Only one buffer (total) can be used at a time.
139112func (b * buffer ) takeBuffer (length int ) ([]byte , error ) {
140- if b .length > 0 {
113+ if b .busy () {
141114 return nil , ErrBusyBuffer
142115 }
143116
144117 // test (cheap) general case first
145- if length <= cap (b .buf ) {
146- return b .buf [:length ], nil
118+ if length <= len (b .cachedBuf ) {
119+ return b .cachedBuf [:length ], nil
147120 }
148121
149- if length < maxPacketSize {
150- b .buf = make ([]byte , length )
151- return b .buf , nil
122+ if length < maxCachedBufSize {
123+ b .cachedBuf = make ([]byte , length )
124+ return b .cachedBuf , nil
152125 }
153126
154127 // buffer is larger than we want to store.
@@ -159,29 +132,26 @@ func (b *buffer) takeBuffer(length int) ([]byte, error) {
159132// known to be smaller than defaultBufSize.
160133// Only one buffer (total) can be used at a time.
161134func (b * buffer ) takeSmallBuffer (length int ) ([]byte , error ) {
162- if b .length > 0 {
135+ if b .busy () {
163136 return nil , ErrBusyBuffer
164137 }
165- return b .buf [:length ], nil
138+ return b .cachedBuf [:length ], nil
166139}
167140
168141// takeCompleteBuffer returns the complete existing buffer.
169142// This can be used if the necessary buffer size is unknown.
170143// cap and len of the returned buffer will be equal.
171144// Only one buffer (total) can be used at a time.
172145func (b * buffer ) takeCompleteBuffer () ([]byte , error ) {
173- if b .length > 0 {
146+ if b .busy () {
174147 return nil , ErrBusyBuffer
175148 }
176- return b .buf , nil
149+ return b .cachedBuf , nil
177150}
178151
179152// store stores buf, an updated buffer, if its suitable to do so.
180- func (b * buffer ) store (buf []byte ) error {
181- if b .length > 0 {
182- return ErrBusyBuffer
183- } else if cap (buf ) <= maxPacketSize && cap (buf ) > cap (b .buf ) {
184- b .buf = buf [:cap (buf )]
153+ func (b * buffer ) store (buf []byte ) {
154+ if cap (buf ) <= maxCachedBufSize && cap (buf ) > cap (b .cachedBuf ) {
155+ b .cachedBuf = buf [:cap (buf )]
185156 }
186- return nil
187157}
0 commit comments