**Payload Performance Test:** - Add job cleanup after each iteration using DeleteJob() - Ensure isolated memory measurements between test runs **All Benchmark Tests:** - General improvements and maintenance updates
157 lines
3.7 KiB
Go
157 lines
3.7 KiB
Go
package benchmarks
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/jfraeys/fetch_ml/internal/api"
|
|
)
|
|
|
|
var benchmarkDataPayload = func() []byte {
|
|
buf := make([]byte, 4096)
|
|
for i := range buf {
|
|
buf[i] = byte(i % 251)
|
|
}
|
|
return buf
|
|
}()
|
|
|
|
var benchmarkPackets = []struct {
|
|
name string
|
|
packet *api.ResponsePacket
|
|
}{
|
|
{
|
|
name: "success",
|
|
packet: &api.ResponsePacket{
|
|
PacketType: api.PacketTypeSuccess,
|
|
Timestamp: 1_732_000_000,
|
|
SuccessMessage: "Job 'benchmark' queued successfully",
|
|
},
|
|
},
|
|
{
|
|
name: "error",
|
|
packet: &api.ResponsePacket{
|
|
PacketType: api.PacketTypeError,
|
|
Timestamp: 1_732_000_000,
|
|
ErrorCode: api.ErrorCodeDatabaseError,
|
|
ErrorMessage: "Failed to enqueue task",
|
|
ErrorDetails: "database connection refused",
|
|
},
|
|
},
|
|
{
|
|
name: "data",
|
|
packet: &api.ResponsePacket{
|
|
PacketType: api.PacketTypeData,
|
|
Timestamp: 1_732_000_000,
|
|
DataType: "status",
|
|
DataPayload: benchmarkDataPayload,
|
|
},
|
|
},
|
|
{
|
|
name: "progress",
|
|
packet: &api.ResponsePacket{
|
|
PacketType: api.PacketTypeProgress,
|
|
Timestamp: 1_732_000_000,
|
|
ProgressType: api.ProgressTypePercentage,
|
|
ProgressValue: 42,
|
|
ProgressTotal: 100,
|
|
ProgressMessage: "running",
|
|
},
|
|
},
|
|
}
|
|
|
|
func BenchmarkResponsePacketSerialize(b *testing.B) {
|
|
for _, variant := range benchmarkPackets {
|
|
variant := variant
|
|
b.Run(variant.name+"/current", func(b *testing.B) {
|
|
benchmarkSerializePacket(b, variant.packet)
|
|
})
|
|
b.Run(variant.name+"/legacy", func(b *testing.B) {
|
|
benchmarkLegacySerializePacket(b, variant.packet)
|
|
})
|
|
}
|
|
}
|
|
|
|
func benchmarkSerializePacket(b *testing.B, packet *api.ResponsePacket) {
|
|
b.Helper()
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := packet.Serialize(); err != nil {
|
|
b.Fatalf("serialize failed: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func benchmarkLegacySerializePacket(b *testing.B, packet *api.ResponsePacket) {
|
|
b.Helper()
|
|
b.ReportAllocs()
|
|
for b.Loop() {
|
|
if _, err := legacySerializePacket(packet); err != nil {
|
|
b.Fatalf("legacy serialize failed: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func legacySerializePacket(p *api.ResponsePacket) ([]byte, error) {
|
|
var buf []byte
|
|
|
|
buf = append(buf, p.PacketType)
|
|
|
|
timestampBytes := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(timestampBytes, p.Timestamp)
|
|
buf = append(buf, timestampBytes...)
|
|
|
|
switch p.PacketType {
|
|
case api.PacketTypeSuccess:
|
|
buf = append(buf, legacySerializeString(p.SuccessMessage)...)
|
|
|
|
case api.PacketTypeError:
|
|
buf = append(buf, p.ErrorCode)
|
|
buf = append(buf, legacySerializeString(p.ErrorMessage)...)
|
|
buf = append(buf, legacySerializeString(p.ErrorDetails)...)
|
|
|
|
case api.PacketTypeProgress:
|
|
buf = append(buf, p.ProgressType)
|
|
valueBytes := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(valueBytes, p.ProgressValue)
|
|
buf = append(buf, valueBytes...)
|
|
|
|
totalBytes := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(totalBytes, p.ProgressTotal)
|
|
buf = append(buf, totalBytes...)
|
|
|
|
buf = append(buf, legacySerializeString(p.ProgressMessage)...)
|
|
|
|
case api.PacketTypeStatus:
|
|
buf = append(buf, legacySerializeString(p.StatusData)...)
|
|
|
|
case api.PacketTypeData:
|
|
buf = append(buf, legacySerializeString(p.DataType)...)
|
|
buf = append(buf, legacySerializeBytes(p.DataPayload)...)
|
|
|
|
case api.PacketTypeLog:
|
|
buf = append(buf, p.LogLevel)
|
|
buf = append(buf, legacySerializeString(p.LogMessage)...)
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unknown packet type: %d", p.PacketType)
|
|
}
|
|
|
|
return buf, nil
|
|
}
|
|
|
|
func legacySerializeString(s string) []byte {
|
|
length := uint16(len(s))
|
|
buf := make([]byte, 2+len(s))
|
|
binary.BigEndian.PutUint16(buf[:2], length)
|
|
copy(buf[2:], s)
|
|
return buf
|
|
}
|
|
|
|
func legacySerializeBytes(b []byte) []byte {
|
|
length := uint32(len(b))
|
|
buf := make([]byte, 4+len(b))
|
|
binary.BigEndian.PutUint32(buf[:4], length)
|
|
copy(buf[4:], b)
|
|
return buf
|
|
}
|