Added plan of tests

This commit is contained in:
Alexander Pivkin
2025-12-20 10:21:45 +03:00
parent a889e1c7dd
commit 640a6d2a46
171 changed files with 57454 additions and 0 deletions
@@ -0,0 +1,127 @@
package benchmarks
import (
"context"
"database/sql"
"log"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
sqlc "github.com/rexfordnyrk/go-db-comparison/benchmarks/sqlc_generated"
)
func init() {
var err error
// Opening a database connection.
db, err = sql.Open("mysql", "theuser:thepass@tcp(localhost:3306)/thedb?multiStatements=true&parseTime=true")
if err != nil {
panic(err)
}
//sqlx connection using existing db connection
dbx = sqlx.NewDb(db, "mysql")
//sqlc connection using existing db connection
dbc = sqlc.New(db)
//gorm connection using existing db connection
gdb, err = gorm.Open(mysql.New(mysql.Config{Conn: db}))
if err != nil {
panic(err)
}
}
var (
gdb *gorm.DB
db *sql.DB
dbx *sqlx.DB
dbc *sqlc.Queries
)
func setup() {
clear()
table := `CREATE TABLE students (
id bigint NOT NULL AUTO_INCREMENT,
fname varchar(50) not null,
lname varchar(50) not null,
date_of_birth datetime not null,
email varchar(50) not null,
address varchar(50) not null,
gender varchar(50) not null,
PRIMARY KEY (id)
);`
_, err := db.Exec(table)
if err != nil {
panic(err)
}
//inserting records
_, err = db.Exec(records)
if err != nil {
panic(err)
}
}
func clear() {
_, err := db.Exec(`DROP TABLE IF EXISTS students;`)
if err != nil {
panic(err)
}
}
type Student struct {
ID int64
Fname string
Lname string
DateOfBirth time.Time `db:"date_of_birth"`
Email string
Address string
Gender string
}
func DbSqlQueryStudentWithLimit(limit int) {
var students []Student
rows, err := db.Query("SELECT * FROM students limit ?", limit)
if err != nil {
log.Fatalf("DbSqlQueryStudentWithLimit %d %v", limit, err)
}
defer rows.Close()
// Loop through rows, using Scan to assign column data to struct fields.
for rows.Next() {
var s Student
if err := rows.Scan(&s.ID, &s.Fname, &s.Lname, &s.DateOfBirth, &s.Email, &s.Address, &s.Gender); err != nil {
log.Fatalf("DbSqlQueryStudentWithLimit %d %v", limit, err)
}
students = append(students, s)
}
if err := rows.Err(); err != nil {
log.Fatalf("DbSqlQueryStudentWithLimit %d %v", limit, err)
}
}
func SqlxQueryStudentWithLimit(limit int) {
var students []Student
err := dbx.Select(&students, "SELECT * FROM students LIMIT ?", limit)
if err != nil {
log.Fatalf("SqlxQueryStudentWithLimit %d %v", limit, err)
}
}
func SqlcQueryStudentWithLimit(limit int) {
_, err := dbc.FetchStudents(context.Background(), int32(limit))
if err != nil {
log.Fatalf("SqlcQueryStudentWithLimit %d %v", limit, err)
}
}
func GormQueryStudentWithLimit(limit int) {
var students []Student
if err := gdb.Limit(limit).Find(&students).Error; err != nil {
log.Fatalf("GormQueryStudentWithLimit %d %v", limit, err)
}
}
@@ -0,0 +1,55 @@
package benchmarks
import (
"fmt"
"testing"
)
func Benchmark(b *testing.B) {
setup()
defer clear()
// Benchmark goes in here
limits := []int{
1,
10,
100,
1000,
10000,
15000,
}
for _, lim := range limits { // Fetch varying number of rows
fmt.Printf("================================== BENCHMARKING %d RECORDS ======================================\n", lim)
// Benchmark Database/sql
b.Run(fmt.Sprintf("Database/sql limit:%d ", lim), func(b *testing.B) {
for i := 0; i < b.N; i++ {
DbSqlQueryStudentWithLimit(lim)
}
})
// Benchmark Sqlx
b.Run(fmt.Sprintf("Sqlx limit:%d ", lim), func(b *testing.B) {
for i := 0; i < b.N; i++ {
SqlxQueryStudentWithLimit(lim)
}
})
// Benchmark Sqlc
b.Run(fmt.Sprintf("Sqlc limit:%d ", lim), func(b *testing.B) {
for i := 0; i < b.N; i++ {
SqlcQueryStudentWithLimit(lim)
}
})
// Benchmark GORM
b.Run(fmt.Sprintf("GORM limit:%d ", lim), func(b *testing.B) {
for i := 0; i < b.N; i++ {
GormQueryStudentWithLimit(lim)
}
})
fmt.Println("=================================================================================================")
}
}
@@ -0,0 +1,31 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.16.0
package sqlc
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
}
}
@@ -0,0 +1,19 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.16.0
package sqlc
import (
"time"
)
type Student struct {
ID int64
Fname string
Lname string
DateOfBirth time.Time
Email string
Address string
Gender string
}
@@ -0,0 +1,2 @@
-- name: FetchStudents :many
SELECT * FROM students LIMIT ?;
@@ -0,0 +1,45 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.16.0
// source: query.sql
package sqlc
import (
"context"
)
const fetchStudents = `-- name: FetchStudents :many
SELECT id, fname, lname, date_of_birth, email, address, gender FROM students LIMIT ?
`
func (q *Queries) FetchStudents(ctx context.Context, limit int32) ([]Student, error) {
rows, err := q.db.QueryContext(ctx, fetchStudents, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Student
for rows.Next() {
var i Student
if err := rows.Scan(
&i.ID,
&i.Fname,
&i.Lname,
&i.DateOfBirth,
&i.Email,
&i.Address,
&i.Gender,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
@@ -0,0 +1,10 @@
CREATE TABLE `students` (
`id` bigint NOT NULL AUTO_INCREMENT,
`fname` varchar(50) not null,
`lname` varchar(50) not null,
`date_of_birth` datetime not null,
`email` varchar(50) not null,
`address` varchar(50) not null,
`gender` varchar(50) not null,
PRIMARY KEY (`id`)
);
@@ -0,0 +1,7 @@
version: 1
packages:
- path: "./"
name: "sqlc"
engine: "mysql"
schema: "schema.sql"
queries: "query.sql"
File diff suppressed because it is too large Load Diff