Ruby очень легко интегрируется с языком программирования C. Можно создавать расширения для Ruby. Или мы можем сделать обертку для библиотеки на C, и использовать ее как обычную Ruby библиотеку. Так же можно реализовать критичные вычисления на C прямо в Ruby коде! Другой вариант интеграции — это использование Ruby в C/C++ программах, в качестве скриптового языка. Например, как это сделано в Google SketchUp.
Давайте посмотрим, какие возможности Ruby представляет для интеграции с C.
Пусть в нашей программе есть bottleneck, какой-то кусок вычислений, который, например, выполняется в цикле. Эти вычисления очень сильно понижают производительность приложения.
Решение — переписать критичный кусок на C, т.к. компилируемые языки заведомо быстрее интерпретируемых.
Тут у нас два варианта, либо создать расширение для Ruby, либо использовать код C прямо из Ruby.
Для начала выберем второй вариант, и в этом нам на помощь придет библиотека RubyInline.
Пусть у нас есть метод разложения числа на простые делители. Пойдем по самому простому пути, и реализуем этот метод алгоритмом перебора:
Но нас не устраивает скорость работы этого метода, по-этому перепишем его на C, с помощью библиотеки RubyInline.
Для начала установим ее:
RubyInline требует POSIX систему, т.е либо *nix, либо Cygwin на Windows.
А также C/C++ компилятор.
Простой пример использования:
В примере кода мы сделали небольшой C метод, возвращающий строку приветсвия.
Метод
— выполняет конверсию типов аргументов и возвращаемого значения из C в Ruby
— компилирует строку с кодом метода
— добавляет классу Test метод test
После этого мы можем использовать
Вернемся к факторизации. Перепишем метод factorization с помощью RubyInline.
А теперь, самое интересное. Тесты производительности.
Тест Ruby реализации:
Результат:
И аналогично C:
И результат:
Как видно из теста, RubyInline позволяет ускорить критичные куски кода практически в 10 раз!
Код тестов: factor.rb, factorfast.rb.
Подводя итог, можно сказать, что если наше приложение не справляется с нагрузками, то мы всегда можем его ускорить, реализовав критичные моменты на C. Благо Ruby предоставляет нам мощные и удобные средства для этого.
В следующей части я расскажу про создание C расширений для Ruby.
Ссылки по теме:
RubyInline: http://rubyforge.org/projects/rubyinline/
Документация: http://rubyinline.rubyforge.org/RubyInline/
Давайте посмотрим, какие возможности Ruby представляет для интеграции с C.
Пусть в нашей программе есть bottleneck, какой-то кусок вычислений, который, например, выполняется в цикле. Эти вычисления очень сильно понижают производительность приложения.
Решение — переписать критичный кусок на C, т.к. компилируемые языки заведомо быстрее интерпретируемых.
Тут у нас два варианта, либо создать расширение для Ruby, либо использовать код C прямо из Ruby.
Для начала выберем второй вариант, и в этом нам на помощь придет библиотека RubyInline.
Пусть у нас есть метод разложения числа на простые делители. Пойдем по самому простому пути, и реализуем этот метод алгоритмом перебора:
class Factor #num - входное число, show - выводить ли результат на экран def factorization num, show=false num1 = num n = 2 #начинаем поиск делителей с двойки while n*n <= num1 if num%n == 0 # если текущее число - делитель, выводим его num = num / n puts n if show else #иначе увеличиваем текущее число n += 1 end end end end
Но нас не устраивает скорость работы этого метода, по-этому перепишем его на C, с помощью библиотеки RubyInline.
Для начала установим ее:
gem install RubyInline
RubyInline требует POSIX систему, т.е либо *nix, либо Cygwin на Windows.
А также C/C++ компилятор.
Простой пример использования:
require 'rubygems' require 'inline' #подключаем RubyInline class Test #обработчик встроенного кода inline do |builder| #в блок передается объект класса Inline::C builder.c ' static char *test() { return "Hi from C!:)"; } ' end end puts Test.new.test # напечатает "Hi from C!:)"
В примере кода мы сделали небольшой C метод, возвращающий строку приветсвия.
Метод
c
выполняет следующие действия:— выполняет конверсию типов аргументов и возвращаемого значения из C в Ruby
— компилирует строку с кодом метода
— добавляет классу Test метод test
После этого мы можем использовать
test
как обычный Ruby метод.Вернемся к факторизации. Перепишем метод factorization с помощью RubyInline.
require 'rubygems' require 'inline' class FastFactor inline do |builder| builder.c ' static void factorization(int num, int show) { int i = 0; int num1 = num; int n = 2; while ( n*n <= num1 ) { if ( num%n == 0 ) { num = num / n; if ( show ) printf( "%d\n", n ); i ++; } else { n ++; } } } ' end end
А теперь, самое интересное. Тесты производительности.
Тест Ruby реализации:
f = Factor.new 1000.times { f.factorization 999999}
Результат:
$time ruby factor.rb real 0m1.034s user 0m1.028s sys 0m0.004s
И аналогично C:
f = FastFactor.new 1000.times { f.factorization 999999, false }
И результат:
time ruby factorfast.rb real 0m0.116s user 0m0.092s sys 0m0.024s
Как видно из теста, RubyInline позволяет ускорить критичные куски кода практически в 10 раз!
Код тестов: factor.rb, factorfast.rb.
Подводя итог, можно сказать, что если наше приложение не справляется с нагрузками, то мы всегда можем его ускорить, реализовав критичные моменты на C. Благо Ruby предоставляет нам мощные и удобные средства для этого.
В следующей части я расскажу про создание C расширений для Ruby.
Ссылки по теме:
RubyInline: http://rubyforge.org/projects/rubyinline/
Документация: http://rubyinline.rubyforge.org/RubyInline/