Created on 2018-03-05
Modified on 2018-06-25
Published on 2018-03-11
Golang 1.9 ~ 1.10くらいのときに調べた内容。 古くなっている情報を見つけたら教えてくれると嬉しいです。
標準ランタイムでは、stacktraceから取得する方法がある。 しかし、非常に遅い。
const backtraceSize = 1 << 16 // about 64KiB
const gidRegExp = regexp.MustCompile(`^goroutine (\d+)`)
// GoID returns the Goroutine ID.
func GoID() {
var buf [backtraceSize]byte
runtime.Stack(buf[:], false) // First line is "goroutine xxx [running]"
matches := gidRegExp.FindSubmatch(buf[:])
gid, err := strconv.ParseInt(string(matches[1]), 10, 64)
if err != nil {
log.Panic(err)
}
return logutil.GID(gid)
}
runtime
パッケージにこのようなパッチを当てると、高速に取得できる。
// GoID returns the Goroutine ID.
//go:nosplit
func GoID() int64 {
gp := getg()
return gp.goid
}
シンボルに関する情報は、TEXT segmentにコンパクトな形式で格納されている。 アクセスするのはちょっとめんどくさい。
闇が深そうな実装だ。。。。
// NOTE: There are *three* independent implementations of this object
// file format in the Go source tree:
//
// - cmd/internal/goobj/read.go (used by cmd/addr2line, cmd/nm, cmd/objdump, cmd/pprof)
// - cmd/internal/obj/objfile.go (used by cmd/asm and cmd/compile)
// - cmd/link/internal/objfile.go (used by cmd/link)
go/doc.go at release-branch.go1.10 · golang/go
こんな感じ。 全てのモジュール(通常は1個しかない)に対してループし、モジュール内部にある全ての関数に対してループするだけ。 Func構造体のアドレスは、pclntableから取得できる。
for _, md:=range runtime.activeModules() {
for idx, ft:=range md.ftab {
f := (*Func)(unsafe.Pointer(mrand.pclntable[ft.funcoff])
file, line := runtime.funcline1()
}
}
runtime.moduledata構造体のフィールドの1つ。 いろいろなデータを詰め込んだbyteスライス。
pclntableの中に入っていることを確認したデータ一覧 (順不同)
詳細はコンパイラのドキュメントとソースコード、runtimeのHACKING.mdを参照。
runtime.gostringnocopy()
null終端のbyteスライスから文字列オブジェクトを生成する。
渡したbyteスライスの内容は変更してはいけない。
s := gostringnocopy(&buf[0])
のように使う。
//go:nosplit
スタックオーバーフローチェックをしない。
おそらく、呼び出し元の関数と同一のスタックフレームが使われるはず。
これ使用するときは、消費するスタックサイズを小さくしておかないと、問題が発生しそうだ。
//go:nowritebarrier
runtimeパッケージ内のみで使える。 関数内に、Garbage CollectionでのWrite
Barrier処理が含まれていると、コンパイルエラーを起こす。
これを指定すると、ヒープ内のポインタを書き換えることが出来なくなる。
効果も薄いし、使いどころは限られるだろう。
Stack Traces In Go Go, (Golang) Programming - Blog - Ardan Labs
==
演算子で構造体をできないようにするテクニック。
IncomparableStruct
同士を比較しようとすると、コンパイルエラーを起こす。
type IncomparableStruct struct {
SomeFields int
// This artifact prevents this struct from being compared
// with itself. It consumes no space as long as it's not the
// last field in the struct.
_ [0]struct{ _ []byte }
}