Hi there! Looking at performance bottlenecks for my implementation of Lua in Go ([1]), I found that type assertions can have a significant cost, which feels unnecessary to me. I couldn't explain it without quite a lot of context, which makes my post quite long - sorry about that!
I have a Value type that holds Lua values: // A Value is a runtime value. type Value struct { scalar uint64 iface interface{} } As Lua is dynamically typed, values can hold any type. In the Lua runtime implementation, there are "type assertion" functions to convert a Value to a specific Go type, among which is the Cont interface type ([2]) which represents a continuation: func (v Value) AsCont() Cont { return v.iface.(Cont) } This function is called every time a Lua function is called and turns out to be costly when many function calls are made. I know exactly what types implement the Cont interface, so I tried an other implementation of AsCont as follows: func (v Value) AsCont2() Cont { switch cont := v.iface.(type) { case *GoCont: return cont case *LuaCont: return cont case *Termination: return cont default: // Only the types above implement the Cont interface panic("value is not a continuation") } } Here is a benchmark comparing AsCont and AsCont2. func BenchmarkAsCont(b *testing.B) { v1 := ContValue(new(GoCont)) v2 := ContValue(new(LuaCont)) v3 := ContValue(new(Termination)) b.ResetTimer() for i := 0; i < b.N; i++ { _ = v1.AsCont() _ = v2.AsCont() _ = v3.AsCont() } } func BenchmarkAsCont2(b *testing.B) { v1 := ContValue(new(GoCont)) v2 := ContValue(new(LuaCont)) v3 := ContValue(new(Termination)) b.ResetTimer() for i := 0; i < b.N; i++ { _ = v1.AsCont2() _ = v2.AsCont2() _ = v3.AsCont2() } } $ go test -run='^$' -bench '^(BenchmarkAsCont)' github.com/arnodel/golua/runtime goos: darwin goarch: amd64 pkg: github.com/arnodel/golua/runtime cpu: Intel(R) Core(TM) i7-7820HQ CPU @ 2.90GHz BenchmarkAsCont-8 52798504 20.96 ns/op BenchmarkAsCont2-8 433032686 2.866 ns/op PASS ok github.com/arnodel/golua/runtime 2.908s There's a very significant difference in this benchmark, and in some "real tests" benchmarking Lua code I get ~15% speedup, which is pretty good. Now here are my questions. Question 1: I *think* that the compiler has all the information necessary to implement type assertion to the Cont interface as I have, i.e. it knows only 3 types implement that interface, so could it not do the optimisation on my behalf? Question 2: Or is it possible that other Go values can be made at runtime that would implement this interface but not be one of the three known types that implement it? Question 3: Is it possible that there is something dodgy going on with the benchmarks, with some code being optimised away - if so, how can I check that? Thanks in advance for any insights! -- Arnaud [1] https://github.com/arnodel/golua [2] Definition of the Cont interface type: type Cont interface { Push(Value) PushEtc([]Value) RunInThread(*Thread) (Cont, *Error) Next() Cont DebugInfo() *DebugInfo } -- 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/efcf0a84-4e7d-4241-9f5a-994774a7f14dn%40googlegroups.com.