Created
July 7, 2016 03:08
-
-
Save c4pt0r/91b5b00f3cd9ee3174b4aa8084915b46 to your computer and use it in GitHub Desktop.
game.go
This file contains 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
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