235 lines
6.1 KiB
Go
235 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"math"
|
|
"math/rand"
|
|
"os"
|
|
"runtime"
|
|
"sort"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// Workload functions
|
|
|
|
func performIntegerArithmetic(iterations int) {
|
|
result := 0
|
|
for i := 0; i < iterations; i++ {
|
|
result += i * i
|
|
}
|
|
_ = result
|
|
}
|
|
|
|
func performFloatingPointArithmetic(iterations int) {
|
|
result := 0.0
|
|
for i := 0; i < iterations; i++ {
|
|
result += math.Sin(float64(i)) * math.Cos(float64(i))
|
|
}
|
|
_ = result
|
|
}
|
|
|
|
func performSorting(iterations int) {
|
|
for i := 0; i < iterations; i++ {
|
|
data := make([]int, 100)
|
|
for j := range data {
|
|
data[j] = rand.Intn(1000)
|
|
}
|
|
sort.Ints(data)
|
|
}
|
|
}
|
|
|
|
func performHashing(iterations int) {
|
|
data := []byte("initial-hash-data")
|
|
for i := 0; i < iterations; i++ {
|
|
hash := sha256.Sum256(data)
|
|
data = hash[:]
|
|
}
|
|
}
|
|
|
|
// Compression throughput: Fixed duration
|
|
func performCompressionThroughput(duration time.Duration) float64 {
|
|
data := bytes.Repeat([]byte("compress-this-data"), 10) // Data to compress (200 bytes)
|
|
var buf bytes.Buffer
|
|
totalBytes := 0
|
|
start := time.Now()
|
|
|
|
for {
|
|
buf.Reset()
|
|
writer := gzip.NewWriter(&buf)
|
|
_, err := writer.Write(data)
|
|
if err != nil {
|
|
fmt.Println("Error during compression:", err)
|
|
return 0
|
|
}
|
|
_ = writer.Close()
|
|
totalBytes += len(data)
|
|
|
|
if time.Since(start) >= duration {
|
|
break
|
|
}
|
|
}
|
|
|
|
elapsed := time.Since(start).Seconds()
|
|
return float64(totalBytes) / elapsed // Bytes per second
|
|
}
|
|
|
|
// Benchmarking
|
|
|
|
func benchmark(task func(int), iterations int, cores int) float64 {
|
|
var wg sync.WaitGroup
|
|
wg.Add(cores)
|
|
start := time.Now()
|
|
|
|
for i := 0; i < cores; i++ {
|
|
go func() {
|
|
task(iterations / cores)
|
|
wg.Done()
|
|
}()
|
|
}
|
|
|
|
wg.Wait()
|
|
duration := time.Since(start).Seconds()
|
|
return float64(iterations) / duration // Return raw score
|
|
}
|
|
|
|
func humanReadable(score float64, unit string) string {
|
|
units := []string{"", "K", "M", "G", "T"}
|
|
i := 0
|
|
for score >= 1000 && i < len(units)-1 {
|
|
score /= 1000
|
|
i++
|
|
}
|
|
return fmt.Sprintf("%.2f %s%s", score, units[i], unit)
|
|
}
|
|
|
|
func percentageDiff(current, baseline float64) string {
|
|
diff := (current - baseline) / baseline * 100
|
|
return fmt.Sprintf("%+.2f%%", diff)
|
|
}
|
|
|
|
// Encode results into a compact binary format
|
|
func encodeBaseline(results map[string]float64) string {
|
|
values := []float64{
|
|
results["Integer Arithmetic-single"], results["Integer Arithmetic-multi"],
|
|
results["Floating Point Math-single"], results["Floating Point Math-multi"],
|
|
results["Sorting-single"], results["Sorting-multi"],
|
|
results["SHA-256 Hashing-single"], results["SHA-256 Hashing-multi"],
|
|
results["Compression-single"],
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
for _, v := range values {
|
|
// Scale down to save precision (e.g., fixed point)
|
|
scaled := int32(v / 1000) // Scale down by 1000
|
|
binary.Write(buf, binary.LittleEndian, scaled)
|
|
}
|
|
return base64.StdEncoding.EncodeToString(buf.Bytes())
|
|
}
|
|
|
|
// Decode a compact binary baseline
|
|
func decodeBaseline(encoded string) (map[string]float64, error) {
|
|
data, err := base64.StdEncoding.DecodeString(encoded)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
values := make([]float64, 9)
|
|
buf := bytes.NewReader(data)
|
|
for i := 0; i < 9; i++ {
|
|
var scaled int32
|
|
err = binary.Read(buf, binary.LittleEndian, &scaled)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
values[i] = float64(scaled) * 1000 // Scale back up
|
|
}
|
|
|
|
return map[string]float64{
|
|
"Integer Arithmetic-single": values[0], "Integer Arithmetic-multi": values[1],
|
|
"Floating Point Math-single": values[2], "Floating Point Math-multi": values[3],
|
|
"Sorting-single": values[4], "Sorting-multi": values[5],
|
|
"SHA-256 Hashing-single": values[6], "SHA-256 Hashing-multi": values[7],
|
|
"Compression-single": values[8],
|
|
}, nil
|
|
}
|
|
|
|
func main() {
|
|
iterations := 1_000_000 // Adjustable workload size
|
|
cores := runtime.NumCPU()
|
|
|
|
workloads := map[string]func(int){
|
|
"Integer Arithmetic": performIntegerArithmetic,
|
|
"Floating Point Math": performFloatingPointArithmetic,
|
|
"Sorting": performSorting,
|
|
"SHA-256 Hashing": performHashing,
|
|
}
|
|
|
|
// Add compression workload with fixed duration
|
|
compressionDuration := 3 * time.Second // Fixed duration for compression test
|
|
fmt.Printf("\nCompression test duration: %s\n", compressionDuration)
|
|
|
|
// Baseline comparison setup
|
|
var baseline map[string]float64
|
|
if len(os.Args) > 1 {
|
|
var err error
|
|
baseline, err = decodeBaseline(os.Args[1])
|
|
if err != nil {
|
|
fmt.Println("Error parsing baseline:", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// Results storage
|
|
results := make(map[string]float64)
|
|
|
|
fmt.Println("Starting Extended CPU Benchmark...")
|
|
|
|
for name, workload := range workloads {
|
|
fmt.Printf("\nRunning %s benchmark...\n", name)
|
|
|
|
// Single-core benchmark
|
|
fmt.Println("Single-core performance:")
|
|
singleCoreScore := benchmark(workload, iterations, 1)
|
|
results[name+"-single"] = singleCoreScore
|
|
if baseline != nil {
|
|
fmt.Printf(" Single-core score: %s (%s)\n",
|
|
humanReadable(singleCoreScore, "ops/sec"),
|
|
percentageDiff(singleCoreScore, baseline[name+"-single"]))
|
|
} else {
|
|
fmt.Printf(" Single-core score: %s\n", humanReadable(singleCoreScore, "ops/sec"))
|
|
}
|
|
|
|
// Multi-core benchmark
|
|
fmt.Println("Multi-core performance:")
|
|
multiCoreScore := benchmark(workload, iterations, cores)
|
|
results[name+"-multi"] = multiCoreScore
|
|
if baseline != nil {
|
|
fmt.Printf(" Multi-core score: %s (%s) using %d cores\n",
|
|
humanReadable(multiCoreScore, "ops/sec"),
|
|
percentageDiff(multiCoreScore, baseline[name+"-multi"]),
|
|
cores)
|
|
} else {
|
|
fmt.Printf(" Multi-core score: %s using %d cores\n",
|
|
humanReadable(multiCoreScore, "ops/sec"), cores)
|
|
}
|
|
}
|
|
|
|
// Compression throughput
|
|
fmt.Println("\nRunning Compression throughput benchmark...")
|
|
singleCompressionScore := performCompressionThroughput(compressionDuration)
|
|
results["Compression-single"] = singleCompressionScore
|
|
fmt.Printf(" Single-core compression: %s\n", humanReadable(singleCompressionScore, "B/s"))
|
|
|
|
// Output compact results for future runs
|
|
compactResults := encodeBaseline(results)
|
|
fmt.Printf("\nCompact results for future comparison: %s\n", compactResults)
|
|
|
|
fmt.Println("\nExtended CPU Benchmark Completed.")
|
|
}
|