Rubyへの共有ライブラリ接続を利用する

Go 1.5のリリースにより、他の言語のサードパーティプログラム用のgoライブラリを作成できるようになりました。 つまり、面白くて難しいことをするパッケージ、または既成のソリューションを作成して、それを別のGo以外のプログラムに接続することができます。 C、アンドロイド、客観的なCなどです。 Rubyに簡単に接続できる方法を示します。

1.進行中の問題に対する既製の解決策がある場合は、Rubyで書き直してください。
2. Goが、Cがよく機能するgemを使用した既製のソリューションではなく、独自のロジックについて話している場合、Rubyよりも明らかに高速です。
3.大量のデータを処理する必要がある場合、Goはより少ないメモリで済みます。

Goパッケージから始めましょう。

Goで迅速で適切なソリューションを作成する:
Goコード
package main import "C" //export add func add(x, y int) int { c := 0 for i := 0; i < 50000; i++ { c += x + y + 1 } return c } func main() {} 


これにはmainが含まれている必要があります。 必ず指定してください:
 import "C" 

また、外部から使用できる機能については、次を指定する必要があります。
 //export % % 

GOプログラムの準備ができたので、ビルドする必要があります。
 go build -buildmode=c-shared -o libadd.so testruby.go 

-buildmodeはGo 1.5で登場したもので、いくつかの異なるオプションがあります。c-sharedが必要です。 コンパイル後、.soおよび.hファイルを取得します。 これで、非GOプログラムとして接続できます。

現在、Rubyの一部です。

gem ffiが必要です 。 gem installまたはgemfile + bundle installを使用してインストールします。 ライブラリをRubyに接続します。
Rubyコード
 require 'ffi' module MegaSum extend FFI::Library ffi_lib 'lib/libadd.so' attach_function :add, [:int, :int], :int end 


ここで、.soファイルがどこにあるか、それが呼び出す関数( "// export"を記述したもの)、それらが受け入れるもの、返すものを示します(型の完全なリストはここにあります )。 その後、あなたは働くことができます:
挑戦する
  def self.add_go(x,y) Sum.add(x,y) end 


最初の呼び出しは少し遅くなります(おそらくすべてをメモリにロードします)。

ベンチマーク!
同じことを行うRubyコード
 def self.add_ruby(x,y) c = 0 i = 0 while i<50000 c += x + y + 1 i = i+1 end c end 


 [21] pry(main)> Benchmark.realtime { (1..1000).to_a.each {GoHello.add_ruby(3,2) }} => 1.763254 [22] pry(main)> Benchmark.realtime { (1..1000).to_a.each {GoHello.add_go(3,2) }} => 0.030442 [23] pry(main)> Benchmark.realtime { (1..100000).to_a.each {GoHello.add_go(3,2) }} => 3.103797 [24] pry(main)> Benchmark.realtime { (1..100000).to_a.each {GoHello.add_ruby(3,2) }} => 195.282368 

ご覧のとおり、単純な算術演算では、GoはRubyの60倍のパフォーマンスを発揮します。

短所:
1. Goでゴルーチンをたくさん飼育できるかどうかわからない。 私にとっては小さなチェック(数千のゴルーチンではありません)で機能しました。

P.C .: Pythonにも同様のソリューションがあります

Source: https://habr.com/ru/post/J266037/


All Articles