Goにおけるreflectまわり調べた
javaとScalaとGoでそれぞれclass、型、インターフェース、メソッドの用語の意味が微妙に違うから混乱する
なんなら型クラスとかある
なぜ遅いか
- 静的な型付けがされていたり、コンパイルされていたりする言語でもリフレクションアクセスの場合は
interpretiveに解釈されるから
遅い reflectionは
メモリアロケーションが多く発生するため
遅い 恐らく、静的型且つ、コンパイル型であるGoにとってダイナミックにメモリアロケーションをするのは特にコストが高いのかも)makeFunc()を見てみると、makeFunc.go#62で呼び出しているfuncLayout()の処理が重そう(完全に雰囲気だけど)
funcLayout()は渡された汎用型(rtype)を「関数型だったら」「インターフェイス型だったら」とかいっこずつ分解していっって、値型によっても一つ一つみてレイアウト情報を取得してるっぽい。
if runtime.GOARCH == "amd64p32" {
みたいなコードもあるのでCPUアーキテクチャによる分岐もはいってる雰囲気
いかにも重そう(な雰囲気)型情報を取得するときは、ValueOf()でValue型に変換して、Type()を呼び出す
unsafe.Pointerを使って、型の種類ごとに処理が書いてある(Funcならこれやる、Interfaceならこれやるみたいな)
type.uncommon()でFuncなのかArrayなのか、Sliceなのか…を分岐で判断してる
それに応じてruntime/type.goのresolveTypeOff()でごにょごにょしてるが、reflectOffsLock()という関数を呼び出しているので、もしかしたらプロセスのメモリ空間のテキストセグメントにアクセスするときに、goroutine同士のメモリ競合しないようにロックを取得しているのかな?
参考
なぜリフレクションは遅いのか
http://postd.cc/why-is-reflection-slow/
golangのある生活
http://ameblo.jp/principia-ca/entry-11929774278.html
The Laws of Reflection
https://blog.golang.org/laws-of-reflection
How slow is Go’s reflection effectively?
https://groups.google.com/forum/#!topic/golang-nuts/HcfutSkJVoY
Unsafe in Go 甘美な世界
https://techblog.ca-reward.co.jp/2016/08/post-117.html