mirror of
https://gitee.com/johng/gf
synced 2026-07-06 13:42:46 +08:00
grand,gdb增加benchmark测试,改进grand随机数生成性能,改进gdb.New性能
This commit is contained in:
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
31
g/database/gdb/test/gdb_bench_test.go
Normal file
31
g/database/gdb/test/gdb_bench_test.go
Normal 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
104
g/g.go
@ -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操作对象,使用了连接池
|
||||
|
||||
@ -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)]
|
||||
20
g/util/grand/grand_test.go
Normal file
20
g/util/grand/grand_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
@ -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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user