map性能对比

// 对外暴露的map
type MutexMap struct {
    items map[string]interface{} // 为了和上面的ConcurrentMap做比较,都采用string->interface的方式
    mu    *sync.RWMutex          // 读写锁
}

// 新建一个map
func NewMutexMap() *MutexMap {
    return &MutexMap{
        items: map[string]interface{}{},
        mu:    new(sync.RWMutex),
    }
}

// Set 设置key,value
func (m MutexMap) Set(key string, value interface{}) {
    m.mu.Lock()          // 加锁(全锁定)
    m.items[key] = value // 赋值
    m.mu.Unlock()        // 解锁
}

// Get 获取key对应的value
func (m MutexMap) Get(key string) (value interface{}, ok bool) {
    m.mu.RLock()             // 加锁(读锁定)
    value, ok = m.items[key] // 取值
    m.mu.RUnlock()           // 解锁
    return value, ok
}

// Count 统计key个数
func (m MutexMap) Count() int {
    m.mu.RLock() // 加锁(读锁定)
    count := len(m.items)
    m.mu.RUnlock() // 解锁
    return count
}

// Keys 所有的key
func (m MutexMap) Keys() []string {
    m.mu.RLock() // 加锁(读锁定)
    keys := make([]string, len(m.items))
    for k := range m.items {
        keys = append(keys, k)
    }
    m.mu.RUnlock() // 解锁

    return keys
}

sync.map 、MutexMap 、ConcurrentMap性能对比

package main

import (
    "math/rand"
    "strconv"
    "sync"
    "testing"
)

// 10万次的赋值,10万次的读取
var times int = 100000

// 测试ConcurrentMap
func BenchmarkTestConcurrentMap(b *testing.B) {
    for k := 0; k < b.N; k++ {
        b.StopTimer()
        // 产生10000个不重复的键值对(string -> int)
        testKV := map[string]int{}
        for i := 0; i < 10000; i++ {
            testKV[strconv.Itoa(i)] = i
        }

        // 新建一个ConcurrentMap
        pMap := NewConcurrentMap()

        // set到map中
        for k, v := range testKV {
            pMap.Set(k, v)
        }

        // 开始计时
        b.StartTimer()

        wg := sync.WaitGroup{}
        wg.Add(2)

        // 赋值
        go func() {
            // 对随机key,赋值times次
            for i := 0; i < times; i++ {
                index := rand.Intn(times)
                pMap.Set(strconv.Itoa(index), index+1)
            }
            wg.Done()
        }()

        // 读取
        go func() {
            // 对随机key,读取times次
            for i := 0; i < times; i++ {
                index := rand.Intn(times)
                pMap.Get(strconv.Itoa(index))
            }
            wg.Done()
        }()

        // 等待两个协程处理完毕
        wg.Wait()
    }
}

// 测试map加锁
func BenchmarkTestMap(b *testing.B) {
    for k := 0; k < b.N; k++ {
        b.StopTimer()
        // 产生10000个不重复的键值对(string -> int)
        testKV := map[string]int{}
        for i := 0; i < 10000; i++ {
            testKV[strconv.Itoa(i)] = i
        }

        // 新建一个MutexMap
        pMap := NewMutexMap()

        // set到map中
        for k, v := range testKV {
            pMap.Set(k, v)
        }

        // 开始计时
        b.StartTimer()

        wg := sync.WaitGroup{}
        wg.Add(2)
        // 赋值
        go func() {
            // 对随机key,赋值100万次
            for i := 0; i < times; i++ {
                index := rand.Intn(times)
                pMap.Set(strconv.Itoa(index), index+1)
            }
            wg.Done()
        }()

        // 读取
        go func() {
            // 对随机key,读取100万次
            for i := 0; i < times; i++ {
                index := rand.Intn(times)
                pMap.Get(strconv.Itoa(index))
            }
            wg.Done()
        }()

        // 等待两个协程处理完毕
        wg.Wait()
    }
}

// 测试sync.map
func BenchmarkTestSyncMap(b *testing.B) {
    for k := 0; k < b.N; k++ {
        b.StopTimer()
        // 产生10000个不重复的键值对(string -> int)
        testKV := map[string]int{}
        for i := 0; i < 10000; i++ {
            testKV[strconv.Itoa(i)] = i
        }

        // 新建一个sync.Map
        pMap := &sync.Map{}

        // set到map中
        for k, v := range testKV {
            pMap.Store(k, v)
        }

        // 开始计时
        b.StartTimer()

        wg := sync.WaitGroup{}
        wg.Add(2)

        // 赋值
        go func() {
            // 对随机key,赋值10万次
            for i := 0; i < times; i++ {
                index := rand.Intn(times)
                pMap.Store(strconv.Itoa(index), index+1)
            }
            wg.Done()
        }()

        // 读取
        go func() {
            // 对随机key,读取10万次
            for i := 0; i < times; i++ {
                index := rand.Intn(times)
                pMap.Load(strconv.Itoa(index))
            }
            wg.Done()
        }()

        // 等待两个协程处理完毕
        wg.Wait()
    }
}

执行命令:go test -bench=.

image.png

你可能感兴趣的:(map性能对比)