You can also use the internal map implementation and make us of the
runtime's map iterator. This is relatively straightforward at the cost
of vigilance for changes in the runtime.

Here is an example (note that yo need a .S file as well to get the
go:linkname magic to work).
https://github.com/gonum/gonum/blob/master/graph/iterator/map.go

(we back this with a reflect equivalent that it provided by 
https://golang.org/pkg/reflect/#MapIter.

Dan

On Thu, 2020-12-24 at 02:18 -0800, Arnaud Delobelle wrote:
> Hi there!
> 
> In my continued efforts to improve the performance of my Go Lua
> implementation [1], I have reached a bottleneck which causes me a
> quandary.
> 
> Lua has a data structure which is called 'table', which is
> essentially a hashmap.  So far I have implemented it as a Go map,
> which works OK.  However there is significant overhead coming from
> the fact that Lua has a `next` function that allows getting the
> "next" key-value pair in a table after a given one: `next(t, key)`. 
> As far as I can tell Go doesn't allow this so if I want to use a Go
> map, I also have to keep track of the next key for each key, which
> doubles the memory requirement, necessitates more accounting in the
> code and makes iteration via `next` slower.
> 
> So I am looking at not using the builtin Go map and making my own
> hashtable implementation.  However, because the keys are still made
> of Go values, I would like to benefit from the quick hashing that
> maps use.  After some poking around in the implementation of map (and
> discovering the //go:linkname compiler directive), I think that I can
> do this:
> 
> 
> // This is the Lua Value type.  The scalar part contains the payload
> of int64, float64 or bool for quicker access and minimising
> allocations.
> type Value struct {
>     scalar uint64
>     iface interface{}
> }
> 
> 
> //go:linkname goRuntimeInt64Hash runtime.int64Hash
> //go:noescape
> func goRuntimeInt64Hash(i uint64, seed uintptr) uintptr
> 
> //go:linkname goRuntimeEfaceHash runtime.efaceHash
> //go:noescape
> func goRuntimeEfaceHash(i interface{}, seed uintptr) uintptr
> 
> // Hash returns a hash for the value.
> func (v Value) Hash() uintptr {
>     if v.scalar != 0 {
>             return goRuntimeInt64Hash(v.scalar, 0)
>     }
>     return goRuntimeEfaceHash(v.iface, 0)
> }
> 
> Does that sound like a sensible approach?  I.e. is it safe enough to
> use the go:linkname directive, and do those seem like the right
> functions to call to obtain a good hash?
> 
> TIA
> 
> -- 
> Arnaud
> -- 
> You received this message because you are subscribed to the Google
> Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/79e3f124-037c-4c10-a7b6-42f496bd26b6n%40googlegroups.com
> .



-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/d2d742dcbb9ddf7d495255c9efdef2ec01e35096.camel%40kortschak.io.

Reply via email to