optimize window update generation, reducing profiler footprint by 8%

This commit is contained in:
Lucas Clemente
2016-09-15 09:10:59 +02:00
parent 7bd4d0852c
commit 2592b9a97c
5 changed files with 38 additions and 50 deletions

View File

@@ -106,25 +106,15 @@ func (f *flowControlManager) AddBytesRead(streamID protocol.StreamID, n protocol
return nil return nil
} }
// streamID must not be 0 here func (f *flowControlManager) GetWindowUpdates() (res []WindowUpdate) {
func (f *flowControlManager) MaybeTriggerStreamWindowUpdate(streamID protocol.StreamID) (bool, protocol.ByteCount, error) {
f.mutex.Lock() f.mutex.Lock()
defer f.mutex.Unlock() defer f.mutex.Unlock()
for id, fc := range f.streamFlowController {
streamFlowController, err := f.getFlowController(streamID) if necessary, offset := fc.MaybeTriggerWindowUpdate(); necessary {
if err != nil { res = append(res, WindowUpdate{StreamID: id, Offset: offset})
return false, 0, err
} }
}
doIt, offset := streamFlowController.MaybeTriggerWindowUpdate() return res
return doIt, offset, nil
}
func (f *flowControlManager) MaybeTriggerConnectionWindowUpdate() (bool, protocol.ByteCount) {
f.mutex.Lock()
defer f.mutex.Unlock()
return f.streamFlowController[0].MaybeTriggerWindowUpdate()
} }
// streamID must not be 0 here // streamID must not be 0 here

View File

@@ -95,10 +95,10 @@ var _ = Describe("Flow Control Manager", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
err = fcm.AddBytesRead(4, 0x100-0x10) err = fcm.AddBytesRead(4, 0x100-0x10)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
doIt, offset, err := fcm.MaybeTriggerStreamWindowUpdate(4) updates := fcm.GetWindowUpdates()
Expect(err).ToNot(HaveOccurred()) Expect(updates).To(HaveLen(1))
Expect(doIt).To(BeTrue()) Expect(updates[0].StreamID).To(Equal(protocol.StreamID(4)))
Expect(offset).ToNot(Equal(protocol.ByteCount(0x100))) Expect(updates[0].Offset).To(Equal(protocol.ByteCount(0x1f0)))
}) })
It("gets connection level window updates", func() { It("gets connection level window updates", func() {
@@ -110,10 +110,15 @@ var _ = Describe("Flow Control Manager", func() {
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
err = fcm.AddBytesRead(6, 0x100-0x10) err = fcm.AddBytesRead(6, 0x100-0x10)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
doIt, offset := fcm.MaybeTriggerConnectionWindowUpdate() updates := fcm.GetWindowUpdates()
Expect(err).ToNot(HaveOccurred()) Expect(updates).To(HaveLen(3))
Expect(doIt).To(BeTrue()) if updates[0].StreamID == 0 {
Expect(offset).ToNot(Equal(protocol.ByteCount(0x200))) Expect(updates[0].Offset).ToNot(Equal(protocol.ByteCount(0x200)))
} else if updates[1].StreamID == 0 {
Expect(updates[1].Offset).ToNot(Equal(protocol.ByteCount(0x200)))
} else {
Expect(updates[2].Offset).ToNot(Equal(protocol.ByteCount(0x200)))
}
}) })
}) })
}) })

View File

@@ -2,6 +2,12 @@ package flowcontrol
import "github.com/lucas-clemente/quic-go/protocol" import "github.com/lucas-clemente/quic-go/protocol"
// WindowUpdate provides the data for WindowUpdateFrames.
type WindowUpdate struct {
StreamID protocol.StreamID
Offset protocol.ByteCount
}
// A FlowControlManager manages the flow control // A FlowControlManager manages the flow control
type FlowControlManager interface { type FlowControlManager interface {
NewStream(streamID protocol.StreamID, contributesToConnectionFlow bool) NewStream(streamID protocol.StreamID, contributesToConnectionFlow bool)
@@ -9,8 +15,7 @@ type FlowControlManager interface {
// methods needed for receiving data // methods needed for receiving data
UpdateHighestReceived(streamID protocol.StreamID, byteOffset protocol.ByteCount) error UpdateHighestReceived(streamID protocol.StreamID, byteOffset protocol.ByteCount) error
AddBytesRead(streamID protocol.StreamID, n protocol.ByteCount) error AddBytesRead(streamID protocol.StreamID, n protocol.ByteCount) error
MaybeTriggerStreamWindowUpdate(streamID protocol.StreamID) (bool, protocol.ByteCount, error) GetWindowUpdates() []WindowUpdate
MaybeTriggerConnectionWindowUpdate() (bool, protocol.ByteCount)
// methods needed for sending data // methods needed for sending data
AddBytesSent(streamID protocol.StreamID, n protocol.ByteCount) error AddBytesSent(streamID protocol.StreamID, n protocol.ByteCount) error
SendWindowSize(streamID protocol.StreamID) (protocol.ByteCount, error) SendWindowSize(streamID protocol.StreamID) (protocol.ByteCount, error)

View File

@@ -659,25 +659,11 @@ func (s *Session) tryDecryptingQueuedPackets() {
} }
func (s *Session) getWindowUpdateFrames() ([]*frames.WindowUpdateFrame, error) { func (s *Session) getWindowUpdateFrames() ([]*frames.WindowUpdateFrame, error) {
var res []*frames.WindowUpdateFrame updates := s.flowControlManager.GetWindowUpdates()
res := make([]*frames.WindowUpdateFrame, len(updates))
s.streamsMap.Iterate(func(str *stream) (bool, error) { for i, u := range updates {
id := str.StreamID() res[i] = &frames.WindowUpdateFrame{StreamID: u.StreamID, ByteOffset: u.Offset}
doUpdate, offset, err := s.flowControlManager.MaybeTriggerStreamWindowUpdate(id)
if err != nil {
return false, err
} }
if doUpdate {
res = append(res, &frames.WindowUpdateFrame{StreamID: id, ByteOffset: offset})
}
return true, nil
})
doUpdate, offset := s.flowControlManager.MaybeTriggerConnectionWindowUpdate()
if doUpdate {
res = append(res, &frames.WindowUpdateFrame{StreamID: 0, ByteOffset: offset})
}
return res, nil return res, nil
} }

View File

@@ -44,12 +44,14 @@ func (m *mockFlowControlHandler) RemoveStream(streamID protocol.StreamID) {
delete(m.sendWindowSizes, streamID) delete(m.sendWindowSizes, streamID)
} }
func (m *mockFlowControlHandler) MaybeTriggerStreamWindowUpdate(streamID protocol.StreamID) (bool, protocol.ByteCount, error) { func (m *mockFlowControlHandler) GetWindowUpdates() (res []flowcontrol.WindowUpdate) {
return m.triggerStreamWindowUpdate, 0x1337, nil if m.triggerStreamWindowUpdate {
} res = append(res, flowcontrol.WindowUpdate{StreamID: 42, Offset: 0x1337})
}
func (m *mockFlowControlHandler) MaybeTriggerConnectionWindowUpdate() (bool, protocol.ByteCount) { if m.triggerConnectionWindowUpdate {
return m.triggerConnectionWindowUpdate, 0x1337 res = append(res, flowcontrol.WindowUpdate{StreamID: 0, Offset: 0x1337})
}
return res
} }
func (m *mockFlowControlHandler) AddBytesRead(streamID protocol.StreamID, n protocol.ByteCount) error { func (m *mockFlowControlHandler) AddBytesRead(streamID protocol.StreamID, n protocol.ByteCount) error {