Performance Testing of MySQL Using GORM and the FunTester Framework in Go
This article demonstrates how to use the Go-based FunTester framework to conduct performance tests—select, insert, update, and delete—on MySQL through GORM, providing code examples and explaining the setup of the testing harness.
In a previous article titled Go Language GORM Framework MySQL Practice , basic operations of GORM with MySQL were covered. This article shares a simple practice for directly performance‑testing MySQL using the GORM framework.
Framework Support
The author uses a lightweight Go testing framework called FunTester . The framework leverages Go's closures and function‑parameter features, treating a func() as the performance‑test subject and repeatedly executing it. An alternative approach is to run a multithreaded task similar to the Java abstract class com.funtester.base.constaint.ThreadBase , allowing more test scenarios.
// ExecuteRoutineTimes
// @Description: FunTester performance test execution framework
// @param fun function to execute
// @param times number of executions per thread
// @param thread number of concurrent threads
func ExecuteRoutineTimes(fun func(), t int, r int) {
c := make(chan int) // confirm all threads finish
key := false // control all threads to finish together
start := futil.Milli()
for i := 0; i < r; i++ {
go func() {
sum := 0
for i := 0; i < t; i++ {
if key {
break
}
fun()
sum++
}
key = true
c <- sum
}()
}
total := 0
for i := 0; i < r; i++ {
num := <-c
total += num
}
end := futil.Milli()
diff := end - start
//total := thread * times
log.Printf("Total time: %f", float64(diff)/1000)
log.Printf("Total requests: %d", total)
log.Printf("QPS: %f", float64(total)/float64(diff)*1000.0)
}select
The following demonstrates a performance test for a SELECT operation using random ID queries.
func TestSelectP(t *testing.T) {
execute.ExecuteRoutineTimes(func() {
var f Funtester
drive.Where("id = ?", futil.RangInt(35, 20000)).First(&f)
}, 1000, 100)
}delete
This test deletes records using incrementally increasing IDs starting from 35.
func TestDeleteP(t *testing.T) {
var index int32 = 35
execute.ExecuteRoutineTimes(func() {
id := atomic.AddInt32(&index, 1)
drive.Where("id = ?", id).Delete(&Funtester{})
}, 1000, 100)
}update
The update test reuses the SELECT scenario, picking a random ID and updating the name field with a random 10‑character string.
func TestUpdateP(t *testing.T) {
execute.ExecuteRoutineTimes(func() {
drive.Where("id = ?", futil.RangInt(35, 20000)).Update("name", futil.RandomStr(10))
}, 1000, 100)
}insert
The insert test creates records with randomly generated fields using the FunTester struct.
func TestInsertP(t *testing.T) {
execute.ExecuteRoutineTimes(func() {
drive.Create(&Funtester{Name: futil.RandomStr(10), Age: futil.RandomInt(100)})
}, 1000, 100)
}FunTester Constructor
type Funtester struct {
gorm.Model
Name string
Age int
}All performance tests use the basic GORM API; connection‑pool management is delegated entirely to GORM. This is comparable to configuring an HTTP client’s connection pool, showing how powerful frameworks can be simple to use.
For fundamental GORM usage, refer to the previous article Go Language GORM Framework MySQL Practice .
Have Fun ~ Tester !
FunTester 2021 Summary
FunTester Original Works
Performance Test Series – FunTester Original
FunTester
10k followers, 1k articles | completely useless
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.