golangサポートtls


前言
golangの公式デフォルトはtls(Thread Local Storage)をサポートしていません.tlsをサポートする言語も多くありません.例えば、C++やGCC-C(gccのc言語拡張、linux用).goはtlsの実装を公式に拒否し,tls問題を解決するためにコンテキストcontextパケットを導入した(閉パケットもある程度コンテキストである).ローカル変数は、コンテキストパラメータ伝達によって伝達されます.この方法の利点は明示的なコンテキストが明確であり,悪い点は各関数に1つのコンテキストパラメータが必要であり,伝達されることである.ハッカーはもちろんこれに満足しないで、そこで1人の兄たちはgo-tlsをオープンソースしましたhttps://github.com/huandu/go-tlsコードは複雑ではなく、使用も簡単です.そのREADを参考にすればいいです.
go-tlsの原理
実装原理を簡単に説明します.各コヒーレンスにグローバル一意のインクリメントidを定義し、各コヒーレンスのデータを格納するためにグローバルmapを定義します.mapのkeyは、コヒーレントなg構造アドレスであり、データがコヒーレントに局所的であることを保証する.mapはグローバルであるため,複数のコヒーレンスが同時にアクセスし,臨界領域に属するため,読み書きロックが追加された.以下の定義
var (
	tlsDataMap  = map[unsafe.Pointer]*tlsData{
     }
	tlsMu       sync.RWMutex
	tlsUniqueID int64
)

Get/set/Delインタフェースを使用して、コパスのデータを取得、追加、削除します.
コプロセッサのデータは、コプロセッサの終了時に解放される必要がある場合があり、go−tlsは、FILOルールに従って実行される終了関数リストを導入した.
type tlsData struct {
     
	id          int64
	data        dataMap
	atExitFuncs []func()
}

AtExitインタフェースで終了プロセッサを追加します.
次に、コヒーレントのgを取得するアセンブリによって実現される
TEXT ·getg(SB), NOSPLIT, $0-8
    get_tls(CX) //MOVQ TLS, CX
    MOVQ    g(CX), AX //0(CX)(TLS*1)
    MOVQ    AX, ret+0(FP)
    RET

goのデフォルトgoexitをカスタムhackedGoexitに置き換えた特殊なハッカー技術により、上記のatExitFuncsの呼び出しを実現します.goexitを参照してください.go
このようにコヒーレントなtlsを実現した.contextの使用はある程度避けることができますが、もちろん公式の主張とは一致しません.
リスク
  • は、goコンパイラの後期にこのような更新があるかどうかという互換性を考慮する必要があります.goexitを置き換えるプロセスのようなハッカー技術を使用しているため、これは下位層と強く依存しています.
  • 読み書きロックを使用しているため、性能に敏感なニーズは慎重にしてください.syncをお勧めするかもしれません.Mapは普通のmap+読み書きロックの方式を置き換えて、実は私はあなたに教えて、個人はすでに単機で測定したことがあって、それらの2つの性能は相当して、甚だしきに至っては後者はsyncより優れています.Mapはまだほんの少しです.
  • メンテナンスコストを考慮する.公式推奨contextのためです.
  • 協程ではtlsを伝達できない.

  • 以上の4点に敏感でない需要シーンであれば、安心して使用できます.