compiler,runtime: use the size hint when creating a new map

It defaults to hint/8 number of buckets. This number may be tuned in the
future.
Этот коммит содержится в:
Ayke van Laethem 2019-05-13 16:38:58 +02:00 коммит произвёл Ron Evans
родитель 17c42810d0
коммит 55fc7b904a
4 изменённых файлов: 34 добавлений и 5 удалений

Просмотреть файл

@ -1425,7 +1425,16 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
valueSize := c.targetData.TypeAllocSize(llvmValueType)
llvmKeySize := llvm.ConstInt(c.ctx.Int8Type(), keySize, false)
llvmValueSize := llvm.ConstInt(c.ctx.Int8Type(), valueSize, false)
hashmap := c.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize}, "")
sizeHint := llvm.ConstInt(c.uintptrType, 8, false)
if expr.Reserve != nil {
sizeHint = c.getValue(frame, expr.Reserve)
var err error
sizeHint, err = c.parseConvert(expr.Reserve.Type(), types.Typ[types.Uintptr], sizeHint, expr.Pos())
if err != nil {
return llvm.Value{}, err
}
}
hashmap := c.createRuntimeCall("hashmapMake", []llvm.Value{llvmKeySize, llvmValueSize, sizeHint}, "")
return hashmap, nil
case *ssa.MakeSlice:
sliceLen := c.getValue(frame, expr.Len)

Просмотреть файл

@ -60,14 +60,20 @@ func hashmapTopHash(hash uint32) uint8 {
}
// Create a new hashmap with the given keySize and valueSize.
func hashmapMake(keySize, valueSize uint8) *hashmap {
func hashmapMake(keySize, valueSize uint8, sizeHint uintptr) *hashmap {
numBuckets := sizeHint / 8
bucketBits := uint8(0)
for numBuckets != 0 {
numBuckets /= 2
bucketBits++
}
bucketBufSize := unsafe.Sizeof(hashmapBucket{}) + uintptr(keySize)*8 + uintptr(valueSize)*8
bucket := alloc(bucketBufSize)
buckets := alloc(bucketBufSize * (1 << bucketBits))
return &hashmap{
buckets: bucket,
buckets: buckets,
keySize: keySize,
valueSize: valueSize,
bucketBits: 0,
bucketBits: bucketBits,
}
}

13
testdata/map.go предоставленный
Просмотреть файл

@ -47,6 +47,18 @@ func main() {
println(testMapArrayKey[arrKey])
testMapArrayKey[arrKey] = 5555
println(testMapArrayKey[arrKey])
// test preallocated map
squares := make(map[int]int, 200)
for i := 0; i < 100; i++ {
squares[i] = i*i
for j := 0; j <= i; j++ {
if v := squares[j]; v != j*j {
println("unexpected value read back from squares map:", j, v)
}
}
}
println("tested preallocated map")
}
func readMap(m map[string]int, key string) {
@ -56,6 +68,7 @@ func readMap(m map[string]int, key string) {
println(" ", k, "=", v)
}
}
func lookup(m map[string]int, key string) {
value, ok := m[key]
println("lookup with comma-ok:", key, value, ok)

1
testdata/map.txt предоставленный
Просмотреть файл

@ -54,3 +54,4 @@ true false 0
42
4321
5555
tested preallocated map