Skip to content

Commit f6db0d7

Browse files
authored
Merge pull request #3 from anantadwi13/dev
reduce memory allocation
2 parents ee2c14b + 075af8e commit f6db0d7

File tree

5 files changed

+59
-32
lines changed

5 files changed

+59
-32
lines changed

io/buffer.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ type bufReader struct {
147147
isClosed int32
148148
isEofReached bool
149149
reader io.ReadCloser
150-
buffer [][]byte
150+
buffer []*Buffer
151151

152152
currentPos int64
153153
}
@@ -282,7 +282,7 @@ func (b *bufReader) readTo(p []byte) (n int, err error) {
282282
buf := b.buffer[b.currentPos/int64(b.pool.BufferSize())]
283283
currentPos := int(b.currentPos % int64(b.pool.BufferSize()))
284284

285-
read := copy(p[n:], buf[currentPos:])
285+
read := copy(p[n:], buf.buffer[currentPos:])
286286
n += read
287287
b.currentPos += int64(read)
288288
}
@@ -308,12 +308,12 @@ func (b *bufReader) read(n int64) (bytesRead int64, err error) {
308308
return
309309
}
310310

311-
var buf []byte
311+
var buf *Buffer
312312

313313
if len(b.buffer) != 0 {
314314
buf = b.buffer[len(b.buffer)-1]
315315
}
316-
if buf == nil || len(buf) == cap(buf) {
316+
if buf == nil || len(buf.buffer) == cap(buf.buffer) {
317317
buf, err = b.pool.Get(b.ctx)
318318
if err != nil {
319319
if errors.Is(err, context.Canceled) {
@@ -322,14 +322,14 @@ func (b *bufReader) read(n int64) (bytesRead int64, err error) {
322322
return
323323
}
324324

325-
buf = buf[:0]
325+
buf.buffer = buf.buffer[:0]
326326
b.buffer = append(b.buffer, buf)
327327
}
328328

329329
var tmpN int
330-
tmpN, err = b.reader.Read(buf[len(buf):cap(buf)])
330+
tmpN, err = b.reader.Read(buf.buffer[len(buf.buffer):cap(buf.buffer)])
331331
if tmpN > 0 {
332-
b.buffer[len(b.buffer)-1] = b.buffer[len(b.buffer)-1][:len(buf)+tmpN]
332+
buf.buffer = buf.buffer[:len(buf.buffer)+tmpN]
333333
bytesRead += int64(tmpN)
334334
}
335335
}
@@ -342,7 +342,7 @@ func (b *bufReader) getReaderPos() int64 {
342342
return 0
343343
}
344344

345-
return int64(l-1)*int64(b.pool.BufferSize()) + int64(len(b.buffer[l-1]))
345+
return int64(l-1)*int64(b.pool.BufferSize()) + int64(len(b.buffer[l-1].buffer))
346346
}
347347

348348
func (b *bufReader) cleanUpBuffer(all bool) {
@@ -356,7 +356,7 @@ func (b *bufReader) cleanUpBuffer(all bool) {
356356
if b.buffer[i] == nil {
357357
continue
358358
}
359-
b.pool.Put(b.buffer[i])
359+
b.buffer[i].cleanUp()
360360
b.buffer[i] = nil
361361
}
362362
b.buffer = nil

io/buffer_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func TestReaderVariant(t *testing.T) {
147147
}
148148

149149
func TestFlowNormalRead(t *testing.T) {
150-
tp := &testPool{bufSize: 5}
150+
tp := &testPool{p: newPool(5)}
151151
bf := NewBufferReadSeekCloserFactory(OptionWithPool(tp))
152152
assert.EqualValues(t, 5, bf.BufferSize())
153153

@@ -211,7 +211,7 @@ func TestFlowNormalRead(t *testing.T) {
211211
}
212212

213213
func TestFlowReadSeek(t *testing.T) {
214-
tp := &testPool{bufSize: 5}
214+
tp := &testPool{p: newPool(5)}
215215
bf := NewBufferReadSeekCloserFactory(OptionWithPool(tp))
216216
assert.EqualValues(t, 5, bf.BufferSize())
217217

@@ -327,7 +327,7 @@ func TestFlowReadSeek(t *testing.T) {
327327
}
328328

329329
func TestFlowReadSeekOutOfRange(t *testing.T) {
330-
tp := &testPool{bufSize: 5}
330+
tp := &testPool{p: newPool(5)}
331331
bf := NewBufferReadSeekCloserFactory(OptionWithPool(tp))
332332
assert.EqualValues(t, 5, bf.BufferSize())
333333

@@ -362,7 +362,7 @@ func TestFlowReadSeekOutOfRange(t *testing.T) {
362362
}
363363

364364
func TestFlowReadSeekDisableSeeker(t *testing.T) {
365-
tp := &testPool{bufSize: 5}
365+
tp := &testPool{p: newPool(5)}
366366
bf := NewBufferReadSeekCloserFactory(OptionWithPool(tp))
367367
assert.EqualValues(t, 5, bf.BufferSize())
368368

@@ -418,7 +418,7 @@ func TestFlowReadSeekDisableSeeker(t *testing.T) {
418418
}
419419

420420
func TestFlowWithBufferNotFullyFilled(t *testing.T) {
421-
tp := &testPool{bufSize: 5}
421+
tp := &testPool{p: newPool(5)}
422422
bf := NewBufferReadSeekCloserFactory(OptionWithPool(tp))
423423
assert.EqualValues(t, 5, bf.BufferSize())
424424

io/types.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,26 @@ type BufferReadSeekCloser interface {
2929
DisableSeeker()
3030
}
3131

32+
type Buffer struct {
33+
pool Pool
34+
buffer []byte
35+
}
36+
37+
func NewBuffer(pool Pool, buf []byte) *Buffer {
38+
buf = buf[:cap(buf)]
39+
return &Buffer{
40+
pool: pool,
41+
buffer: buf,
42+
}
43+
}
44+
45+
func (b *Buffer) cleanUp() {
46+
b.buffer = b.buffer[:cap(b.buffer)]
47+
b.pool.Put(b)
48+
}
49+
3250
type Pool interface {
3351
BufferSize() int
34-
Put(buf []byte)
35-
Get(ctx context.Context) ([]byte, error)
52+
Put(buf *Buffer)
53+
Get(ctx context.Context) (*Buffer, error)
3654
}

io/util_test.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,31 +44,37 @@ func (p *noPool) BufferSize() int {
4444
return p.bufSize
4545
}
4646

47-
func (p *noPool) Put(buf []byte) {
47+
func (p *noPool) Put(buf *Buffer) {
4848
}
4949

50-
func (p *noPool) Get(ctx context.Context) ([]byte, error) {
51-
return make([]byte, p.bufSize), nil
50+
func (p *noPool) Get(ctx context.Context) (*Buffer, error) {
51+
return NewBuffer(p, make([]byte, p.bufSize)), nil
5252
}
5353

5454
type testPool struct {
55-
bufSize int
56-
diff int32
55+
diff int32
56+
p Pool
5757
}
5858

5959
func (t *testPool) Diff() int32 {
6060
return atomic.LoadInt32(&t.diff)
6161
}
6262

6363
func (t *testPool) BufferSize() int {
64-
return t.bufSize
64+
return t.p.BufferSize()
6565
}
6666

67-
func (t *testPool) Put(buf []byte) {
67+
func (t *testPool) Put(buf *Buffer) {
6868
atomic.AddInt32(&t.diff, -1)
69+
t.p.Put(buf)
6970
}
7071

71-
func (t *testPool) Get(ctx context.Context) ([]byte, error) {
72+
func (t *testPool) Get(ctx context.Context) (*Buffer, error) {
7273
atomic.AddInt32(&t.diff, 1)
73-
return make([]byte, 0, t.bufSize), nil
74+
buf, err := t.p.Get(ctx)
75+
if err != nil {
76+
return nil, err
77+
}
78+
buf.pool = t
79+
return buf, nil
7480
}

io/utils.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@ func newPool(bufferSize int) Pool {
2020
if bufferSize <= 0 {
2121
bufferSize = DefaultBufferSize
2222
}
23-
p := &sync.Pool{New: func() interface{} {
24-
return make([]byte, 0, bufferSize)
23+
p := &pool{
24+
bufSize: bufferSize,
25+
}
26+
p.p = &sync.Pool{New: func() interface{} {
27+
return NewBuffer(p, make([]byte, bufferSize))
2528
}}
26-
return &pool{p: p, bufSize: bufferSize}
29+
return p
2730
}
2831

2932
func (p *pool) BufferSize() int {
3033
return p.bufSize
3134
}
3235

33-
func (p *pool) Put(bytes []byte) {
34-
p.p.Put(bytes)
36+
func (p *pool) Put(buf *Buffer) {
37+
p.p.Put(buf)
3538
}
3639

37-
func (p *pool) Get(ctx context.Context) ([]byte, error) {
38-
return p.p.Get().([]byte), nil
40+
func (p *pool) Get(ctx context.Context) (*Buffer, error) {
41+
return p.p.Get().(*Buffer), nil
3942
}

0 commit comments

Comments
 (0)