Created
September 24, 2014 09:12
-
-
Save pantaluna/89ffe94ec30fb28d9fb8 to your computer and use it in GitHub Desktop.
databaselocked.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
# Filename: databaselocked.go | |
# Script | |
go get | |
go run databaselocked.go --addtestdata | |
go run databaselocked.go --updates | |
go run databaselocked.go --updates > updates.log 2>&1 | |
grep "ERROR" updates.log | |
*/ | |
package main | |
import ( | |
"database/sql" | |
"flag" | |
_ "github.com/mattn/go-sqlite3" | |
"log" | |
"os" | |
"runtime/pprof" | |
"strconv" | |
"sync" | |
"time" | |
) | |
var ( | |
flagSelects, flagUpdates, flagAddTestData *bool | |
gDb *sql.DB | |
//gDbMaxOpenConns = 2 | |
gnRuns = 750 | |
//gnRuns = 7500 | |
) | |
func init() { | |
flagAddTestData = flag.Bool("addtestdata", false, "flag --addtestdata: only add the test data") | |
flagSelects = flag.Bool("selects", false, "flag --selects: only do the sql selects") | |
flagUpdates = flag.Bool("updates", false, "flag --updates: only do the sql updates") | |
flag.Parse() | |
} | |
func main() { | |
log.Printf("cliflag addtestdata: %v\n", *flagAddTestData) | |
log.Printf("cliflag selects: %v\n", *flagSelects) | |
log.Printf("cliflag updates: %v\n", *flagUpdates) | |
// PPROF | |
log.Printf("Start CPU Profiling.\n") | |
fc, err := os.Create("cpuprofile.pprofdata") | |
if err != nil { | |
log.Fatal(err) | |
} | |
pprof.StartCPUProfile(fc) | |
// DB INIT | |
gDb, err = sql.Open("sqlite3", "databaselocked.sqlite") | |
if err != nil { | |
log.Fatal(err) | |
} | |
err = gDb.Ping() | |
if err != nil { | |
log.Fatal(err) | |
} | |
// Default=unlimited... | |
//gDb.SetMaxOpenConns(gDbMaxOpenConns) | |
// | |
if *flagAddTestData { | |
myDbAddTestData() | |
} | |
if *flagSelects { | |
myDbSelects() | |
} | |
if *flagUpdates { | |
myDbUpdates() | |
} | |
// PPROF | |
log.Printf("Stop CPU Profile.\n") | |
pprof.StopCPUProfile() | |
log.Printf("Take Heap Profile.\n") | |
fh, err := os.Create("heapprofile.pprofdata") | |
if err != nil { | |
log.Fatal(err) | |
} | |
pprof.WriteHeapProfile(fh) | |
fh.Close() | |
} | |
func myDbAddTestData() { | |
var ( | |
err error | |
id string | |
sSql string | |
stmnt *sql.Stmt | |
wg sync.WaitGroup | |
) | |
sSql = `DROP TABLE counters` | |
_, err = gDb.Exec(sSql) | |
sSql = ` | |
CREATE TABLE counters ( | |
id TEXT NOT NULL PRIMARY KEY, | |
description TEXT NOT NULL DEFAULT '' | |
)` | |
_, err = gDb.Exec(sSql) | |
if err != nil { | |
log.Fatal(err) | |
} | |
sSql = ` | |
INSERT INTO counters ( | |
id,description | |
) VALUES ( | |
'festivalcounter','initial description' | |
)` | |
_, err = gDb.Exec(sSql) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Printf("\nLOOP inserting %v rows (sequentially)\n", gnRuns) | |
sSql = ` | |
INSERT INTO counters ( | |
id,description | |
) VALUES( | |
?,? | |
)` | |
stmnt, err = gDb.Prepare(sSql) | |
for i := 0; i < gnRuns; i++ { | |
log.Printf("Row %v \n", i+1) | |
id = "fcl-0" + strconv.Itoa(i) | |
_, err = stmnt.Exec(id, "initial description "+id) | |
if err != nil { | |
log.Fatal(err) | |
} | |
} | |
// Wait for all go routines to complete. | |
wg.Wait() | |
} | |
func myDbSelects() { | |
var wg sync.WaitGroup | |
for i := 0; i < gnRuns; i++ { | |
wg.Add(1) | |
go func(myI int) { | |
var ( | |
err error | |
id, description string | |
sSql string | |
timeBegin, timeEnd time.Time | |
) | |
defer wg.Done() | |
// | |
timeBegin = time.Now() | |
id = "fcl-0" + strconv.Itoa(myI) | |
sSql = "SELECT description FROM counters WHERE id=? LIMIT 1" | |
err = gDb.QueryRow(sSql, id).Scan(&description) | |
if err != nil { | |
log.Printf("ERROR SQLSELECT: %v | %v | %v\n", err, id, sSql) | |
} | |
timeEnd = time.Now() | |
log.Printf("Elapsed %v | SQLSELECT %v \n", timeEnd.Sub(timeBegin), id) | |
}(i) | |
} | |
// Wait for all goroutines to complete. | |
wg.Wait() | |
} | |
func myDbUpdates() { | |
var wg sync.WaitGroup | |
for i := 0; i < gnRuns; i++ { | |
wg.Add(1) | |
go func(myI int) { | |
var ( | |
err error | |
id, description string | |
sSql string | |
//sqlResult sql.Result | |
sqlStmnt *sql.Stmt | |
timeBegin, timeEnd time.Time | |
) | |
defer wg.Done() | |
// | |
timeBegin = time.Now() | |
id = "fcl-0" + strconv.Itoa(myI) | |
description = "updated " + id + time.Now().String() | |
sSql = "UPDATE counters SET description=? WHERE id=?" | |
sqlStmnt, err = gDb.Prepare(sSql) | |
if err != nil { | |
log.Printf("ERROR SQLUPDATE Prepare(): %v | %v | %v \n", err, id, description) | |
return // EXIT THE GO FUNC | |
} | |
_, err = sqlStmnt.Exec(description, id) | |
if err != nil { | |
log.Printf("ERROR SQLUPDATE sqlResult.Exec(): %v | %v | %v \n", err, id, description) | |
} | |
timeEnd = time.Now() | |
log.Printf("Elapsed %v | SQLUPDATE \n", timeEnd.Sub(timeBegin)) | |
// | |
}(i) | |
} | |
// Wait for all goroutines to complete. | |
wg.Wait() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment