mirror of
https://github.com/luxfi/mlwe.git
synced 2026-10-30 15:24:54 +00:00
One Benchmark per operation. Pack/Unpack over the real FIPS 204 widths (4/10/13/20-bit) on N=256; ReadVector reuses the package's WriteVector/putU64/getU64 framing helpers so the benched decoder is the round-trip-tested one. ReportAllocs + ResetTimer-after-setup throughout.
88 lines
2.4 KiB
Go
88 lines
2.4 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package codec
|
|
|
|
// Decomplected benchmark suite for the bit codec and bounded framing.
|
|
// Each Benchmark isolates EXACTLY ONE operation.
|
|
//
|
|
// - PackBits / UnpackBits are benched over the real FIPS 204 widths
|
|
// (4-bit w1, 10-bit t1, 13-bit t0, 20-bit gamma1) on a full N=256
|
|
// polynomial, since their cost is N*bits.
|
|
// - ReadVector is benched once at a representative element count; it
|
|
// reuses the package test's getU64/WriteVector framing helpers so the
|
|
// decoder under test is the exact one the round-trip test exercises.
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"math/rand"
|
|
"testing"
|
|
)
|
|
|
|
var benchWidths = []int{4, 10, 13, 20}
|
|
|
|
// benchCoeffs returns 256 coefficients masked to the given bit width.
|
|
func benchCoeffs(bits int) []uint64 {
|
|
rng := rand.New(rand.NewSource(int64(bits)))
|
|
mask := uint64(1)<<uint(bits) - 1
|
|
c := make([]uint64, 256)
|
|
for i := range c {
|
|
c[i] = rng.Uint64() & mask
|
|
}
|
|
return c
|
|
}
|
|
|
|
// BenchmarkPackBits measures one Pack of a 256-coefficient polynomial,
|
|
// per FIPS 204 bit width.
|
|
func BenchmarkPackBits(b *testing.B) {
|
|
for _, bits := range benchWidths {
|
|
c := benchCoeffs(bits)
|
|
b.Run(fmt.Sprintf("%dbit", bits), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
PackBits(c, bits)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkUnpackBits measures one Unpack back to 256 coefficients, per
|
|
// FIPS 204 bit width.
|
|
func BenchmarkUnpackBits(b *testing.B) {
|
|
for _, bits := range benchWidths {
|
|
data := PackBits(benchCoeffs(bits), bits)
|
|
b.Run(fmt.Sprintf("%dbit", bits), func(b *testing.B) {
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
UnpackBits(data, 256, bits)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// BenchmarkReadVector measures one bounded-frame read of 256 u64
|
|
// elements. The frame is built once (setup) with WriteVector/putU64; the
|
|
// timed loop wraps a fresh reader over it and reads via getU64.
|
|
func BenchmarkReadVector(b *testing.B) {
|
|
const n = 256
|
|
var buf bytes.Buffer
|
|
elems := make([]uint64, n)
|
|
for i := range elems {
|
|
elems[i] = uint64(i)
|
|
}
|
|
if err := WriteVector(&buf, elems, putU64); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
data := buf.Bytes()
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := ReadVector(bytes.NewReader(data), n, getU64); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|