Files
p256k1/field_bench_test.go
mleku 14dc85cdc3 Add BMI2/AVX2 field assembly and SIMD comparison benchmarks
- Port field operations assembler from libsecp256k1 (field_amd64.s,
    field_amd64_bmi2.s) with MULX/ADCX/ADOX instructions
  - Add AVX2 scalar and affine point operations in avx/ package
  - Implement CPU feature detection (cpufeatures.go) for AVX2/BMI2
  - Add libsecp256k1.so via purego for native C library comparison
  - Create comprehensive SIMD benchmark suite comparing btcec, P256K1
    pure Go, P256K1 ASM, and libsecp256k1
  - Add BENCHMARK_SIMD.md documenting performance across implementations
  - Remove BtcecSigner, consolidate on P256K1Signer as primary impl
  - Add field operation tests and benchmarks (field_asm_test.go,
    field_bench_test.go)
  - Update GLV endomorphism with wNAF scalar multiplication
  - Add scalar assembly (scalar_amd64.s) for optimized operations
  - Clean up dependencies and update benchmark reports
2025-11-29 08:11:13 +00:00

103 lines
2.4 KiB
Go

package p256k1
import (
"testing"
)
var benchFieldA = FieldElement{
n: [5]uint64{0x4567890abcdef, 0xcba9876543210, 0x3456789abcdef, 0xcba0987654321, 0x123456789ab},
magnitude: 1,
normalized: true,
}
var benchFieldB = FieldElement{
n: [5]uint64{0xdef1234567890, 0x6543210fedcba, 0xcba1234567890, 0x7654321abcdef, 0xfedcba98765},
magnitude: 1,
normalized: true,
}
// BenchmarkFieldMulAsm benchmarks the assembly field multiplication
func BenchmarkFieldMulAsm(b *testing.B) {
if !hasFieldAsm() {
b.Skip("Assembly not available")
}
var r FieldElement
for i := 0; i < b.N; i++ {
fieldMulAsm(&r, &benchFieldA, &benchFieldB)
}
}
// BenchmarkFieldMulPureGo benchmarks the pure Go field multiplication
func BenchmarkFieldMulPureGo(b *testing.B) {
var r FieldElement
for i := 0; i < b.N; i++ {
fieldMulPureGo(&r, &benchFieldA, &benchFieldB)
}
}
// BenchmarkFieldSqrAsm benchmarks the assembly field squaring
func BenchmarkFieldSqrAsm(b *testing.B) {
if !hasFieldAsm() {
b.Skip("Assembly not available")
}
var r FieldElement
for i := 0; i < b.N; i++ {
fieldSqrAsm(&r, &benchFieldA)
}
}
// BenchmarkFieldSqrPureGo benchmarks the pure Go field squaring (via mul)
func BenchmarkFieldSqrPureGo(b *testing.B) {
var r FieldElement
for i := 0; i < b.N; i++ {
fieldMulPureGo(&r, &benchFieldA, &benchFieldA)
}
}
// BenchmarkFieldMul benchmarks the full mul method (which uses assembly when available)
func BenchmarkFieldMul(b *testing.B) {
r := new(FieldElement)
a := benchFieldA
bb := benchFieldB
for i := 0; i < b.N; i++ {
r.mul(&a, &bb)
}
}
// BenchmarkFieldSqr benchmarks the full sqr method (which uses assembly when available)
func BenchmarkFieldSqr(b *testing.B) {
r := new(FieldElement)
a := benchFieldA
for i := 0; i < b.N; i++ {
r.sqr(&a)
}
}
// BMI2 benchmarks
// BenchmarkFieldMulAsmBMI2 benchmarks the BMI2 assembly field multiplication
func BenchmarkFieldMulAsmBMI2(b *testing.B) {
if !hasFieldAsmBMI2() {
b.Skip("BMI2+ADX assembly not available")
}
var r FieldElement
for i := 0; i < b.N; i++ {
fieldMulAsmBMI2(&r, &benchFieldA, &benchFieldB)
}
}
// BenchmarkFieldSqrAsmBMI2 benchmarks the BMI2 assembly field squaring
func BenchmarkFieldSqrAsmBMI2(b *testing.B) {
if !hasFieldAsmBMI2() {
b.Skip("BMI2+ADX assembly not available")
}
var r FieldElement
for i := 0; i < b.N; i++ {
fieldSqrAsmBMI2(&r, &benchFieldA)
}
}