Оптимизация критичных в скорости алгоритмов в Ruby с помощью V8
Для критичных в скорости алгоритмов в Ruby возможно использование движка V8 JavaScript. В процессе проведения простейших тестов производительности, скорости выполнения программ (и более сложных, где сравнивалась уже производительность Ruby и PHP), и обсуждения с людьми выяснилось, что Ruby проигрывает в скорости JavaScript, который использует движок V8, что не удивительно, если верить Википедии: "Компиляция исходного кода JavaScript непосредственно в собственный машинный код, минуя стадию промежуточного байт-кода.". Фактически с движком V8 JavaScript переходит в разряд компилируемых языков, и сравнение с Ruby становится уже несправедливым, но тем не менее.
Но самое замечательное - в Ruby запросто можно использовать V8, подключив соответствующий gem - therubyracer, в Ruby on Rails он вообще требуется для работы. С помощью этого gem-а производится интеграция кода Ruby с кодом JavaScript.
Вот пример теста Фибоначчи и наглядные результаты выполнения:
require "benchmark" require "v8" def fib(n) return n if n <= 1 fib(n - 1) + fib(n - 2) end Benchmark.bm do | make | i = 0 6.times do make.report { puts fib(30 + i) } i += 1 end end ctx = V8::Context.new fib_js = ctx.eval <<-JS function Fib() { this.fib = function(n) { if (n <= 1) { return n; } return (this.fib(n - 1) + this.fib(n - 2)); }; } new Fib(); JS puts 'Using V8:' Benchmark.bm do | make | i = 0 6.times do make.report { puts fib_js.fib(30 + i) } i += 1 end end
Результаты:
user system total real 832040 0.250000 0.000000 0.250000 ( 0.248631) 1346269 0.400000 0.000000 0.400000 ( 0.400701) 2178309 0.640000 0.000000 0.640000 ( 0.639987) 3524578 1.030000 0.000000 1.030000 ( 1.029717) 5702887 1.670000 0.000000 1.670000 ( 1.669645) 9227465 2.700000 0.000000 2.700000 ( 2.700381) Using V8: user system total real 832040 0.030000 0.000000 0.030000 ( 0.034632) 1346269 0.060000 0.000000 0.060000 ( 0.053876) 2178309 0.090000 0.000000 0.090000 ( 0.086107) 3524578 0.130000 0.000000 0.130000 ( 0.137856) 5702887 0.220000 0.000000 0.220000 ( 0.216403) 9227465 0.360000 0.000000 0.360000 ( 0.353677)
Как можно видеть, алгоритм выполняется в ~7-8 раз быстрее. Хотя мне лично всегда было достаточно той скорости выполнения программ, которую предоставляет Ruby, никогда не сталкивался с тем, что Ruby где-то тормозит. Но на этом примере видно, что если кому-о недостаточно производительности, то есть способы оптимизации "узких мест" в программе.