-
Notifications
You must be signed in to change notification settings - Fork 239
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
improve memory utilization in receive buffer, fix flow control
* flow control was assuming a `Read` consumed the entire buffer * introduced fixed receive buffer on streams to reduce memory utilization when receiving large streams of data * use timer pool to reduce allocations * use static handler function pointer to avoid closure allocations for every frame
- Loading branch information
1 parent
b82d425
commit d483bcb
Showing
4 changed files
with
140 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package yamux | ||
|
||
import ( | ||
"errors" | ||
"io" | ||
) | ||
|
||
// buffer is an io.ReadWriteCloser backed by a fixed size buffer. | ||
// It never allocates, but moves old data as new data is written. | ||
type buffer struct { | ||
buf []byte | ||
r, w int | ||
} | ||
|
||
var ( | ||
errWriteFull = errors.New("write: full buffer") | ||
) | ||
|
||
// Read copies bytes from the buffer into p. | ||
// It is an error to read when no data is available. | ||
func (b *buffer) Read(p []byte) (n int, err error) { | ||
n = copy(p, b.buf[b.r:b.w]) | ||
b.r += n | ||
if b.r == b.w && n == 0 { | ||
err = io.EOF | ||
} | ||
return n, nil | ||
} | ||
|
||
// Len returns the number of bytes of the unread portion of the buffer. | ||
func (b *buffer) Len() int { | ||
return b.w - b.r | ||
} | ||
|
||
// Cap returns the capacity of the buffer's underlying byte slice, that is, the | ||
// total space allocated for the buffer's data. | ||
func (b *buffer) Cap() int { | ||
return cap(b.buf) | ||
} | ||
|
||
// Write copies bytes from p into the buffer. | ||
// It is an error to write more data than the buffer can hold. | ||
func (b *buffer) Write(p []byte) (n int, err error) { | ||
// Slide existing data to beginning. | ||
if b.r > 0 && len(p) > len(b.buf)-b.w { | ||
copy(b.buf, b.buf[b.r:b.w]) | ||
b.w -= b.r | ||
b.r = 0 | ||
} | ||
|
||
// Write new data. | ||
n = copy(b.buf[b.w:], p) | ||
b.w += n | ||
if n < len(p) { | ||
err = errWriteFull | ||
} | ||
return n, err | ||
} | ||
|
||
// ReadFrom reads data from r until EOF and appends it to the buffer, growing | ||
// the buffer as needed. The return value n is the number of bytes read. Any | ||
// error except io.EOF encountered during the read is also returned. If the | ||
// buffer becomes too large, ReadFrom will panic with ErrTooLarge. | ||
func (b *buffer) ReadFrom(r io.Reader) (n int64, err error) { | ||
// Slide existing data to beginning. | ||
if b.r > 0 { | ||
copy(b.buf, b.buf[b.r:b.w]) | ||
b.w -= b.r | ||
b.r = 0 | ||
} | ||
|
||
for { | ||
m, e := r.Read(b.buf[b.w:]) | ||
if b.w == len(b.buf) && e != io.EOF { | ||
return n, errWriteFull | ||
} | ||
|
||
n += int64(m) | ||
b.w += m | ||
if e == io.EOF { | ||
break | ||
} | ||
if e != nil { | ||
return n, e | ||
} | ||
} | ||
return n, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters