Skip to content

Commit 8d13050

Browse files
committed
Merge branch 'feature/performance' into develop
2 parents 94d1e97 + 018b0a0 commit 8d13050

10 files changed

Lines changed: 589 additions & 97 deletions

File tree

.github/workflows/release-build.yml

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,22 @@ on:
44

55
name: Build & release
66
jobs:
7+
test:
8+
name: Tests
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v6
12+
13+
- uses: actions/setup-go@v5
14+
with:
15+
go-version-file: go.mod
16+
17+
- name: Run tests
18+
run: go test ./... -v
19+
720
releases-matrix:
821
name: Build
22+
needs: test
923
runs-on: ubuntu-latest
1024
strategy:
1125
matrix:
@@ -19,19 +33,19 @@ jobs:
1933
- goarch: arm
2034
goos: windows
2135
steps:
22-
- uses: actions/checkout@v6
36+
- uses: actions/checkout@v6
2337

24-
# build the binaries
25-
- uses: wangyoucao577/go-release-action@v1.55
26-
with:
27-
github_token: ${{ secrets.GITHUB_TOKEN }}
28-
goos: ${{ matrix.goos }}
29-
goarch: ${{ matrix.goarch }}
30-
binary_name: "wireguard-vanity-keygen"
31-
pre_command: export CGO_ENABLED=0
32-
asset_name: wireguard-vanity-keygen-${{ matrix.goos }}-${{ matrix.goarch }}
33-
extra_files: LICENSE README.md
34-
md5sum: false
35-
overwrite: true
36-
retry: 5
37-
ldflags: -w -X "main.appVersion=${{ github.ref_name }}"
38+
# build the binaries
39+
- uses: wangyoucao577/go-release-action@v1.55
40+
with:
41+
github_token: ${{ secrets.GITHUB_TOKEN }}
42+
goos: ${{ matrix.goos }}
43+
goarch: ${{ matrix.goarch }}
44+
binary_name: "wireguard-vanity-keygen"
45+
pre_command: export CGO_ENABLED=0
46+
asset_name: wireguard-vanity-keygen-${{ matrix.goos }}-${{ matrix.goarch }}
47+
extra_files: LICENSE README.md
48+
md5sum: false
49+
overwrite: true
50+
retry: 5
51+
ldflags: -w -X "main.appVersion=${{ github.ref_name }}"

.github/workflows/tests.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [develop, "feature/**"]
6+
pull_request:
7+
branches: [develop, "feature/**"]
8+
9+
jobs:
10+
test:
11+
name: Test
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v6
15+
16+
- uses: actions/setup-go@v5
17+
with:
18+
go-version-file: go.mod
19+
20+
- name: Run tests
21+
run: go test ./... -v

go.mod

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
module github.com/axllent/wireguard-vanity-keygen
22

3-
go 1.24.0
3+
go 1.25.0
44

55
require (
6+
github.com/axllent/ghru/v2 v2.2.0
67
github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729
78
github.com/spf13/pflag v1.0.10
89
)
910

10-
require golang.org/x/sys v0.40.0 // indirect
11+
require (
12+
golang.org/x/mod v0.34.0 // indirect
13+
golang.org/x/sys v0.42.0 // indirect
14+
)

go.sum

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
github.com/axllent/ghru/v2 v2.2.0 h1:DzWyWPJL+3qSwvR2S4tTetOhVgP9XjJixng1Aax8GGo=
2+
github.com/axllent/ghru/v2 v2.2.0/go.mod h1:tyH60pqmLCDHd3UMOZyiedrYMFVLwBQqPQ5y8WLvDzA=
13
github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729 h1:yfQ2sO9WJXUAIUR+g7NUkxJSKCAFJcR5sUDu+ZmjTZI=
24
github.com/oasisprotocol/curve25519-voi v0.0.0-20251114093237-2ab5a27a1729/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s=
35
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
46
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
5-
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
6-
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
7+
golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI=
8+
golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY=
9+
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
10+
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=

keygen/crypto.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,12 @@ func (k *PrivateKey) Public() Key {
3838
var pub curve25519voi.MontgomeryPoint
3939
base := *curve25519voi.X25519_BASEPOINT
4040
s, err := scalar.NewFromBytesModOrder(k[:])
41-
if err != nil || s == nil {
41+
if err != nil {
4242
panic("invalid private key for scalar.NewFromBytesModOrder: " + err.Error())
4343
}
44+
if s == nil {
45+
panic("invalid private key for scalar.NewFromBytesModOrder: nil scalar")
46+
}
4447
pub.Mul(&base, s)
4548
return Key(pub)
4649
}

keygen/crypto_benchmark_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package keygen
22

33
import (
4+
"encoding/base64"
5+
"math"
6+
"runtime"
7+
"sync"
48
"testing"
59
)
610

@@ -13,3 +17,44 @@ func BenchmarkKeygenGenerationSpeed(b *testing.B) {
1317
}
1418
}
1519
}
20+
21+
// BenchmarkCrunchThroughput benchmarks concurrent crunch() throughput including
22+
// key generation, base64 encoding, case conversion, and prefix matching.
23+
// This reflects the worker pool design: fixed goroutines loop internally.
24+
func BenchmarkCrunchThroughput(b *testing.B) {
25+
opts := Options{Cores: runtime.NumCPU(), CaseSensitive: false}
26+
c := New(opts, 0)
27+
// Use a prefix that will never match so the counter never saturates
28+
c.WordMap["zzzz"] = &AtomicCounter{Value: math.MaxInt64}
29+
b.ResetTimer()
30+
b.RunParallel(func(pb *testing.PB) {
31+
buf := make([]byte, base64.StdEncoding.EncodedLen(KeySize)) // one per goroutine
32+
for pb.Next() {
33+
c.crunch(func(Pair) {}, buf)
34+
}
35+
})
36+
}
37+
38+
// BenchmarkGoroutinePerAttempt simulates the previous design where a new goroutine
39+
// was spawned for every single key attempt. Compare against BenchmarkCrunchThroughput
40+
// to quantify the goroutine lifecycle overhead that the worker pool eliminates.
41+
func BenchmarkGoroutinePerAttempt(b *testing.B) {
42+
cores := runtime.NumCPU()
43+
thread := make(chan int, cores)
44+
var wg sync.WaitGroup
45+
b.ResetTimer()
46+
for i := 0; i < b.N; i++ {
47+
thread <- 1
48+
wg.Add(1)
49+
go func() {
50+
defer wg.Done()
51+
k, err := newPrivateKey()
52+
if err != nil {
53+
panic(err)
54+
}
55+
_ = k.Public().String()
56+
<-thread
57+
}()
58+
}
59+
wg.Wait()
60+
}

0 commit comments

Comments
 (0)