Використання переваг Go у Ruby

3 хв. читання

Я захоплююся Ruby, але у порівнянні з іншими мовами програмування він має завеликий час виконання, особливо при використанні комплексних алгоритмів. Загалом, структури даних у інтерпритованих мовах працюють повільніше, ніж у мовах, які підлягають компіляції. Деякі алгоритми, наприклад n-body або fannkuch-redux, написані на Ruby можуть бути до 30 разів повільніші ніж ідентичні, написані на Go. Це стало одною з причин моєї зацікавленості у інтеграції Go в оточення Ruby.

Для тих, хто не знає як взаємодіють спільні бібліотеки: вони працюють подібно до DLL бібліотек у Windows. Але вони мають власний, окремий код, з доступом до інтерфейсу компілятора С.

  • Зауваження: Windows використовує DLL систему, і у такому випадку немає необхідності тримати у проекті код бібліотеки. Прикладом слугують DLL написані на C#, які можуть використовуватися на віртуальній машині. Я не користуюсь Windows, тому не протестував виконання бібліотек таким чином.

Ви маєте використовувати Golang 1.5+ та Ruby 1.8.7+.

Створення Go бібліотеки

Вона буде мало чим відрізняється від інших бібліотек, проте матиме своєрідні особливості. Для використання зовнішніх функцій необхідно буде використати С. Проте для решти проекту використовується стандартний синтаксис Go.

Для цього необхідно підключити бібліотеку С:

import "C"

Пам'ятайте, що це слабка сторона Go, тому спробуйте створювати мінімально можливі інтерфейси, у яких будуть оброблюватися невелика кількість даних. Взагалі, перетворення типів даних Go у аналогічні на С відбувається надзвичайно повільно.

Сигнатура експорту функцій

Вам необхідно повідомити компілятору Go, які саме функції будуть знаходитися у бібліотеці. Для цього додайте export над необхідними функціями.

import "C"
//export my_add
func my_add(a, b C.int) C.int {
  return a + b
}
func main() {
  // Це необхідно для компілятора.
   // Ви можете додати щось, що буде
   // виконується при залученні вашої бібліотеки
   // до інтерпретатора.
}
  • Зауваження: Я знаю, що стандартна номенклатура Go відрізняється коду в прикладі, але у мене є звичка писати інтерфейси у стилі Ruby. Тому слова у імені функції розділяються нижнім_підкресленням, а не горбатимРегістром.

Запам'ятайте, що функція, яка буде експортуватися, має знаходитися у головному пакеті. Для компіляції запустіть команду:

go build -o my_lib.so -buildmode=c-shared my_file.go

Написання інтерфейсу для бібліотеки на Ruby

Це найшвидший шлях включення коду Go до оточення Ruby, у будь-якому випадку, слід пам'ятати, що використання Go інтерфейсу не буде супер швидким.

Додайте до вашого Gemfile наступний гем:

gem 'ffi'

Або встановіть його явно: gem install ffi

Просто створіть модуль і додайте в нього ваші сигнатури функцій з пакета Ruby, який ми створили раніше. Дещо подібне можна побачити у файлах з розширенням .h.

require 'ffi'
module Foo
  extend FFI::Library
  ffi_lib './my_lib.so'
  attach_function :my_add, [:int, :int], :int
end
puts Foo.my_add(2, 2)
# => 4

Що я помітив при використанні нативного Go у оточенні Ruby?

У певних ситуаціях, інтеграція Go з Ruby може бути швидкою і ефективною. Запуск нативного коду Go надає декілька переваг, наприклад різні графічні компоненти, інструменти для роботи з базами даних і ефективні структури даних, що включені до бібліотеки і імплементовані з Go і мають продуктивність підпрограм Go.

Пам'ятайте, що такий підхід можна використовувати при передачі невеликого об'єму даних між Go та Ruby. І це матиме сенс лише у випадку, якщо ви отримаєте значний приріст продуктивності, такий як приведені вище алгоритми, n-body і fannkuch-redux, що будуть компенсувати втрати продуктивності викликами функцій через бібліотеку на С для Go.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.7K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація