-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
233 additions
and
31 deletions.
There are no files selected for viewing
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
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
## map 性能测试结果 | ||
|
||
测试方法:随机生成1000w个完全不相同的数字k,k<1亿 ,打乱顺序让多协程并发写入、读取、删除,每个协程处理其中的一部分号段 | ||
|
||
> 结论: concurrentMap 在分段为2048时,性能和内存分配明显好于sync.Map。 但在资源竞争率高的时候,性能差异不明显,concurrentMap略好于syncMap。 | ||
```shell | ||
go test -v -run ^$ -bench BenchmarkMap -benchtime=5s -benchmem | ||
``` | ||
|
||
```text | ||
goos: windows | ||
goarch: amd64 | ||
pkg: github.com/lvyahui8/ellyn/ellyn_common/collections | ||
cpu: AMD Ryzen 7 4800U with Radeon Graphics | ||
BenchmarkMap | ||
BenchmarkMap/concurrentMap_put | ||
BenchmarkMap/concurrentMap_put-16 18 342347494 ns/op 80002544 B/op 9999784 allocs/op | ||
BenchmarkMap/concurrentMap_read | ||
BenchmarkMap/concurrentMap_read-16 18 339383994 ns/op 80001507 B/op 9999781 allocs/op | ||
BenchmarkMap/concurrentMap_delete | ||
BenchmarkMap/concurrentMap_delete-16 61 99936639 ns/op 80000277 B/op 9999779 allocs/op | ||
BenchmarkMap/concurrentMap_R&W | ||
BenchmarkMap/concurrentMap_R&W-16 9 723391478 ns/op 160000385 B/op 19999569 allocs/op | ||
BenchmarkMap/syncMap_put | ||
BenchmarkMap/syncMap_put-16 1 8409727400 ns/op 1470761288 B/op 40306906 allocs/op | ||
BenchmarkMap/syncMap_read | ||
BenchmarkMap/syncMap_read-16 1 6106719400 ns/op 80012880 B/op 9999918 allocs/op | ||
BenchmarkMap/syncMap_delete | ||
BenchmarkMap/syncMap_delete-16 15 369030780 ns/op 79999968 B/op 9999778 allocs/op | ||
BenchmarkMap/syncMap_R&W | ||
BenchmarkMap/syncMap_R&W-16 7 1029901486 ns/op 319999952 B/op 29999555 allocs/op | ||
PASS | ||
ok github.com/lvyahui8/ellyn/ellyn_common/collections 70.109s | ||
``` |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package collections | ||
|
||
import ( | ||
"github.com/stretchr/testify/require" | ||
"math/rand" | ||
"runtime" | ||
"sync" | ||
"testing" | ||
"time" | ||
"unsafe" | ||
) | ||
|
||
const maxVal = 10000 * 10000 | ||
const cnt = 1000 * 10000 | ||
|
||
func shuffle(nums []int) (res []int) { | ||
res = make([]int, len(nums)) | ||
for i, v := range nums { | ||
res[i] = v | ||
} | ||
rand.Seed(time.Now().UnixMilli()) | ||
rand.Shuffle(len(nums), func(i, j int) { | ||
res[i], res[j] = res[j], res[i] | ||
}) | ||
return | ||
} | ||
|
||
// 生成100w个小于1000w不重复的数字 | ||
func randomSeq() (res []int) { | ||
raw := make([]int, maxVal) | ||
for i := 0; i < maxVal; i++ { | ||
raw[i] = i | ||
} | ||
res = shuffle(raw[0:cnt]) | ||
return | ||
} | ||
|
||
func testReadWrite(b *testing.B, name string, m mapApi, insertSeq, readSeq, deleteSeq []int) { | ||
// 测试纯粹写入的并发性能 | ||
routineSize := runtime.NumCPU() | ||
handleSize := len(insertSeq) / routineSize | ||
b.Run(name+"_put", func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
w := sync.WaitGroup{} | ||
w.Add(routineSize) | ||
for j := 0; j < routineSize; j++ { | ||
go func(offset int) { | ||
defer w.Done() | ||
for i := offset; i < handleSize+offset; i++ { | ||
m.Store(insertSeq[i], struct{}{}) | ||
} | ||
}(handleSize * j) | ||
} | ||
w.Wait() | ||
} | ||
}) | ||
// 测试纯粹读取的并发性能 | ||
b.Run(name+"_read", func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
w := sync.WaitGroup{} | ||
w.Add(routineSize) | ||
for j := 0; j < routineSize; j++ { | ||
go func(offset int) { | ||
defer w.Done() | ||
for i := offset; i < handleSize+offset; i++ { | ||
_, _ = m.Load(readSeq[i]) | ||
} | ||
}(handleSize * j) | ||
} | ||
w.Wait() | ||
} | ||
}) | ||
// 测试纯粹删除的并发性能 | ||
b.Run(name+"_delete", func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
w := sync.WaitGroup{} | ||
w.Add(routineSize) | ||
for j := 0; j < routineSize; j++ { | ||
go func(offset int) { | ||
defer w.Done() | ||
for i := offset; i < handleSize+offset; i++ { | ||
m.Delete(deleteSeq[i]) | ||
} | ||
}(handleSize * j) | ||
} | ||
w.Wait() | ||
} | ||
}) | ||
// 测试同时写入、读取的并发性能 | ||
b.Run(name+"_R&W", func(b *testing.B) { | ||
for i := 0; i < b.N; i++ { | ||
w := sync.WaitGroup{} | ||
w.Add(routineSize * 2) | ||
for j := 0; j < routineSize; j++ { | ||
go func(offset int) { | ||
defer w.Done() | ||
for i := offset; i < handleSize+offset; i++ { | ||
m.Store(insertSeq[i], struct{}{}) | ||
} | ||
}(handleSize * j) | ||
} | ||
for j := 0; j < routineSize; j++ { | ||
go func(offset int) { | ||
defer w.Done() | ||
for i := offset; i < handleSize+offset; i++ { | ||
_, _ = m.Load(readSeq[i]) | ||
} | ||
}(handleSize * j) | ||
} | ||
w.Wait() | ||
} | ||
}) | ||
} | ||
|
||
func BenchmarkMap(b *testing.B) { | ||
insertSeq := randomSeq() | ||
readSeq := shuffle(insertSeq) | ||
deleteSeq := shuffle(insertSeq) | ||
testReadWrite(b, "concurrentMap", NewConcurrentMap(2048, func(key interface{}) int { | ||
return key.(int) | ||
}), insertSeq, readSeq, deleteSeq) | ||
sMap := &sync.Map{} | ||
testReadWrite(b, "syncMap", sMap, insertSeq, readSeq, deleteSeq) | ||
} | ||
|
||
func TestMapPadding(t *testing.T) { | ||
m := NewConcurrentMap(2048, func(key interface{}) int { | ||
return key.(int) | ||
}) | ||
require.Equal(t, 64, int(unsafe.Sizeof(*m))) | ||
t.Log(unsafe.Sizeof(m.size)) | ||
t.Log(unsafe.Sizeof(m.segMask)) | ||
t.Log(unsafe.Sizeof(m.hasher)) | ||
t.Log(unsafe.Sizeof(m.segments)) | ||
t.Log("=======") | ||
ms := mapSegment{} | ||
require.Equal(t, 64, int(unsafe.Sizeof(ms))) | ||
t.Log(unsafe.Sizeof(ms.RWMutex)) | ||
t.Log(unsafe.Sizeof(ms.entries)) | ||
t.Log(unsafe.Sizeof(ms.size)) | ||
} |
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
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package gls | ||
|
||
import "runtime" | ||
|
||
func GetGoId() uint64 { | ||
return runtime.EllynGetGoid() | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package gls |