grand,gdb增加benchmark测试,改进grand随机数生成性能,改进gdb.New性能

This commit is contained in:
John
2018-04-27 11:38:26 +08:00
parent 46a01da07c
commit 08a52d7efd
8 changed files with 148 additions and 127 deletions

View File

@ -122,11 +122,10 @@ func New(groupName...string) (*Db, error) {
if len(masterList) < 1 {
return nil, errors.New("at least one master node configuration's need to make sense")
}
masterNode := getConfigNodeByPriority(&masterList)
masterNode := getConfigNodeByPriority(masterList)
var slaveNode *ConfigNode
if len(slaveList) > 0 {
slaveNode = getConfigNodeByPriority(&slaveList)
slaveNode = getConfigNodeByPriority(slaveList)
}
return newDb(masterNode, slaveNode)
} else {
@ -135,22 +134,31 @@ func New(groupName...string) (*Db, error) {
}
// 按照负载均衡算法(优先级配置)从数据库集群中选择一个配置节点出来使用
func getConfigNodeByPriority (cg *ConfigGroup) *ConfigNode {
if len(*cg) < 2 {
return &(*cg)[0]
// 算法说明举例,
// 1、假如2个节点的priority都是1那么随机大小范围为[0, 199]
// 2、那么节点1的权重范围为[0, 99]节点2的权重范围为[100, 199]比例为1:1
// 3、假如计算出的随机数为99;
// 4、那么选择的配置为节点1;
func getConfigNodeByPriority (cg ConfigGroup) *ConfigNode {
if len(cg) < 2 {
return &cg[0]
}
var total int
for i := 0; i < len(*cg); i++ {
total += (*cg)[i].Priority * 100
for i := 0; i < len(cg); i++ {
total += cg[i].Priority * 100
}
// 不能取到末尾的边界点
r := grand.Rand(0, total)
if r > 0 {
r -= 1
}
min := 0
max := 0
for i := 0; i < len(*cg); i++ {
max = min + (*cg)[i].Priority * 100
for i := 0; i < len(cg); i++ {
max = min + cg[i].Priority * 100
//fmt.Printf("r: %d, min: %d, max: %d\n", r, min, max)
if r >= min && r < max {
return &(*cg)[i]
return &cg[i]
} else {
min = max
}
@ -178,7 +186,6 @@ func newDb (masterNode *ConfigNode, slaveNode *ConfigNode) (*Db, error) {
return nil, err
}
}
return &Db {
link : link,
master : master,

View File

@ -19,13 +19,13 @@ type dbmysql struct {
// 创建SQL操作对象内部采用了lazy link处理
func (db *dbmysql) Open (c *ConfigNode) (*sql.DB, error) {
var dbsource string
var source string
if c.Linkinfo != "" {
dbsource = c.Linkinfo
source = c.Linkinfo
} else {
dbsource = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", c.User, c.Pass, c.Host, c.Port, c.Name)
source = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", c.User, c.Pass, c.Host, c.Port, c.Name)
}
if db, err := sql.Open("mysql", dbsource); err == nil {
if db, err := sql.Open("mysql", source); err == nil {
return db, nil
} else {
return nil, err

View File

@ -23,13 +23,13 @@ type dbpgsql struct {
// 创建SQL操作对象内部采用了lazy link处理
func (db *dbpgsql) Open (c *ConfigNode) (*sql.DB, error) {
var dbsource string
var source string
if c.Linkinfo != "" {
dbsource = c.Linkinfo
source = c.Linkinfo
} else {
dbsource = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s", c.User, c.Pass, c.Host, c.Port, c.Name)
source = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s", c.User, c.Pass, c.Host, c.Port, c.Name)
}
if db, err := sql.Open("postgres", dbsource); err == nil {
if db, err := sql.Open("postgres", source); err == nil {
return db, nil
} else {
return nil, err

View File

@ -0,0 +1,31 @@
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
// go test *.go -bench=".*"
package test
import (
"testing"
"gitee.com/johng/gf/g"
)
func init() {
// 这里需要修改为本地配置文件的目录地址
g.Config().SetPath("/home/john/Workspace/Go/GOPATH/src/gitee.com/johng/gf/geg/frame")
}
func Benchmark_New(b *testing.B) {
for i := 0; i < b.N; i++ {
g.Database()
}
}
func Benchmark_NewAndClose(b *testing.B) {
for i := 0; i < b.N; i++ {
g.Database().Close()
}
}

104
g/g.go
View File

@ -9,15 +9,20 @@ package g
import (
"strings"
"strconv"
"gitee.com/johng/gf/g/os/gview"
"gitee.com/johng/gf/g/os/gcfg"
"gitee.com/johng/gf/g/os/gview"
"gitee.com/johng/gf/g/util/gconv"
"gitee.com/johng/gf/g/frame/gins"
"gitee.com/johng/gf/g/os/gcache"
"gitee.com/johng/gf/g/os/gfsnotify"
"gitee.com/johng/gf/g/database/gdb"
"gitee.com/johng/gf/g/database/gredis"
)
const (
gIS_DATABASE_CONFIG_CACHED = "gf.core.component.database.cached"
)
// 常用map数据结构
type Map map[string]interface{}
@ -42,56 +47,61 @@ func Database(name...string) *gdb.Db {
if config == nil {
return nil
}
if m := config.GetMap("database"); m != nil {
c := gdb.Config{}
for group, v := range m {
cg := gdb.ConfigGroup{}
if list, ok := v.([]interface{}); ok {
for _, nodev := range list {
node := gdb.ConfigNode{}
nodem := nodev.(map[string]interface{})
if value, ok := nodem["host"]; ok {
node.Host = gconv.String(value)
// 数据库配置是否已经设置
if gcache.Get(gIS_DATABASE_CONFIG_CACHED) == nil {
if m := config.GetMap("database"); m != nil {
c := gdb.Config{}
for group, v := range m {
cg := gdb.ConfigGroup{}
if list, ok := v.([]interface{}); ok {
for _, nodev := range list {
node := gdb.ConfigNode{}
nodem := nodev.(map[string]interface{})
if value, ok := nodem["host"]; ok {
node.Host = gconv.String(value)
}
if value, ok := nodem["port"]; ok {
node.Port = gconv.String(value)
}
if value, ok := nodem["user"]; ok {
node.User = gconv.String(value)
}
if value, ok := nodem["pass"]; ok {
node.Pass = gconv.String(value)
}
if value, ok := nodem["name"]; ok {
node.Name = gconv.String(value)
}
if value, ok := nodem["type"]; ok {
node.Type = gconv.String(value)
}
if value, ok := nodem["role"]; ok {
node.Role = gconv.String(value)
}
if value, ok := nodem["charset"]; ok {
node.Charset = gconv.String(value)
}
if value, ok := nodem["priority"]; ok {
node.Priority = gconv.Int(value)
}
cg = append(cg, node)
}
if value, ok := nodem["port"]; ok {
node.Port = gconv.String(value)
}
if value, ok := nodem["user"]; ok {
node.User = gconv.String(value)
}
if value, ok := nodem["pass"]; ok {
node.Pass = gconv.String(value)
}
if value, ok := nodem["name"]; ok {
node.Name = gconv.String(value)
}
if value, ok := nodem["type"]; ok {
node.Type = gconv.String(value)
}
if value, ok := nodem["role"]; ok {
node.Role = gconv.String(value)
}
if value, ok := nodem["charset"]; ok {
node.Charset = gconv.String(value)
}
if value, ok := nodem["priority"]; ok {
node.Priority, _ = strconv.Atoi(gconv.String(value))
}
cg = append(cg, node)
}
c[group] = cg
}
c[group] = cg
}
gdb.SetConfig(c)
if db, err := gdb.New(name...); err == nil {
return db
} else {
return nil
gdb.SetConfig(c)
gcache.Set(gIS_DATABASE_CONFIG_CACHED, struct{}{}, 0)
// 使用gfsnotify进行文件监控当配置文件有任何变化时清空数据库配置缓存
gfsnotify.Add(Config().GetFilePath(), func(event *gfsnotify.Event) {
gcache.Remove(gIS_DATABASE_CONFIG_CACHED)
})
}
}
return nil
if db, err := gdb.New(name...); err == nil {
return db
} else {
return nil
}
}
// Redis操作对象使用了连接池

View File

@ -14,13 +14,20 @@ import (
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
var digits = []rune("0123456789")
// 修改全局随机数seed
func Seed (seed...int64) {
if len(seed) > 0 {
rand.Seed(seed[0])
} else {
rand.Seed(time.Now().UnixNano())
}
}
// 获得一个 min, max 之间的随机数(min <= x <= max)
func Rand (min, max int) int {
//fmt.Printf("min: %d, max: %d\n", min, max)
if min >= max {
return min
}
rand.Seed(time.Now().UnixNano())
n := rand.Intn(max + 1)
if n < min {
return Rand(min, max)
@ -30,7 +37,6 @@ func Rand (min, max int) int {
// 获得指定长度的随机字符串(可能包含数字和字母)
func RandStr(n int) string {
rand.Seed(time.Now().UnixNano())
b := make([]rune, n)
for i := range b {
if rand.Intn(2) == 1 {
@ -44,7 +50,6 @@ func RandStr(n int) string {
// 获得指定长度的随机数字字符串
func RandDigits(n int) string {
rand.Seed(time.Now().UnixNano())
b := make([]rune, n)
for i := range b {
b[i] = digits[rand.Intn(10)]
@ -54,7 +59,6 @@ func RandDigits(n int) string {
// 获得指定长度的随机字母字符串
func RandLetters(n int) string {
rand.Seed(time.Now().UnixNano())
b := make([]rune, n)
for i := range b {
b[i] = letters[rand.Intn(52)]

View File

@ -0,0 +1,20 @@
// Copyright 2018 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
// go test *.go -bench=".*"
package grand_test
import (
"testing"
"gitee.com/johng/gf/g/util/grand"
)
func Benchmark_Rand(b *testing.B) {
for i := 0; i < b.N; i++ {
grand.Rand(0, 200)
}
}

View File

@ -2,62 +2,11 @@ package main
import (
"fmt"
"math/rand"
)
var arabicNumber2RomanSymbolMap = map[int]string{
1 : "I",
5 : "V",
10 : "X",
50 : "L",
100 : "C",
500 : "D",
1000 : "M",
}
var romanSymbol2ArabicNumberMap = map[int]string{
4000 : "MMMCMC",
1000 : "M",
900 : "CM",
500 : "D",
400 : "CD",
100 : "C",
90 : "XC",
50 : "L",
40 : "XL",
10 : "X",
9 : "IX",
5 : "V",
4 : "IV",
1 : "I",
}
var array = []int{4000, 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
// Arabic numbers to Roman symbols
func romanSymbols2ArabicNumber(s string) int {
}
// Arabic numbers to Roman symbols
func arabicNumberToRomanSymbols(i int) string {
r := ""
for i > 0 {
for _, v := range array {
if i >= v {
r += romans[v]
i -= v
break
}
}
}
return r
}
func main() {
fmt.Println(intToRomans(1944))
//for i := 0; i < 10; i++ {
// fmt.Println(intToRomans(i))
//}
for i := 0; i < 100; i++ {
fmt.Println(rand.Intn(200))
}
}