Last active
November 5, 2015 15:32
-
-
Save mindreframer/9879200 to your computer and use it in GitHub Desktop.
therubyracer freezes, if used in webservice
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
##### freezes after a couple of requests... | |
# OS: osx 10.9.1, libv8 (3.16.14.3 x86_64-darwin-13), therubyracer (0.12.1) | |
# gem install sinatra therubyracer json puma | |
# rackup sinatra-nodejs.ru | |
# wrk -t 2 -d 3 http://0.0.0.0:9292/am | |
# webserver (puma/webrick) does not make any difference | |
require 'sinatra/base' | |
require 'json' | |
require 'v8' | |
SUGGESTIONS = [] | |
File.foreach("/usr/share/dict/words") do |line| | |
SUGGESTIONS << line | |
break if SUGGESTIONS.size > 200 | |
end | |
class HelloWord < Sinatra::Base | |
get '/:q' do | |
matches = get_matches(params[:q]) | |
halt 200, {'Content-Type' => 'text/json'}, matches.to_json | |
end | |
def get_matches(q) | |
matches = nil | |
with_proper_vm_lock do | |
ctx = V8::Context.new | |
ctx['suggestions'] = SUGGESTIONS | |
ctx['q'] = q | |
matches = Array(ctx.eval(<<-eojs | |
suggestions.filter(function(suggestion) { | |
return suggestion.search(q) > -1; | |
}).slice(0,10); | |
eojs | |
)) | |
ctx.dispose() | |
end | |
matches | |
end | |
def with_proper_vm_lock | |
V8::C::Locker() do | |
V8::C::HandleScope() do | |
@cxt = V8::C::Context::New() | |
begin | |
@cxt.Enter() | |
yield | |
ensure | |
@cxt.Exit() | |
end | |
end | |
end | |
end | |
end | |
run HelloWord |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
##### v.2, with connection_pool.... still freezes. | |
##### freezes after a couple of requests... | |
# gem install sinatra therubyracer json puma | |
# rackup sinatra-v8-connection-pool.ru | |
# wrk -t 2 -d 3 http://0.0.0.0:9292/am | |
# webserver (puma/webrick) does not make any difference | |
require 'sinatra/base' | |
require 'json' | |
require 'connection_pool' | |
require 'v8' | |
require 'execjs' | |
SUGGESTIONS = [] | |
File.foreach("/usr/share/dict/words") do |line| | |
SUGGESTIONS << line | |
break if SUGGESTIONS.size > 200 | |
end | |
class Renderer | |
class << self | |
attr_accessor :pool | |
def setup! | |
@pool.shutdown{} if @pool | |
@pool = ConnectionPool.new(:size => 10, :timeout => 20) { self.new } | |
end | |
def render(q) | |
@pool.with do |renderer| | |
renderer.render(q) | |
end | |
end | |
end | |
def context | |
@context ||= ExecJS.compile('1+1') | |
end | |
def render(q) | |
jscode = <<-JS | |
function() { | |
var q = '#{q}'; | |
var suggestions = #{SUGGESTIONS.to_json} | |
return suggestions.filter(function(suggestion) { | |
return suggestion.search(q) > -1; | |
}).slice(0,10); | |
}() | |
JS | |
context.eval(jscode) | |
rescue ExecJS::ProgramError => e | |
"[Renderer] #{e.message}" | |
end | |
end | |
Renderer.setup! | |
class HelloWord < Sinatra::Base | |
get '/:q' do | |
matches = get_matches(params[:q]) | |
halt 200, {'Content-Type' => 'text/json'}, matches.to_json | |
end | |
def get_matches(q) | |
Renderer.render(q) | |
end | |
end | |
run HelloWord |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Did you make any headway figuring out why? I am wanting to do something similar on running js on the server and trying to decide between just using node directly or therubyracer within sinatra/rails. Also considered elixir, but it doesn't have the power of therubyracer.