summaryrefslogtreecommitdiff
path: root/internal/server/handlers/line_writer_alloc_test.go
blob: fc82e81acd813262b9c54194df0979c9cb0aee3e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package handlers

import (
	"bytes"
	"testing"

	"github.com/mimecast/dtail/internal/io/dlog"
	"github.com/mimecast/dtail/internal/io/pool"
)

// nopLineWriter is a zero-allocation LineWriter used to isolate the
// per-line trace-guard overhead in the alloc test below.
type nopLineWriter struct{}

func (nopLineWriter) WriteLineData(lineContent []byte, lineNum uint64, sourceID string) error {
	return nil
}
func (nopLineWriter) WriteServerMessage(message string) error { return nil }
func (nopLineWriter) Flush() error                            { return nil }

// TestDirectLineProcessorProcessLineNoAllocWhenTraceOff locks in task 1t0: the
// per-line hot path must not allocate when trace logging is off (the default
// production/output level). Before the fix, ProcessLine unconditionally built a
// []interface{} and boxed lineCount/lineNum (runtime.convT64) and sourceID
// (convTstring) on every line even though dlog.Trace early-returns — that call
// site was ~98% of all allocated objects in the output serverless dcat profile.
// The dlog.Server.TraceEnabled() guard elides all of it.
func TestDirectLineProcessorProcessLineNoAllocWhenTraceOff(t *testing.T) {
	orig := dlog.Server
	// Zero-value DLog has maxLevel == None, i.e. trace disabled.
	dlog.Server = &dlog.DLog{}
	t.Cleanup(func() { dlog.Server = orig })

	if dlog.Server.TraceEnabled() {
		t.Fatal("precondition failed: trace must be disabled for this test")
	}

	p := NewDirectLineProcessor(nopLineWriter{}, "globID")

	allocs := testing.AllocsPerRun(1000, func() {
		// Mirror the real hot path: a pooled buffer that ProcessLine recycles.
		buf := pool.BytesBuffer.Get().(*bytes.Buffer)
		buf.Reset()
		buf.WriteString("some representative log line content")
		if err := p.ProcessLine(buf, 42, "sourceID"); err != nil {
			t.Fatalf("ProcessLine: %v", err)
		}
	})

	if allocs != 0 {
		t.Fatalf("ProcessLine allocated %v objects/run with trace off; want 0 "+
			"(the per-line trace guard should elide all interface boxing)", allocs)
	}
}