Skip to content

Commit

Permalink
avoid some allocs to reduce GC overhead
Browse files Browse the repository at this point in the history
  • Loading branch information
markus-wa committed Sep 4, 2024
1 parent b8fd000 commit e7c8b7f
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 19 deletions.
1 change: 1 addition & 0 deletions pkg/demoinfocs/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ type parser struct {
equipmentTypePerModel map[uint64]common.EquipmentType // Used to retrieve the EquipmentType of grenade projectiles based on models value. Source 2 only.
stringTables []createStringTable // Contains all created sendtables, needed when updating them
delayedEventHandlers []func() // Contains event handlers that need to be executed at the end of a tick (e.g. flash events because FlashDuration isn't updated before that)
pendingMessagesCache []pendingMessage // Cache for pending messages that need to be dispatched after the current tick
}

// NetMessageCreator creates additional net-messages to be dispatched to net-message handlers.
Expand Down
10 changes: 5 additions & 5 deletions pkg/demoinfocs/s2_commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -310,21 +310,21 @@ func (p *parser) handleDemoPacket(pack *msgs2.CDemoPacket) {

r := bitread.NewSmallBitReader(bytes.NewReader(b))

ms := make([]pendingMessage, 0)
p.pendingMessagesCache = p.pendingMessagesCache[:0]

for len(b)*8-r.ActualPosition() > 7 {
t := int32(r.ReadUBitInt())
size := r.ReadVarInt32()
buf := r.ReadBytes(int(size))

ms = append(ms, pendingMessage{t, buf})
p.pendingMessagesCache = append(p.pendingMessagesCache, pendingMessage{t, buf})
}

sort.SliceStable(ms, func(i, j int) bool {
return ms[i].priority() < ms[j].priority() // TODO: taken from dotabuff/manta. do we really need this?
sort.SliceStable(p.pendingMessagesCache, func(i, j int) bool {
return p.pendingMessagesCache[i].priority() < p.pendingMessagesCache[j].priority()
})

for _, m := range ms {
for _, m := range p.pendingMessagesCache {
var msgCreator NetMessageCreator

if m.t < int32(msgs2.SVC_Messages_svc_ServerInfo) {
Expand Down
11 changes: 3 additions & 8 deletions pkg/demoinfocs/sendtables2/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -484,12 +484,7 @@ func (p *Parser) OnPacketEntities(m *msgs2.CSVCMsg_PacketEntities) error {
p.entityFullPackets++
}

type tuple struct {
ent *Entity
op st.EntityOp
}

var tuples []tuple
p.tuplesCache = p.tuplesCache[:0]

for ; updates > 0; updates-- {
var (
Expand Down Expand Up @@ -575,10 +570,10 @@ func (p *Parser) OnPacketEntities(m *msgs2.CSVCMsg_PacketEntities) error {
}
}

tuples = append(tuples, tuple{e, op})
p.tuplesCache = append(p.tuplesCache, tuple{e, op})
}

for _, t := range tuples {
for _, t := range p.tuplesCache {
e := t.ent

for _, h := range p.entityHandlers {
Expand Down
5 changes: 4 additions & 1 deletion pkg/demoinfocs/sendtables2/field_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ func quantizedFactory(f *field) fieldDecoder {
}

qfd := newQuantizedFloatDecoder(f.bitCount, f.encodeFlags, f.lowValue, f.highValue)

return func(r *reader) interface{} {
return qfd.decode(r)
}
Expand All @@ -274,9 +275,11 @@ func vectorFactory(n int) fieldFactory {
d := floatFactory(f)
return func(r *reader) interface{} {
x := make([]float32, n)

for i := 0; i < n; i++ {
x[i] = d(r).(float32)
}

return x
}
}
Expand Down Expand Up @@ -319,7 +322,7 @@ func ammoDecoder(r *reader) interface{} {
}

func noscaleDecoder(r *reader) interface{} {
return math.Float32frombits(r.readBits(32))
return math.Float32frombits(r.readLeUint32())
}

func runeTimeDecoder(r *reader) interface{} {
Expand Down
6 changes: 6 additions & 0 deletions pkg/demoinfocs/sendtables2/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ var itemCounts = map[string]int{
"MAX_ABILITY_DRAFT_ABILITIES": 48,
}

type tuple struct {
ent *Entity
op st.EntityOp
}

type Parser struct {
serializers map[string]*serializer
classIdSize uint32
Expand All @@ -61,6 +66,7 @@ type Parser struct {
entities map[int32]*Entity
entityHandlers []st.EntityHandler
pathCache []*fieldPath
tuplesCache []tuple
}

func (p *Parser) ReadEnterPVS(r *bit.BitReader, index int, entities map[int]st.Entity, slot int) st.Entity {
Expand Down
21 changes: 16 additions & 5 deletions pkg/demoinfocs/sendtables2/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ func (r *reader) remBytes() uint32 {

// nextByte reads the next byte from the buffer
func (r *reader) nextByte() byte {
r.pos++

if r.pos > r.size {
if r.pos >= r.size {
_panicf("nextByte: insufficient buffer (%d of %d)", r.pos, r.size)
}

return r.buf[r.pos-1]
x := r.buf[r.pos]

r.pos++

return x
}

// readBits returns the uint32 value for the given number of sequential bits
Expand Down Expand Up @@ -77,22 +79,31 @@ func (r *reader) readBytes(n uint32) []byte {
// Fast path if we're byte aligned
if r.bitCount == 0 {
r.pos += n

if r.pos > r.size {
_panicf("readBytes: insufficient buffer (%d of %d)", r.pos, r.size)
}

return r.buf[r.pos-n : r.pos]
}

buf := make([]byte, n)

for i := uint32(0); i < n; i++ {
buf[i] = byte(r.readBits(8))
}

return buf
}

// readLeUint32 reads an little-endian uint32
func (r *reader) readLeUint32() uint32 {
return binary.LittleEndian.Uint32(r.readBytes(4))
// Fast path if we're byte aligned
if r.bitCount == 0 {
return binary.LittleEndian.Uint32(r.readBytes(4))
}

return r.readBits(32)
}

// readLeUint64 reads a little-endian uint64
Expand Down

0 comments on commit e7c8b7f

Please sign in to comment.