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 RubyInlineRubyInline требует 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/
