Skip to content

Instantly share code, notes, and snippets.

@c4pt0r
Created July 7, 2016 03:08
Show Gist options
  • Save c4pt0r/91b5b00f3cd9ee3174b4aa8084915b46 to your computer and use it in GitHub Desktop.
Save c4pt0r/91b5b00f3cd9ee3174b4aa8084915b46 to your computer and use it in GitHub Desktop.
game.go
package main
import (
"flag"
"fmt"
"net/http"
"sync"
"time"
"github.com/go-xorm/xorm"
"github.com/ngaut/log"
_ "net/http/pprof"
_ "github.com/go-sql-driver/mysql"
)
type Charbase struct {
PlatformID int64 `xorm:"'platformid'"`
ZoneID int64 `xorm:"'zoneid'"`
AccID int64 `xorm:"pk 'accid'"`
CharID int64 `xorm:"'charid'"`
Name string `xorm:"'name'"`
MapID int64 `xorm:"'mapid'"`
Gender int64 `xorm:"'gender'"`
Profession int64 `xorm:"'profession'"`
DestProfession int64 `xorm:"'destprofession'"`
RoleLv int64 `xorm:"'rolelv'"`
RoleExp int64 `xorm:"'roleexp'"`
Charge int64 `xorm:"'charge'"`
Diamond int64 `xorm:"'diamond'"`
Silver int64 `xorm:"'silver'"`
Gold int64 `xorm:"'gold'"`
CreateTime int64 `xorm:"'createtime'"`
OnlineTime int64 `xorm:"'onlinetime'"`
OfflineTime int64 `xorm:"'offlinetime'"`
Addict int64 `xorm:"'addict'"`
BattleTime int64 `xorm:"'battletime'"`
Body int64 `xorm:"'body'"`
AddictTipsTime int64 `xorm:"'addicttipstime'"`
UserData []byte `xorm:"'userdata'"`
Package []byte `xorm:"'package'"`
Quest []byte `xorm:"'quest'"`
Pet []byte `xorm:"'pet'"`
Var []byte `xorm:"'var'"`
Fighter []byte `xorm:"'fighter'"`
ChatMsg []byte `xorm:"'chatmsg'"`
UserTower []byte `xorm:"'usertower'"`
Seal []byte `xorm:"'seal'"`
Manual []byte `xorm:"'manual'"`
}
var (
host = flag.String("h", "localhost", "db host")
port = flag.Int("P", 3306, "db port")
passwd = flag.String("p", "", "db password")
user = flag.String("u", "root", "db user")
defaultDB = flag.String("db", "test", "default db")
)
var (
fromAccID = flag.Int("id-from", 0, "test account id range, from")
toAccID = flag.Int("id-to", 10000, "test account id range, to")
)
const maxBatchCount = 5000
var engine *xorm.Engine
func randBytes(n int) []byte {
b := make([]byte, n)
for i := range b {
b[i] = 'a'
}
return b
}
func mustPrepareUsers() {
log.Info("preparing user...")
sess := engine.NewSession()
err := sess.Begin()
if err != nil {
log.Fatal(err)
}
for i := *fromAccID; i < *toAccID; i++ {
sess.Insert(&Charbase{
AccID: int64(i),
UserData: []byte("hello world"),
})
if i > 0 && i%maxBatchCount == 0 {
log.Info("commit batch, row count:", i)
// commit and close this batch
sess.Commit()
sess.Close()
// start new transaction
sess = engine.NewSession()
sess.Begin()
}
}
// commit the rest even if it's empty
err = sess.Commit()
if err != nil {
log.Fatal(err)
}
sess.Close()
log.Info("done")
}
func updateUser(accountID int64) error {
// update userdata
userDataSize := 10 * 1024
randUserData := randBytes(userDataSize)
u := &Charbase{
UserData: randUserData,
}
_, err := engine.Id(accountID).Update(u)
if err != nil {
log.Error(err)
return err
}
return nil
}
type TpsCounter struct {
mu sync.Mutex
cnt int64
}
func (t *TpsCounter) Run() {
for {
tt := time.Now()
time.Sleep(time.Second)
elapse := int64(time.Since(tt)) * 1.0 / int64(time.Second)
if elapse > 0 {
t.mu.Lock()
tps := t.cnt / elapse
t.mu.Unlock()
log.Info("tps: ", tps)
}
t.mu.Lock()
t.cnt = 0
t.mu.Unlock()
}
}
func (t *TpsCounter) Add(delta int64) {
t.mu.Lock()
t.cnt += delta
t.mu.Unlock()
}
var tpsCounter = &TpsCounter{}
func updateWorker(idChan <-chan int64) {
for id := range idChan {
updateUser(id)
tpsCounter.Add(1)
}
}
func main() {
flag.Parse()
var err error
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8", *user, *passwd, *host, *port, *defaultDB)
engine, err = xorm.NewEngine("mysql", dsn)
if err != nil {
log.Fatal(err)
}
// set max conn
engine.SetMaxIdleConns(200)
engine.SetMaxOpenConns(200)
log.Info("drop and create table...")
engine.DropTables(&Charbase{})
engine.CreateTables(&Charbase{})
log.Info("done")
// insert users
mustPrepareUsers()
go tpsCounter.Run()
var chs []chan int64
for i := 0; i < 30; i++ {
ch := make(chan int64, 100)
go updateWorker(ch)
chs = append(chs, ch)
}
go func() {
http.ListenAndServe("localhost:6060", nil)
}()
// simulate N users online, random update userdata
onlineCount := 10000
for i := 0; i < onlineCount; i++ {
go func(id int) {
// simulate user, choose a random account id
ch := chs[id%len(chs)]
for {
ch <- int64(id)
}
}(i)
}
for {
time.Sleep(time.Second)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment