mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 18:37:26 +08:00
176 lines
3.5 KiB
Go
176 lines
3.5 KiB
Go
//
|
|
// main.go
|
|
//
|
|
// Copyright (c) 2019-2023 Markku Rossi
|
|
//
|
|
// All rights reserved.
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"math"
|
|
"os"
|
|
"runtime/pprof"
|
|
"strings"
|
|
|
|
"source.quilibrium.com/quilibrium/monorepo/bedlam/compiler"
|
|
"source.quilibrium.com/quilibrium/monorepo/bedlam/compiler/utils"
|
|
)
|
|
|
|
var template = `
|
|
package main
|
|
|
|
func main(a, b int%d) int {
|
|
return a * b
|
|
}
|
|
`
|
|
|
|
type result struct {
|
|
bits int
|
|
bestLimit int
|
|
bestCost uint64
|
|
worstLimit int
|
|
worstCost uint64
|
|
costs []uint64
|
|
}
|
|
|
|
func main() {
|
|
numWorkers := flag.Int("workers", 8, "number of workers")
|
|
startBits := flag.Int("start", 8, "start bit count")
|
|
endBits := flag.Int("end", 0xffffffff, "end bit count")
|
|
minLimit := flag.Int("min", 8, "treshold minimum limit")
|
|
maxLimit := flag.Int("max", 22, "treshold maximum limit")
|
|
cpuprofile := flag.String("cpuprofile", "", "write cpu profile to `file`")
|
|
flag.Parse()
|
|
|
|
if len(*cpuprofile) > 0 {
|
|
f, err := os.Create(*cpuprofile)
|
|
if err != nil {
|
|
log.Fatal("could not create CPU profile: ", err)
|
|
}
|
|
defer f.Close()
|
|
if err := pprof.StartCPUProfile(f); err != nil {
|
|
log.Fatal("could not start CPU profile: ", err)
|
|
}
|
|
defer pprof.StopCPUProfile()
|
|
}
|
|
|
|
results := make(map[int]*result)
|
|
ch := make(chan *result)
|
|
|
|
for i := 0; i < *numWorkers; i++ {
|
|
go func(bits int) {
|
|
for ; bits <= *endBits; bits += *numWorkers {
|
|
code := fmt.Sprintf(template, bits)
|
|
var bestLimit int
|
|
var bestCost uint64
|
|
var worstLimit int
|
|
var worstCost uint64
|
|
var costs []uint64
|
|
|
|
params := utils.NewParams()
|
|
|
|
for limit := *minLimit; limit <= *maxLimit; limit++ {
|
|
params.CircMultArrayTreshold = limit
|
|
circ, _, err := compiler.New(params).Compile(code, nil)
|
|
if err != nil {
|
|
log.Fatalf("Compilation %d:%d failed: %s\n%s",
|
|
bits, limit, err, code)
|
|
}
|
|
cost := circ.Cost()
|
|
costs = append(costs, cost)
|
|
|
|
if bestCost == 0 || cost < bestCost ||
|
|
(limit == 21 && cost <= bestCost) {
|
|
bestCost = cost
|
|
bestLimit = limit
|
|
}
|
|
if cost > worstCost {
|
|
worstCost = cost
|
|
worstLimit = limit
|
|
}
|
|
}
|
|
ch <- &result{
|
|
bits: bits,
|
|
bestLimit: bestLimit,
|
|
bestCost: bestCost,
|
|
worstLimit: worstLimit,
|
|
worstCost: worstCost,
|
|
costs: costs,
|
|
}
|
|
}
|
|
}(*startBits + i)
|
|
}
|
|
|
|
next := *startBits
|
|
|
|
outer:
|
|
for result := range ch {
|
|
results[result.bits] = result
|
|
for {
|
|
r, ok := results[next]
|
|
if !ok {
|
|
break
|
|
}
|
|
if r.bestLimit == 21 {
|
|
fmt.Printf("\t// %d: %d, %10d\t%.4f\t%s\n",
|
|
r.bits, r.bestLimit,
|
|
r.bestCost, float64(r.bestCost)/float64(r.worstCost),
|
|
Sparkline(r.costs))
|
|
} else {
|
|
fmt.Printf("\t%d: %d, // %10d\t%.4f\t%s\n",
|
|
r.bits, r.bestLimit,
|
|
r.bestCost, float64(r.bestCost)/float64(r.worstCost),
|
|
Sparkline(r.costs))
|
|
}
|
|
if next >= *endBits {
|
|
break outer
|
|
}
|
|
next++
|
|
}
|
|
}
|
|
}
|
|
|
|
// Sparkline creates a histogram chart of values. The chart is scaled
|
|
// to [min...max] containing differences between values.
|
|
func Sparkline(values []uint64) string {
|
|
if len(values) == 0 {
|
|
return ""
|
|
}
|
|
|
|
var min uint64 = math.MaxUint64
|
|
var max uint64
|
|
|
|
for _, v := range values {
|
|
if v < min {
|
|
min = v
|
|
}
|
|
if v > max {
|
|
max = v
|
|
}
|
|
}
|
|
delta := max - min
|
|
|
|
var sb strings.Builder
|
|
for _, v := range values {
|
|
var tick uint64
|
|
if delta == 0 {
|
|
tick = 4
|
|
} else {
|
|
tick = (v - min) * 7 / delta
|
|
}
|
|
if v == min && false {
|
|
sb.WriteString("\x1b[92m")
|
|
sb.WriteRune(rune(0x2581 + tick))
|
|
sb.WriteString("\x1b[0m")
|
|
} else {
|
|
sb.WriteRune(rune(0x2581 + tick))
|
|
}
|
|
}
|
|
return sb.String()
|
|
}
|