#365 Thread-Safety pro
Jul 09, 2012 | 10 minutes | Performance, Production, Rails 4.0
The config.threadsafe! option will likely be enabled by default in Rails 4.0. Here you will learn what this option does, how it affects production, and some tips on thread safety.
- source codeProject Files in Zip (45.2 KB)
- mp4Full Size H.264 Video (20.1 MB)
- m4vSmaller H.264 Video (12 MB)
- webmFull Size VP8 Video (14.6 MB)
- ogvFull Size Theora Video (25.7 MB)
I'm using Unicorn in production, and I have a (probably) dumb question. If I enable threadsafe, will this help (even if just slightly) the memory usage by not loading the Rack::Lock middleware?
I don't think that it will help you, because of preload_frameworks. Normally classes are lazy loaded - so you have only classes that you need in memory. With this option everything will be loaded at start. If you want to remove Rack::Lock I would rather check if there's an separate option for it.
No, I don't think so.
You mentioned Rubinius/JRuby - how about an episode deploying to these platforms?
btw. could someone tell how would look like updating same records by different threads? Checking updated_at or some locks?
Yes, this is a database problem, not a thread problem.
+1 Yes something introducing jRuby would be great for instance I think TorqueBox is great and more people should be looking at it.
+1 for TorqueBox. An episode deploying TorqueBox to Engine Yard would be fantastic.
another +1 for TorqueBox.
Torquebox is great and has it own screencasts : http://torquebox.org/podcasts/
Another +1 for TorqueBox.
you might be interested in this book? recently released by Pragmatic Programmers - http://pragprog.com/book/jkdepj/deploying-with-jruby "Deploying with JRuby: Deliver Scalable Web Apps using the JVM"
Thanks for the video, I found it very useful. You mentioned at the end that Rails' controllers are limited by database Pool connection size, even when you're not using a database connection in your action. That kind of floored me, I've written tons of controller actions that never talk to ActiveRecord, never realizing that AR could still be a bottleneck.
I almost fell over too not knowing this. The fact that Rails is reserving a connection I guess part of the 'magic'. I'm wondering now if there's something out I can use to tell Rails not to reserve a connection, or to make controllers explicitly define whether they require a connection...
Very useful screencast and I was interested in this when T-Love originally posted.
Anyone know if attr_accessible is considered a class variable (i.e., requiring a mutex lock if I enable Threadsafe!)?
I have a Post model that dynamically sets attr_accessible from the Posts controller based on a user's permission.
The controller action first looks up the user and then looks up the user's permissions (for example, an admin user would have all fields accessible.) Would I wrap this in a mutex? Any idea how to even test concurrent action calls with more involved than just hitting a controller action with a generic get (i.e., a put or post with data...)?
If you do it the way episode #237 does it you will be good.
I have one question about the class variable that is preceded by @@, I know that the Web is stateless and everytime a request comes to a server it is as if it's the first time they meet each other. since I don't see any database in the example, the @@counter must be incremented 5 times to get to the number 5, but if it loses its state in each request, how does it ever get up to 5? does that repeat 5 command tell the connection to stay alive for another request? or is that & at the end of the curl command doing this? I hope I am making sense here...
Rails is not a PHP framework where every request always destroys and creates all variables and object over and over again. In Rails class variables are created once during boot time. They are not recreated with incoming new HTTP request. So in multithreaded mode those variables should not be changed or should be guarded by mutex.
Thanks for saving me a few hours of research to understand the significance of the change.
I've been playing with this setting and have run into a bit of a gotcha.
tl;dr - models don't load in rake tasks/migrations - do this:
config.threadsafe! unless $rails_rake_taskor explicitly require the model.
dependency_loading = falsesetting in the
threadsafe!method means that you won't have access to your models in migrations or rake tasks (ie. db:seed).
It's described here this old rails issue and discussed in this article.
Thanks for the heads up!
Just logged in to post this gotcha too, but then I saw your comment.
This should be added to rails guides and definitely to release notes or something...
Cool, thanks very much. I will try it later.
Is repeat a ZSH command? Is that available for bash? I can't figure out where you got it.
Can someone point me in the right direction?
Found it: http://www.stefanoforenza.com/how-to-repeat-a-shell-command-n-times/
thanks, I had the same question.
Are Time.zone or I18n.locale thread safe? They seem like class variables, but are used in most Rails apps.
It seems they are thread-safe since they rely on Thread.current: directly from guides.rubyonrails.org
I see that paper_trail gem uses the Thread.current to pass current_user to model. Is it safe to use it when we use server like puma?
How did you get this 'repeat' command?
Hi, I got this question. What if in the bar action, instead of saying
The developer can just type as:
Is my last code considered to be thread-safe?
In Java, we may need to put a keyword 'volatile' on variables of an object which is shared across different threads. What about Ruby in our case ??
Thanks if you could let me know
This is not thread-safe at all. Mutating static scope is never threadsafe.
When asking what is thread-safe and what isn't it also depends on your application. In generall mutating shared state without a mutex, semaphore etc. is not threadsafe.
For Rails you have a seperate controller instance per web request thread. So mutating
controller instance vars and all the instance vars of the objects created by controllers is threadsafe, whereby mutating statics is not, because it is shared among all threads.
Rubyists hack around this with the Thread.current Hash
If you're looking for a non-blocking, real time Rails solution, check out Entangled: https://github.com/dchacke/entangled
Thanks for this