私が取り組んでいるプロジェクトでは、Go から一連の C 関数を使用する必要があります。現在の実装では cgo を使用してそれを実現していますが、これを行うとパフォーマンスに大きな影響が生じるため、これを取り除こうとしています。
- cgo はすべての C コードを syscall としてマークし、必要に応じてスケジューラに新しいスレッドを割り当てさせます。プロジェクトの CPU 時間の約 80% が重い C 作業に費やされているため、すぐに多くのスレッド (
GOMAXPROCS
(= 8) ではなく 500 以上) を持つことになり、Linux カーネルはこれをあまり好みません。 - 通常の「リミッター」アプローチ (バッファリングされたチャネルに cgo 呼び出しをロックさせる) を行うと、多数のミューテックスが発生し、プログラムの速度が低下します。
Go は並行性を管理する優れた方法であるため、このプロジェクトでは引き続き Go を使用したいと考えています。
私が試したこと:
- のようなものをコメントアウトします (あまり役に立たないよう
entersyscall()
でsrc/runtime/cgocall.go
、Go コードの変更は避けたいと思います)。 - 私のコードを .c ファイルに入れて、.c なしで Go から呼び出します
import "C"
。ここで運が悪い-関数を呼び出すことができず、関数名を書いたときにpackage·function
、コンパイラがファイル内の無効な文字について不平を言った。 - .s ファイルを使用し、それをアセンブリとして記述します。私のasmはそれほど素晴らしいものではなく、理解できませんでした。
だから、私の質問は: cgo のオーバーヘッドを回避しながら、Go から C 関数をどのように使用するのですか?
補足: cgo がすべての呼び出しを syscall としてマークする理由はわかっていますが、この特定のケースでは、呼び出す関数はロックまたは IO でブロックされません。