Skip to content

Commit e7c8b7f

Browse files
committed
avoid some allocs to reduce GC overhead
1 parent b8fd000 commit e7c8b7f

File tree

6 files changed

+35
-19
lines changed

6 files changed

+35
-19
lines changed

pkg/demoinfocs/parser.go

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ type parser struct {
104104
equipmentTypePerModel map[uint64]common.EquipmentType // Used to retrieve the EquipmentType of grenade projectiles based on models value. Source 2 only.
105105
stringTables []createStringTable // Contains all created sendtables, needed when updating them
106106
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)
107+
pendingMessagesCache []pendingMessage // Cache for pending messages that need to be dispatched after the current tick
107108
}
108109

109110
// NetMessageCreator creates additional net-messages to be dispatched to net-message handlers.

pkg/demoinfocs/s2_commands.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -310,21 +310,21 @@ func (p *parser) handleDemoPacket(pack *msgs2.CDemoPacket) {
310310

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

313-
ms := make([]pendingMessage, 0)
313+
p.pendingMessagesCache = p.pendingMessagesCache[:0]
314314

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

320-
ms = append(ms, pendingMessage{t, buf})
320+
p.pendingMessagesCache = append(p.pendingMessagesCache, pendingMessage{t, buf})
321321
}
322322

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

327-
for _, m := range ms {
327+
for _, m := range p.pendingMessagesCache {
328328
var msgCreator NetMessageCreator
329329

330330
if m.t < int32(msgs2.SVC_Messages_svc_ServerInfo) {

pkg/demoinfocs/sendtables2/entity.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -484,12 +484,7 @@ func (p *Parser) OnPacketEntities(m *msgs2.CSVCMsg_PacketEntities) error {
484484
p.entityFullPackets++
485485
}
486486

487-
type tuple struct {
488-
ent *Entity
489-
op st.EntityOp
490-
}
491-
492-
var tuples []tuple
487+
p.tuplesCache = p.tuplesCache[:0]
493488

494489
for ; updates > 0; updates-- {
495490
var (
@@ -575,10 +570,10 @@ func (p *Parser) OnPacketEntities(m *msgs2.CSVCMsg_PacketEntities) error {
575570
}
576571
}
577572

578-
tuples = append(tuples, tuple{e, op})
573+
p.tuplesCache = append(p.tuplesCache, tuple{e, op})
579574
}
580575

581-
for _, t := range tuples {
576+
for _, t := range p.tuplesCache {
582577
e := t.ent
583578

584579
for _, h := range p.entityHandlers {

pkg/demoinfocs/sendtables2/field_decoder.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ func quantizedFactory(f *field) fieldDecoder {
260260
}
261261

262262
qfd := newQuantizedFloatDecoder(f.bitCount, f.encodeFlags, f.lowValue, f.highValue)
263+
263264
return func(r *reader) interface{} {
264265
return qfd.decode(r)
265266
}
@@ -274,9 +275,11 @@ func vectorFactory(n int) fieldFactory {
274275
d := floatFactory(f)
275276
return func(r *reader) interface{} {
276277
x := make([]float32, n)
278+
277279
for i := 0; i < n; i++ {
278280
x[i] = d(r).(float32)
279281
}
282+
280283
return x
281284
}
282285
}
@@ -319,7 +322,7 @@ func ammoDecoder(r *reader) interface{} {
319322
}
320323

321324
func noscaleDecoder(r *reader) interface{} {
322-
return math.Float32frombits(r.readBits(32))
325+
return math.Float32frombits(r.readLeUint32())
323326
}
324327

325328
func runeTimeDecoder(r *reader) interface{} {

pkg/demoinfocs/sendtables2/parser.go

+6
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ var itemCounts = map[string]int{
5151
"MAX_ABILITY_DRAFT_ABILITIES": 48,
5252
}
5353

54+
type tuple struct {
55+
ent *Entity
56+
op st.EntityOp
57+
}
58+
5459
type Parser struct {
5560
serializers map[string]*serializer
5661
classIdSize uint32
@@ -61,6 +66,7 @@ type Parser struct {
6166
entities map[int32]*Entity
6267
entityHandlers []st.EntityHandler
6368
pathCache []*fieldPath
69+
tuplesCache []tuple
6470
}
6571

6672
func (p *Parser) ReadEnterPVS(r *bit.BitReader, index int, entities map[int]st.Entity, slot int) st.Entity {

pkg/demoinfocs/sendtables2/reader.go

+16-5
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,15 @@ func (r *reader) remBytes() uint32 {
3939

4040
// nextByte reads the next byte from the buffer
4141
func (r *reader) nextByte() byte {
42-
r.pos++
43-
44-
if r.pos > r.size {
42+
if r.pos >= r.size {
4543
_panicf("nextByte: insufficient buffer (%d of %d)", r.pos, r.size)
4644
}
4745

48-
return r.buf[r.pos-1]
46+
x := r.buf[r.pos]
47+
48+
r.pos++
49+
50+
return x
4951
}
5052

5153
// readBits returns the uint32 value for the given number of sequential bits
@@ -77,22 +79,31 @@ func (r *reader) readBytes(n uint32) []byte {
7779
// Fast path if we're byte aligned
7880
if r.bitCount == 0 {
7981
r.pos += n
82+
8083
if r.pos > r.size {
8184
_panicf("readBytes: insufficient buffer (%d of %d)", r.pos, r.size)
8285
}
86+
8387
return r.buf[r.pos-n : r.pos]
8488
}
8589

8690
buf := make([]byte, n)
91+
8792
for i := uint32(0); i < n; i++ {
8893
buf[i] = byte(r.readBits(8))
8994
}
95+
9096
return buf
9197
}
9298

9399
// readLeUint32 reads an little-endian uint32
94100
func (r *reader) readLeUint32() uint32 {
95-
return binary.LittleEndian.Uint32(r.readBytes(4))
101+
// Fast path if we're byte aligned
102+
if r.bitCount == 0 {
103+
return binary.LittleEndian.Uint32(r.readBytes(4))
104+
}
105+
106+
return r.readBits(32)
96107
}
97108

98109
// readLeUint64 reads a little-endian uint64

0 commit comments

Comments
 (0)