mirror of
https://gitee.com/johng/gf
synced 2026-07-07 14:25:17 +08:00
改进gmap,并完善基准测试
This commit is contained in:
@ -23,7 +23,6 @@ var sbm = NewStringBoolMap()
|
||||
var sim = NewStringIntMap()
|
||||
var sifm = NewStringInterfaceMap()
|
||||
var ssm = NewStringStringMap()
|
||||
var uifm = NewUintInterfaceMap()
|
||||
|
||||
// 写入性能测试
|
||||
|
||||
@ -81,11 +80,6 @@ func Benchmark_StringStringMap_Set(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_UintInterfaceMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
uifm.Set(uint(i), i)
|
||||
}
|
||||
}
|
||||
|
||||
// 读取性能测试
|
||||
|
||||
@ -143,9 +137,3 @@ func Benchmark_StringStringMap_Get(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_UintInterfaceMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
uifm.Get(uint(i))
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
// 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=".*"
|
||||
// go test *.go -bench=".*" -benchmem
|
||||
|
||||
package gmap_test
|
||||
|
||||
139
g/container/gmap/gmap_bench_unsafe_test.go
Normal file
139
g/container/gmap/gmap_bench_unsafe_test.go
Normal file
@ -0,0 +1,139 @@
|
||||
// Copyright 2017 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=".*" -benchmem
|
||||
|
||||
package gmap
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
|
||||
var ibmUnsafe = NewIntBoolMap(false)
|
||||
var iimUnsafe = NewIntIntMap(false)
|
||||
var iifmUnsafe = NewIntInterfaceMap(false)
|
||||
var ismUnsafe = NewIntStringMap(false)
|
||||
var ififmUnsafe = NewInterfaceInterfaceMap(false)
|
||||
var sbmUnsafe = NewStringBoolMap(false)
|
||||
var simUnsafe = NewStringIntMap(false)
|
||||
var sifmUnsafe = NewStringInterfaceMap(false)
|
||||
var ssmUnsafe = NewStringStringMap(false)
|
||||
|
||||
// 写入性能测试
|
||||
|
||||
func Benchmark_Unsafe_IntBoolMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ibmUnsafe.Set(i, true)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_IntIntMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
iimUnsafe.Set(i, i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_IntInterfaceMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
iifmUnsafe.Set(i, i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_IntStringMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ismUnsafe.Set(i, strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_InterfaceInterfaceMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ififmUnsafe.Set(i, i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringBoolMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sbmUnsafe.Set(strconv.Itoa(i), true)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringIntMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
simUnsafe.Set(strconv.Itoa(i), i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringInterfaceMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sifmUnsafe.Set(strconv.Itoa(i), i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringStringMap_Set(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ssmUnsafe.Set(strconv.Itoa(i), strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 读取性能测试
|
||||
|
||||
func Benchmark_Unsafe_IntBoolMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ibmUnsafe.Get(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_IntIntMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
iimUnsafe.Get(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_IntInterfaceMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
iifmUnsafe.Get(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_IntStringMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ismUnsafe.Get(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_InterfaceInterfaceMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ififmUnsafe.Get(i)
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringBoolMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sbmUnsafe.Get(strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringIntMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
simUnsafe.Get(strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringInterfaceMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sifmUnsafe.Get(strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
|
||||
func Benchmark_Unsafe_StringStringMap_Get(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ssmUnsafe.Get(strconv.Itoa(i))
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,23 +69,70 @@ func (this *IntBoolMap) Get(key int) bool {
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *IntBoolMap) GetWithDefault(key int, value bool) bool {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *IntBoolMap) doSetWithLockCheck(key int, value bool) bool {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
return value
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *IntBoolMap) Remove(key int) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
// 当键名存在时返回其键值,否则写入指定的键值
|
||||
func (this *IntBoolMap) GetOrSet(key int, value bool) bool {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
||||
func (this *IntBoolMap) GetOrSetFunc(key int, f func() bool) bool {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func (this *IntBoolMap) GetOrSetFuncLock(key int, f func() bool) bool {
|
||||
this.mu.RLock()
|
||||
val, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
val = f()
|
||||
this.m[key] = val
|
||||
return val
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名不存在时写入,并返回true;否则返回false。
|
||||
func (this *IntBoolMap) SetIfNotExist(key int, value bool) bool {
|
||||
if !this.Contains(key) {
|
||||
this.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
@ -98,7 +145,7 @@ func (this *IntBoolMap) BatchRemove(keys []int) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *IntBoolMap) GetAndRemove(key int) (bool) {
|
||||
func (this *IntBoolMap) Remove(key int) bool {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -69,23 +69,70 @@ func (this *IntIntMap) Get(key int) (int) {
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *IntIntMap) GetWithDefault(key int, value int) int {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *IntIntMap) doSetWithLockCheck(key int, value int) int {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
return value
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *IntIntMap) Remove(key int) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
// 当键名存在时返回其键值,否则写入指定的键值
|
||||
func (this *IntIntMap) GetOrSet(key int, value int) int {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
||||
func (this *IntIntMap) GetOrSetFunc(key int, f func() int) int {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func (this *IntIntMap) GetOrSetFuncLock(key int, f func() int) int {
|
||||
this.mu.RLock()
|
||||
val, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
val = f()
|
||||
this.m[key] = val
|
||||
return val
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名不存在时写入,并返回true;否则返回false。
|
||||
func (this *IntIntMap) SetIfNotExist(key int, value int) bool {
|
||||
if !this.Contains(key) {
|
||||
this.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
@ -98,7 +145,7 @@ func (this *IntIntMap) BatchRemove(keys []int) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *IntIntMap) GetAndRemove(key int) (int) {
|
||||
func (this *IntIntMap) Remove(key int) int {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -67,23 +67,58 @@ func (this *IntInterfaceMap) Get(key int) (interface{}) {
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *IntInterfaceMap) GetWithDefault(key int, value interface{}) interface{} {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *IntInterfaceMap) doSetWithLockCheck(key int, value interface{}) interface{} {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
return v
|
||||
}
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
if f, ok := value.(func() interface {}); ok {
|
||||
value = f()
|
||||
}
|
||||
this.m[key] = value
|
||||
return value
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *IntInterfaceMap) Remove(key int) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
// 当键名存在时返回其键值,否则写入指定的键值
|
||||
func (this *IntInterfaceMap) GetOrSet(key int, value interface{}) interface{} {
|
||||
if v := this.Get(key); v == nil {
|
||||
return this.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
||||
func (this *IntInterfaceMap) GetOrSetFunc(key int, f func() interface{}) interface{} {
|
||||
if v := this.Get(key); v == nil {
|
||||
v = f()
|
||||
this.doSetWithLockCheck(key, v)
|
||||
return v
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func (this *IntInterfaceMap) GetOrSetFuncLock(key int, f func() interface{}) interface{} {
|
||||
if v := this.Get(key); v == nil {
|
||||
this.doSetWithLockCheck(key, f)
|
||||
return v
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名不存在时写入,并返回true;否则返回false。
|
||||
func (this *IntInterfaceMap) SetIfNotExist(key int, value interface{}) bool {
|
||||
if !this.Contains(key) {
|
||||
this.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
@ -96,7 +131,7 @@ func (this *IntInterfaceMap) BatchRemove(keys []int) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *IntInterfaceMap) GetAndRemove(key int) (interface{}) {
|
||||
func (this *IntInterfaceMap) Remove(key int) interface{} {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -69,23 +69,70 @@ func (this *IntStringMap) Get(key int) string {
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *IntStringMap) GetWithDefault(key int, value string) string {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *IntStringMap) doSetWithLockCheck(key int, value string) string {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
return value
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *IntStringMap) Remove(key int) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
// 当键名存在时返回其键值,否则写入指定的键值
|
||||
func (this *IntStringMap) GetOrSet(key int, value string) string {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
||||
func (this *IntStringMap) GetOrSetFunc(key int, f func() string) string {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func (this *IntStringMap) GetOrSetFuncLock(key int, f func() string) string {
|
||||
this.mu.RLock()
|
||||
val, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
val = f()
|
||||
this.m[key] = val
|
||||
return val
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名不存在时写入,并返回true;否则返回false。
|
||||
func (this *IntStringMap) SetIfNotExist(key int, value string) bool {
|
||||
if !this.Contains(key) {
|
||||
this.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
@ -98,7 +145,7 @@ func (this *IntStringMap) BatchRemove(keys []int) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *IntStringMap) GetAndRemove(key int) (string) {
|
||||
func (this *IntStringMap) Remove(key int) string {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -73,15 +73,14 @@ func (this *InterfaceInterfaceMap) Get(key interface{}) interface{} {
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *InterfaceInterfaceMap) doSetWithLockCheck(key interface{}, value interface{}) interface{} {
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
if f, ok := value.(func() interface {}); ok {
|
||||
value = f()
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return value
|
||||
}
|
||||
|
||||
@ -124,13 +123,6 @@ func (this *InterfaceInterfaceMap) SetIfNotExist(key interface{}, value interfac
|
||||
return false
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *InterfaceInterfaceMap) Remove(key interface{}) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
func (this *InterfaceInterfaceMap) BatchRemove(keys []interface{}) {
|
||||
this.mu.Lock()
|
||||
@ -141,7 +133,7 @@ func (this *InterfaceInterfaceMap) BatchRemove(keys []interface{}) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *InterfaceInterfaceMap) GetAndRemove(key interface{}) (interface{}) {
|
||||
func (this *InterfaceInterfaceMap) Remove(key interface{}) interface{} {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -69,23 +69,70 @@ func (this *StringBoolMap) Get(key string) bool {
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *StringBoolMap) GetWithDefault(key string, value bool) bool {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *StringBoolMap) doSetWithLockCheck(key string, value bool) bool {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
return value
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *StringBoolMap) Remove(key string) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
// 当键名存在时返回其键值,否则写入指定的键值
|
||||
func (this *StringBoolMap) GetOrSet(key string, value bool) bool {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
||||
func (this *StringBoolMap) GetOrSetFunc(key string, f func() bool) bool {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func (this *StringBoolMap) GetOrSetFuncLock(key string, f func() bool) bool {
|
||||
this.mu.RLock()
|
||||
val, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
val = f()
|
||||
this.m[key] = val
|
||||
return val
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名不存在时写入,并返回true;否则返回false。
|
||||
func (this *StringBoolMap) SetIfNotExist(key string, value bool) bool {
|
||||
if !this.Contains(key) {
|
||||
this.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
@ -98,7 +145,7 @@ func (this *StringBoolMap) BatchRemove(keys []string) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *StringBoolMap) GetAndRemove(key string) (bool) {
|
||||
func (this *StringBoolMap) Remove(key string) bool {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -67,23 +67,70 @@ func (this *StringIntMap) Get(key string) int {
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *StringIntMap) GetWithDefault(key string, value int) int {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *StringIntMap) doSetWithLockCheck(key string, value int) int {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
return value
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *StringIntMap) Remove(key string) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
// 当键名存在时返回其键值,否则写入指定的键值
|
||||
func (this *StringIntMap) GetOrSet(key string, value int) int {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
||||
func (this *StringIntMap) GetOrSetFunc(key string, f func() int) int {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func (this *StringIntMap) GetOrSetFuncLock(key string, f func() int) int {
|
||||
this.mu.RLock()
|
||||
val, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
val = f()
|
||||
this.m[key] = val
|
||||
return val
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名不存在时写入,并返回true;否则返回false。
|
||||
func (this *StringIntMap) SetIfNotExist(key string, value int) bool {
|
||||
if !this.Contains(key) {
|
||||
this.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
@ -96,7 +143,7 @@ func (this *StringIntMap) BatchRemove(keys []string) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *StringIntMap) GetAndRemove(key string) (int) {
|
||||
func (this *StringIntMap) Remove(key string) int {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -72,16 +72,15 @@ func (this *StringInterfaceMap) Get(key string) interface{} {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *StringInterfaceMap) doSetWithLockCheck(key string, value interface{}) interface{} {
|
||||
this.mu.Lock()
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
if f, ok := value.(func() interface {}); ok {
|
||||
value = f()
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return value
|
||||
}
|
||||
|
||||
@ -124,13 +123,6 @@ func (this *StringInterfaceMap) SetIfNotExist(key string, value interface{}) boo
|
||||
return false
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *StringInterfaceMap) Remove(key string) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
func (this *StringInterfaceMap) BatchRemove(keys []string) {
|
||||
this.mu.Lock()
|
||||
@ -141,7 +133,7 @@ func (this *StringInterfaceMap) BatchRemove(keys []string) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *StringInterfaceMap) GetAndRemove(key string) interface{} {
|
||||
func (this *StringInterfaceMap) Remove(key string) interface{} {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -67,23 +67,70 @@ func (this *StringStringMap) Get(key string) string {
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *StringStringMap) GetWithDefault(key string, value string) string {
|
||||
// 设置kv缓存键值对,内部会对键名的存在性使用写锁进行二次检索确认,如果存在则不再写入;返回键名对应的键值。
|
||||
// 在高并发下有用,防止数据写入的并发逻辑错误。
|
||||
func (this *StringStringMap) doSetWithLockCheck(key string, value string) string {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
this.m[key] = value
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
return value
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *StringStringMap) Remove(key string) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
// 当键名存在时返回其键值,否则写入指定的键值
|
||||
func (this *StringStringMap) GetOrSet(key string, value string) string {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, value)
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名存在时返回其键值,否则写入指定的键值,键值由指定的函数生成
|
||||
func (this *StringStringMap) GetOrSetFunc(key string, f func() string) string {
|
||||
this.mu.RLock()
|
||||
v, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
return this.doSetWithLockCheck(key, f())
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func (this *StringStringMap) GetOrSetFuncLock(key string, f func() string) string {
|
||||
this.mu.RLock()
|
||||
val, ok := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
if !ok {
|
||||
this.mu.Lock()
|
||||
defer this.mu.Unlock()
|
||||
if v, ok := this.m[key]; ok {
|
||||
this.mu.Unlock()
|
||||
return v
|
||||
}
|
||||
val = f()
|
||||
this.m[key] = val
|
||||
return val
|
||||
} else {
|
||||
return val
|
||||
}
|
||||
}
|
||||
|
||||
// 当键名不存在时写入,并返回true;否则返回false。
|
||||
func (this *StringStringMap) SetIfNotExist(key string, value string) bool {
|
||||
if !this.Contains(key) {
|
||||
this.doSetWithLockCheck(key, value)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
@ -96,7 +143,7 @@ func (this *StringStringMap) BatchRemove(keys []string) {
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *StringStringMap) GetAndRemove(key string) string {
|
||||
func (this *StringStringMap) Remove(key string) string {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
@ -1,175 +0,0 @@
|
||||
// Copyright 2017 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.
|
||||
//
|
||||
|
||||
package gmap
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/container/internal/rwmutex"
|
||||
)
|
||||
|
||||
type UintInterfaceMap struct {
|
||||
mu *rwmutex.RWMutex
|
||||
m map[uint]interface{}
|
||||
}
|
||||
|
||||
func NewUintInterfaceMap(safe...bool) *UintInterfaceMap {
|
||||
return &UintInterfaceMap{
|
||||
m : make(map[uint]interface{}),
|
||||
mu : rwmutex.New(safe...),
|
||||
}
|
||||
}
|
||||
|
||||
func (this *UintInterfaceMap) Iterator(f func (k uint, v interface{}) bool) {
|
||||
this.mu.RLock()
|
||||
defer this.mu.RUnlock()
|
||||
for k, v := range this.m {
|
||||
if !f(k, v) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 哈希表克隆
|
||||
func (this *UintInterfaceMap) Clone() map[uint]interface{} {
|
||||
m := make(map[uint]interface{})
|
||||
this.mu.RLock()
|
||||
for k, v := range this.m {
|
||||
m[k] = v
|
||||
}
|
||||
this.mu.RUnlock()
|
||||
return m
|
||||
}
|
||||
|
||||
// 设置键值对
|
||||
func (this *UintInterfaceMap) Set(key uint, val interface{}) {
|
||||
this.mu.Lock()
|
||||
this.m[key] = val
|
||||
this.mu.Unlock()
|
||||
}
|
||||
|
||||
// 批量设置键值对
|
||||
func (this *UintInterfaceMap) BatchSet(m map[uint]interface{}) {
|
||||
this.mu.Lock()
|
||||
for k, v := range m {
|
||||
this.m[k] = v
|
||||
}
|
||||
this.mu.Unlock()
|
||||
}
|
||||
|
||||
// 获取键值
|
||||
func (this *UintInterfaceMap) Get(key uint) interface{} {
|
||||
this.mu.RLock()
|
||||
val, _ := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// 获取键值,如果键值不存在则写入默认值
|
||||
func (this *UintInterfaceMap) GetWithDefault(key uint, value interface{}) interface{} {
|
||||
this.mu.Lock()
|
||||
val, ok := this.m[key]
|
||||
if !ok {
|
||||
this.m[key] = value
|
||||
val = value
|
||||
}
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// 删除键值对
|
||||
func (this *UintInterfaceMap) Remove(key uint) {
|
||||
this.mu.Lock()
|
||||
delete(this.m, key)
|
||||
this.mu.Unlock()
|
||||
}
|
||||
|
||||
// 批量删除键值对
|
||||
func (this *UintInterfaceMap) BatchRemove(keys []uint) {
|
||||
this.mu.Lock()
|
||||
for _, key := range keys {
|
||||
delete(this.m, key)
|
||||
}
|
||||
this.mu.Unlock()
|
||||
}
|
||||
|
||||
// 返回对应的键值,并删除该键值
|
||||
func (this *UintInterfaceMap) GetAndRemove(key uint) (interface{}) {
|
||||
this.mu.Lock()
|
||||
val, exists := this.m[key]
|
||||
if exists {
|
||||
delete(this.m, key)
|
||||
}
|
||||
this.mu.Unlock()
|
||||
return val
|
||||
}
|
||||
|
||||
// 返回键列表
|
||||
func (this *UintInterfaceMap) Keys() []uint {
|
||||
this.mu.RLock()
|
||||
keys := make([]uint, 0)
|
||||
for key, _ := range this.m {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
this.mu.RUnlock()
|
||||
return keys
|
||||
}
|
||||
|
||||
// 返回值列表(注意是随机排序)
|
||||
func (this *UintInterfaceMap) Values() []interface{} {
|
||||
this.mu.RLock()
|
||||
vals := make([]interface{}, 0)
|
||||
for _, val := range this.m {
|
||||
vals = append(vals, val)
|
||||
}
|
||||
this.mu.RUnlock()
|
||||
return vals
|
||||
}
|
||||
|
||||
// 是否存在某个键
|
||||
func (this *UintInterfaceMap) Contains(key uint) bool {
|
||||
this.mu.RLock()
|
||||
_, exists := this.m[key]
|
||||
this.mu.RUnlock()
|
||||
return exists
|
||||
}
|
||||
|
||||
// 哈希表大小
|
||||
func (this *UintInterfaceMap) Size() int {
|
||||
this.mu.RLock()
|
||||
length := len(this.m)
|
||||
this.mu.RUnlock()
|
||||
return length
|
||||
}
|
||||
|
||||
// 哈希表是否为空
|
||||
func (this *UintInterfaceMap) IsEmpty() bool {
|
||||
this.mu.RLock()
|
||||
empty := len(this.m) == 0
|
||||
this.mu.RUnlock()
|
||||
return empty
|
||||
}
|
||||
|
||||
// 清空哈希表
|
||||
func (this *UintInterfaceMap) Clear() {
|
||||
this.mu.Lock()
|
||||
this.m = make(map[uint]interface{})
|
||||
this.mu.Unlock()
|
||||
}
|
||||
|
||||
// 并发安全写锁操作,使用自定义方法执行加锁修改操作
|
||||
func (this *UintInterfaceMap) LockFunc(f func(m map[uint]interface{})) {
|
||||
this.mu.Lock(true)
|
||||
defer this.mu.Unlock(true)
|
||||
f(this.m)
|
||||
}
|
||||
|
||||
// 并发安全读锁操作,使用自定义方法执行加锁读取操作
|
||||
func (this *UintInterfaceMap) RLockFunc(f func(m map[uint]interface{})) {
|
||||
this.mu.RLock(true)
|
||||
defer this.mu.RUnlock(true)
|
||||
f(this.m)
|
||||
}
|
||||
@ -15,7 +15,6 @@ import (
|
||||
)
|
||||
|
||||
var ints = gset.NewIntSet()
|
||||
var uints = gset.NewUintSet()
|
||||
var itfs = gset.NewInterfaceSet()
|
||||
var strs = gset.NewStringSet()
|
||||
|
||||
@ -37,24 +36,6 @@ func BenchmarkIntSet_Remove(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUintSet_Add(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
uints.Add(uint(i))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUintSet_Contains(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
uints.Contains(uint(i))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkUintSet_Remove(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
uints.Remove(uint(i))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInterfaceSet_Add(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
itfs.Add(i)
|
||||
|
||||
@ -46,6 +46,11 @@ func GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{}
|
||||
return cache.GetOrSetFunc(key, f, expire)
|
||||
}
|
||||
|
||||
// 与GetOrSetFunc不同的是,f是在写锁机制内执行
|
||||
func GetOrSetFuncLock(key interface{}, f func() interface{}, expire int) interface{} {
|
||||
return cache.GetOrSetFuncLock(key, f, expire)
|
||||
}
|
||||
|
||||
// 是否存在指定的键名,true表示存在,false表示不存在。
|
||||
func Contains(key interface{}) bool {
|
||||
return cache.Contains(key)
|
||||
@ -57,8 +62,8 @@ func Remove(key interface{}) interface{} {
|
||||
}
|
||||
|
||||
// (使用全局KV缓存对象)批量删除指定键值对
|
||||
func BatchRemove(keys []interface{}) map[interface{}]interface{} {
|
||||
return cache.BatchRemove(keys)
|
||||
func BatchRemove(keys []interface{}) {
|
||||
cache.BatchRemove(keys)
|
||||
}
|
||||
|
||||
// 获得所有的键名,组成数组返回
|
||||
|
||||
@ -213,14 +213,12 @@ func (c *memCache) Remove(key interface{}) interface{} {
|
||||
}
|
||||
|
||||
// 批量删除键值对,并返回被删除的键值对数据
|
||||
func (c *memCache) BatchRemove(keys []interface{}) map[interface{}]interface{} {
|
||||
m := make(map[interface{}]interface{})
|
||||
func (c *memCache) BatchRemove(keys []interface{}) {
|
||||
c.dmu.Lock()
|
||||
for _, key := range keys {
|
||||
if v := c.Remove(key); v != nil {
|
||||
m[key] = v
|
||||
}
|
||||
delete(c.data, key)
|
||||
}
|
||||
return m
|
||||
c.dmu.Unlock()
|
||||
}
|
||||
|
||||
// 获得所有的键名,组成数组返回
|
||||
|
||||
Reference in New Issue
Block a user