go のmap と戦ってみたの後、やはり linked listで作成した dirty の探査が遅い
という問題がある。
まぁhash table を自分で実は実装したことがないので、やってみようということでやってみた。
まずは Hash関数だけどこれはgo のruntime を呼び出してやるよくやるやり口だ
//go:noescape//go:linkname memhash runtime.memhashfuncmemhash(punsafe.Pointer,h,suintptr)uintptrfuncMemHash(data[]byte)uint64{ss:=(*stringStruct)(unsafe.Pointer(&data))returnuint64(memhash(ss.str,0,uintptr(ss.len)))}funcMemHashString(strstring)uint64{ss:=(*stringStruct)(unsafe.Pointer(&str))returnuint64(memhash(ss.str,0,uintptr(ss.len)))}funcKeyToHash(keyinterface{})(uint64,uint64){ifkey==nil{return0,0}switchk:=key.(type){caseuint64:returnk,0casestring:returnMemHashString(k),xxhash.Sum64String(k)case[]byte:returnMemHash(k),xxhash.Sum64(k)casebyte:returnuint64(k),0caseint:returnuint64(k),0caseint32:returnuint64(k),0caseuint32:returnuint64(k),0caseint64:returnuint64(k),0default:panic("Key type not supported")}}
hash 値から実際のアイテムを参照するような作りでやるとして
ふつうにやる感じだと
こういう感じで bucket(table) ごとにlinked list をもってやる。
bucket 自体もlinked list にしてしまえば bucket もlock free(concurrent) にできるし
しかし実装するのにbucket ごとにlinked list というのもめんどくさい
なので item は単一のlinked list にしてbucket からの参照用のdummy のitem を追加すれば
linked list 自体は 2本ですむ。