timingbench/bench_test.go

153 lines
3.2 KiB
Go

package timingbench
import (
"context"
"math/rand"
"testing"
"time"
)
// isPrime checks if a number is a prime number.
func isPrime(n int) bool {
if n <= 1 {
return false
}
for i := 2; i*i <= n; i++ {
if n%i == 0 {
return false
}
}
return true
}
// randomSleep introduces a random delay between 1 and 20 milliseconds.
func randomSleep() {
time.Sleep(time.Duration(rand.Intn(20)+1) * time.Millisecond)
}
// generatePrimes generates prime numbers up to a given limit.
func generatePrimes(limit int) []int {
primes := []int{}
for i := 2; i <= limit; i++ {
if isPrime(i) {
primes = append(primes, i)
}
}
return primes
}
// sortRandomSlice generates a slice with random integers and sorts it.
func sortRandomSlice(size int) {
slice := make([]int, size)
for i := range slice {
slice[i] = rand.Intn(10000)
}
quickSort(slice)
}
// quickSort sorts a slice of integers using the quicksort algorithm.
func quickSort(arr []int) {
if len(arr) < 2 {
return
}
left, right := 0, len(arr)-1
pivotIndex := rand.Int() % len(arr)
arr[pivotIndex], arr[right] = arr[right], arr[pivotIndex]
for i := range arr {
if arr[i] < arr[right] {
arr[i], arr[left] = arr[left], arr[i]
left++
}
}
arr[left], arr[right] = arr[right], arr[left]
quickSort(arr[:left])
quickSort(arr[left+1:])
}
// sampleFunction performs a mix of different operations to introduce variability in runtime.
func sampleFunction() {
randomSleep()
generatePrimes(500 + rand.Intn(1500))
sortRandomSlice(500 + rand.Intn(1500))
multiplyMatrices(20 + rand.Intn(10))
}
func TestTimeFunction(t *testing.T) {
// Define the number of iterations.
iterations := 700
// Create a context with a timeout for cancellation.
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()
// Measure the execution times of the sample function.
result, err := TimeFunction(ctx, sampleFunction, iterations)
if err != nil {
t.Fatalf("Error measuring function: %v", err)
}
// Print the timing results.
t.Logf(result.String())
}
func multiplyMatrices(size int) int {
matrixA := make([][]int, size)
matrixB := make([][]int, size)
result := make([][]int, size)
for i := 0; i < size; i++ {
matrixA[i] = make([]int, size)
matrixB[i] = make([]int, size)
result[i] = make([]int, size)
for j := 0; j < size; j++ {
matrixA[i][j] = rand.Intn(10)
matrixB[i][j] = rand.Intn(10)
}
}
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
sum := 0
for k := 0; k < size; k++ {
sum += matrixA[i][k] * matrixB[k][j]
}
result[i][j] = sum
}
}
// sum the result matrix
sum := 0
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
sum += result[i][j]
}
}
return sum
}
func TestMatrixMultiply(t *testing.T) {
// Define the matrix size and number of iterations.
matrixSize := 11
iterations := 1000000
// Create a context with a timeout for cancellation.
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
// Measure the execution times of the matrix multiplication function.
result, err := TimeFunction(ctx, func() {
_ = multiplyMatrices(matrixSize)
}, iterations)
if err != nil {
t.Fatalf("Error measuring function: %v", err)
}
// Print the timing results.
t.Logf(result.String())
}