mirror of https://github.com/v2ray/v2ray-core
reduce memory allocation in kcp
parent
5b58066345
commit
33d2513e3c
|
@ -48,6 +48,13 @@ func NewDataSegment() *DataSegment {
|
||||||
return new(DataSegment)
|
return new(DataSegment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *DataSegment) SetData(b []byte) {
|
||||||
|
if this.Data == nil {
|
||||||
|
this.Data = alloc.NewLocalBuffer(1600)
|
||||||
|
}
|
||||||
|
this.Data.Clear().Append(b)
|
||||||
|
}
|
||||||
|
|
||||||
func (this *DataSegment) Bytes(b []byte) []byte {
|
func (this *DataSegment) Bytes(b []byte) []byte {
|
||||||
b = serial.Uint16ToBytes(this.Conv, b)
|
b = serial.Uint16ToBytes(this.Conv, b)
|
||||||
b = append(b, byte(CommandData), byte(this.Option))
|
b = append(b, byte(CommandData), byte(this.Option))
|
||||||
|
@ -181,7 +188,7 @@ func ReadSegment(buf []byte) (Segment, []byte) {
|
||||||
if len(buf) < dataLen {
|
if len(buf) < dataLen {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
seg.Data = AllocateBuffer().Clear().Append(buf[:dataLen])
|
seg.SetData(buf[:dataLen])
|
||||||
buf = buf[dataLen:]
|
buf = buf[dataLen:]
|
||||||
|
|
||||||
return seg, buf
|
return seg, buf
|
||||||
|
|
|
@ -10,9 +10,10 @@ type SendingWindow struct {
|
||||||
len uint32
|
len uint32
|
||||||
last uint32
|
last uint32
|
||||||
|
|
||||||
data []*DataSegment
|
data []DataSegment
|
||||||
prev []uint32
|
inuse []bool
|
||||||
next []uint32
|
prev []uint32
|
||||||
|
next []uint32
|
||||||
|
|
||||||
totalInFlightSize uint32
|
totalInFlightSize uint32
|
||||||
writer SegmentWriter
|
writer SegmentWriter
|
||||||
|
@ -25,9 +26,10 @@ func NewSendingWindow(size uint32, writer SegmentWriter, onPacketLoss func(uint3
|
||||||
cap: size,
|
cap: size,
|
||||||
len: 0,
|
len: 0,
|
||||||
last: 0,
|
last: 0,
|
||||||
data: make([]*DataSegment, size),
|
data: make([]DataSegment, size),
|
||||||
prev: make([]uint32, size),
|
prev: make([]uint32, size),
|
||||||
next: make([]uint32, size),
|
next: make([]uint32, size),
|
||||||
|
inuse: make([]bool, size),
|
||||||
writer: writer,
|
writer: writer,
|
||||||
onPacketLoss: onPacketLoss,
|
onPacketLoss: onPacketLoss,
|
||||||
}
|
}
|
||||||
|
@ -50,9 +52,13 @@ func (this *SendingWindow) IsFull() bool {
|
||||||
return this.len == this.cap
|
return this.len == this.cap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SendingWindow) Push(seg *DataSegment) {
|
func (this *SendingWindow) Push(number uint32, data []byte) {
|
||||||
pos := (this.start + this.len) % this.cap
|
pos := (this.start + this.len) % this.cap
|
||||||
this.data[pos] = seg
|
this.data[pos].SetData(data)
|
||||||
|
this.data[pos].Number = number
|
||||||
|
this.data[pos].timeout = 0
|
||||||
|
this.data[pos].transmit = 0
|
||||||
|
this.inuse[pos] = true
|
||||||
if this.len > 0 {
|
if this.len > 0 {
|
||||||
this.next[this.last] = pos
|
this.next[this.last] = pos
|
||||||
this.prev[pos] = this.last
|
this.prev[pos] = this.last
|
||||||
|
@ -61,8 +67,8 @@ func (this *SendingWindow) Push(seg *DataSegment) {
|
||||||
this.len++
|
this.len++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SendingWindow) First() *DataSegment {
|
func (this *SendingWindow) FirstNumber() uint32 {
|
||||||
return this.data[this.start]
|
return this.data[this.start].Number
|
||||||
}
|
}
|
||||||
|
|
||||||
func (this *SendingWindow) Clear(una uint32) {
|
func (this *SendingWindow) Clear(una uint32) {
|
||||||
|
@ -77,13 +83,11 @@ func (this *SendingWindow) Remove(idx uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pos := (this.start + idx) % this.cap
|
pos := (this.start + idx) % this.cap
|
||||||
seg := this.data[pos]
|
if !this.inuse[pos] {
|
||||||
if seg == nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
this.inuse[pos] = false
|
||||||
this.totalInFlightSize--
|
this.totalInFlightSize--
|
||||||
seg.Release()
|
|
||||||
this.data[pos] = nil
|
|
||||||
if pos == this.start && pos == this.last {
|
if pos == this.start && pos == this.last {
|
||||||
this.len = 0
|
this.len = 0
|
||||||
this.start = 0
|
this.start = 0
|
||||||
|
@ -109,7 +113,7 @@ func (this *SendingWindow) HandleFastAck(number uint32, rto uint32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := this.start; ; i = this.next[i] {
|
for i := this.start; ; i = this.next[i] {
|
||||||
seg := this.data[i]
|
seg := &this.data[i]
|
||||||
if number-seg.Number > 0x7FFFFFFF {
|
if number-seg.Number > 0x7FFFFFFF {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -133,7 +137,7 @@ func (this *SendingWindow) Flush(current uint32, rto uint32, maxInFlightSize uin
|
||||||
var inFlightSize uint32
|
var inFlightSize uint32
|
||||||
|
|
||||||
for i := this.start; ; i = this.next[i] {
|
for i := this.start; ; i = this.next[i] {
|
||||||
segment := this.data[i]
|
segment := &this.data[i]
|
||||||
needsend := false
|
needsend := false
|
||||||
if current-segment.timeout < 0x7FFFFFFF {
|
if current-segment.timeout < 0x7FFFFFFF {
|
||||||
if segment.transmit == 0 {
|
if segment.transmit == 0 {
|
||||||
|
@ -205,7 +209,7 @@ func (this *SendingWorker) ProcessReceivingNextWithoutLock(nextNumber uint32) {
|
||||||
func (this *SendingWorker) FindFirstUnacknowledged() {
|
func (this *SendingWorker) FindFirstUnacknowledged() {
|
||||||
v := this.firstUnacknowledged
|
v := this.firstUnacknowledged
|
||||||
if !this.window.IsEmpty() {
|
if !this.window.IsEmpty() {
|
||||||
this.firstUnacknowledged = this.window.First().Number
|
this.firstUnacknowledged = this.window.FirstNumber()
|
||||||
} else {
|
} else {
|
||||||
this.firstUnacknowledged = this.nextNumber
|
this.firstUnacknowledged = this.nextNumber
|
||||||
}
|
}
|
||||||
|
@ -264,12 +268,7 @@ func (this *SendingWorker) Push(b []byte) int {
|
||||||
} else {
|
} else {
|
||||||
size = len(b)
|
size = len(b)
|
||||||
}
|
}
|
||||||
seg := NewDataSegment()
|
this.window.Push(this.nextNumber, b[:size])
|
||||||
seg.Data = AllocateBuffer().Clear().Append(b[:size])
|
|
||||||
seg.Number = this.nextNumber
|
|
||||||
seg.timeout = 0
|
|
||||||
seg.transmit = 0
|
|
||||||
this.window.Push(seg)
|
|
||||||
this.nextNumber++
|
this.nextNumber++
|
||||||
b = b[size:]
|
b = b[size:]
|
||||||
nBytes += size
|
nBytes += size
|
||||||
|
|
|
@ -11,37 +11,27 @@ func TestSendingWindow(t *testing.T) {
|
||||||
assert := assert.On(t)
|
assert := assert.On(t)
|
||||||
|
|
||||||
window := NewSendingWindow(5, nil, nil)
|
window := NewSendingWindow(5, nil, nil)
|
||||||
window.Push(&DataSegment{
|
window.Push(0, []byte{})
|
||||||
Number: 0,
|
window.Push(1, []byte{})
|
||||||
})
|
window.Push(2, []byte{})
|
||||||
window.Push(&DataSegment{
|
|
||||||
Number: 1,
|
|
||||||
})
|
|
||||||
window.Push(&DataSegment{
|
|
||||||
Number: 2,
|
|
||||||
})
|
|
||||||
assert.Int(window.Len()).Equals(3)
|
assert.Int(window.Len()).Equals(3)
|
||||||
|
|
||||||
window.Remove(1)
|
window.Remove(1)
|
||||||
assert.Int(window.Len()).Equals(3)
|
assert.Int(window.Len()).Equals(3)
|
||||||
assert.Uint32(window.First().Number).Equals(0)
|
assert.Uint32(window.FirstNumber()).Equals(0)
|
||||||
|
|
||||||
window.Remove(0)
|
window.Remove(0)
|
||||||
assert.Int(window.Len()).Equals(1)
|
assert.Int(window.Len()).Equals(1)
|
||||||
assert.Uint32(window.First().Number).Equals(2)
|
assert.Uint32(window.FirstNumber()).Equals(2)
|
||||||
|
|
||||||
window.Remove(0)
|
window.Remove(0)
|
||||||
assert.Int(window.Len()).Equals(0)
|
assert.Int(window.Len()).Equals(0)
|
||||||
|
|
||||||
window.Push(&DataSegment{
|
window.Push(4, []byte{})
|
||||||
Number: 4,
|
|
||||||
})
|
|
||||||
assert.Int(window.Len()).Equals(1)
|
assert.Int(window.Len()).Equals(1)
|
||||||
assert.Uint32(window.First().Number).Equals(4)
|
assert.Uint32(window.FirstNumber()).Equals(4)
|
||||||
|
|
||||||
window.Push(&DataSegment{
|
window.Push(5, []byte{})
|
||||||
Number: 5,
|
|
||||||
})
|
|
||||||
assert.Int(window.Len()).Equals(2)
|
assert.Int(window.Len()).Equals(2)
|
||||||
|
|
||||||
window.Remove(1)
|
window.Remove(1)
|
||||||
|
|
Loading…
Reference in New Issue