If Node.js is single threaded, what is Rails? - ruby-on-rails

If we say Node.js is single threaded and therefore there is just one thread that handles all the requests, what is Rails?
As I understand, Node.js is both the application and the server, but I am lost on what Rails would be? How does Rails handle requests in terms of threads/processes?

Rails can be single-threaded, it can be multi-threaded, it can be multi-process (where each process is single-threaded), or it can be multi-process where each process is multi-threaded.
It really all depends upon the app server you're using, and it kind of depends upon which Ruby implementation you're using. MRI Ruby supports native threads as of 1.9, but it still maintains what's known as a global interpreter lock. The GIL prevents the Ruby interpreter from running in multiple threads at a time. In most cases that's not really a big deal though, because the thing threads are helping with the most is waiting for I/O. If you're using either JRuby or Rubinius, they can actually run Ruby code in multiple threads at a time.
Check out the different app servers and what they offer in terms of concurrency features. Unicorn is a common one for deploying multi-process/single-threaded applications. Puma is a newer app server that's capable of running multi-threaded applications, and I believe they're either adding (or maybe have added by now, I'm not sure) the ability to run multi-process as well. Passenger seems to be able to work in every model I've listed above.
I hope this helps a little. It should at least give you some things to Google for to find more information.

Related

Why rails 5 using puma instead of webrick for development purpose?

I tried to find out the difference between the Puma and Webrick, but didn't get it or satisfied with it.
So could any one please share information regarding it.
By default WEBrick is single threaded, single process. This means that if two requests come in at the same time, the second must wait for the first to finish.
The most efficient way to tackle slow I/O is multithreading. A worker process spawns several worker threads inside of it. Each request is handled by one of those threads, but when it pauses for I/O - like waiting on a db query - another thread starts its work. This rapid back & forth makes best use of your RAM limitations, and keeps your CPU busy.
So, multithreading is achieved using Puma and that is why it is used as a default App Server in Rails App.
This is a question for Ruby on Rails developers rather than broad audience, because I don't understand reasons any other that putting development environment closer to production where Puma is a solid choice.
To correct the current answer however, I must say that Webrick is, and always has been, a multi-threaded web server. It now ships with Ruby language (and also a rubygem is available). And it is definitely good enough to serve Rails applications for development or for lower-scale production environments.
On the other hand it is not as configurable as other web servers like Puma. Also it is based on the old-school new thread per request design. This can be a problem under heavy load which can lead to too many threads created. Modern web servers solve this by using thread pools, worker processes or combination of the two or other techniques. This includes Puma, however for development spawning a new thread per request is totally fine.
I have no hard feelings for any of the two, both are great Ruby web servers and in our project we actually use them both in production. Anyway, if you like using Webrick for RoR development, you indeed can still use it:
rails server webrick
Rails 6.1 Minor update:
rails server -u webrick [-p NNNN]

New rails project with MRI Ruby2 or JRuby 1?

I am new to Ruby on Rails and beginning a project soon. Having read about different Ruby implementations, I am wondering which setup to use. My project is expected to have a fair amount of traffic.
I am considering two optiosn: MRI Ruby (v 2.0) and JRuby (v 1.9). I am concerned that MRI Ruby is not multithreaded and am worried about the impact this will have on the web app. Perhaps the application server can eliminate this problem? Right now it looks like we will be using Puma as the application server.
In short, should I use JRuby because it is multithreaded on 1.9 or should I use MRI Ruby on 2.0?
TL;DR
Using either Puma or Passenger negates this issue because they handle threads on their own. I would recommend working with the newest version of Ruby and Rails possible as this will minimize the upgrade work you need to do when upgrading your app.
Here is a wonderful article which addresses your issue.
To summarize.
Puma is multithreaded-only. The open source variant of Phusion
Passenger is multi-process single-threaded. The Enterprise variant can
be configured to be either single-threaded or multithreaded.
...
Both Puma and Phusion Passenger Enterprise can be hybrid multi-process
multi-threaded. That is, running multiple multithreaded processes.
Hybrid mode allows Ruby and Python, which despite having a Global
Interpreter Lock, to fully utilize all CPU cores.[1] In Puma, the
hybrid mode is called "clustered".
[1] Only the case on MRI, not on JRuby and Rubinius. JRuby and Rubinius fully support multi-core threads in a single process.
In other words, both Puma and Passenger are able to treat any Ruby implementation as multi threaded. They do this by using a hybrid between multiple processes and multiple threads. This is only minimally heavier than simple multi-threading.
To be honest, I don't think this is an issue you need to worry about at this time. Wait to see how your server handles the site's traffic.
Honestly, if you are new to Ruby and Rails, just stick with the defaults - MRI in this case. Ruby enjoy several great implementations (MRI, JRuby, Rubinius, ...) that will run your web application without any problem. Starts with MRI, you can always decide to change later if needed.
You will be in a much better position to judge what is the best Ruby implementation and server when the work on your application will have started - more proficient on the plateform, and more aware of your specific challenges (not every application is that dependent on multi threading performance).
Enjoy the road!

Mongrel does not use the full CPU power on Windows 2003 server

I have a deployment using:
rails 2.3.2
ruby 1.8.7
mysql db
and
3 mongrel instances (windows services) with apache as load balancer
[I know it is due for upgrade...]
OS: Windows2003
We have many CPU intensive tasks and when these occur on the 4 core machine the mongrel process is able to only use a max 25% cpu power on the core the task was scheduled.
After running many tests we noticed that it is only able to use the power of a single core and therefore there is time lag in finishing tasks.
There is a suggestion to virtualize... which is difficult to do on the client server.
Has anyone got any suggestion on how the situation can be improved? Memory does reach 250MB to 1GB for this process but this not such a big issue.
Thanks in advance
Linus
The typically used Ruby versions (MRI or YARV, i.e 1.8 or 1.9) are not able to use more than one core at a time. MRI is single-threaded and just provides green threads internally. YARV uses real OS threads but has a GIL (global interpreter lock) that ensures that only one thread is running at a time.
Thus, your mongrels are unable to use more than one core each (even if you would have coded your Rails app to be threadsafe). There are alternative Ruby implementations, like JRuby or Rubinius that provide native threads without a global interpreter lock and thus allow your app to use more than one core, but you'd probably need to adapt your app a bit.
That said, even then a single request would run in a single thread and thus only use a single core. But that is something that is hard to come by without you handling your own threads (or at least fibers in 1.9) which is most probably not worth the hassle.
So generally, the recommendation is to start multiple app server processes (mongrels in your case). I personally use about 1.5 - 3 per core (depending on the app). That way, you are able to answer that many parallel requests and fully use your available CPU power shared between them.

Rails (3) server - what to use nowadays?

I've been using Ruby Enterprise Edition and Passenger (for Apache, since I run Apache anyway for other things) for some time, but I'm wondering if there's a new trend about what to use on servers nowadays.
For example I've heard about Thin, Unicorn... I also know that 1.9.2 is faster than REE, but I wonder about RAM consumption. I'd rather have it consume less RAM even at the expense of some speed.
Thanks for all advice.
If you want minimal memory you should try Thin.
It does not have master worker as Unicorn or Passenger, thus uses less memory.
Suppose you have a very small app that needs to run on a small VM, then you can use 1 thin worker + nginx. I ran several rails 3.2 apps using Thin+nginx+postgres on 256MB VMs without swapping.
Unicorn is faster but it needs a master worker. It's good if you want to run on Heroku, you can set it 2 or 3 workers and be within the 512MB limit.
If your app is very big and you have too many long running requests, I would check out jRuby and Thinidad/Torquebox.
I converted a few apps from MRI+Sidekiq to jruby+Trinidad+Trinidad_Scheduler. I get about 100-200 req/sec using a pool of 50 threads in a trinidad server!
What I like about jRuby is that you can combine everything on one Rails Server. You can put together on the same JavaVM the cache_store with EHcache, Scheduling, Background processing and real multithreading.
You don't need to run redis, memcached, resque or sidekiq separately.
Im not saying they are not good, I love sidekiq and resque, but you can decrease your complexity by combining everything on one process and have high concurrency.
A more advanced and Enterprise solution is Torquebox, it has support for clustering and is super scalable. But I've had problems with my app crashing on torquebox, so i'm sticking to Trinidad for now.
The disadvantages of jRuby? MEmory! A Trinidad server will use minimum 512MB, up to 2-3GB ram.
Also, for Single Thread server, a single request from a rails app running Ruby-1.9.3 is about twice as fast as the same request on jRuby.
Another option is Puma, you can get full multithreading on MRI with puma. I myself could not get it stable enough on my apps.
So, it all depends on your requirements, memory usage, full threading and concurrency.
Apart from Passenger, have a look at Unicorn, Trinidad, Puma and Torquebox. Those seems to be the top rails servers right now.
There is an great book with an introduction of converting your Rails app to jRuby and deploy your app using several methods such as trinidad.
http://pragprog.com/book/jkdepj/deploying-with-jruby
The Torquebox Documentation is amazingly good. It's very detailed and explains really good how to use all Torquebox features.
http://torquebox.org/documentation/
I Hope that sharing my experience has helped.
Passenger is still extremely strong, especially being REE will naturally support 1.9 in the near future. The fact that your application can crash, however it won't affect anything else on your machine is an amazing feature to have. Deploying code is extremely easy because the server will continue to accept connections, which means less frustration/stress for you.
However, in terms of comparisons:
Here is a great resource is check out various comparisons(including memory consumption) with all the new servers.
It compares Thin, Unicorn, Passenger, TorqueBox, Glassfish, and Trinidad:
http://torquebox.org/news/2011/03/14/benchmarking-torquebox-round2/
Mike Lewis' link does a good job of comparing those different ruby servers. My personal experience has been with nginx/REE/Passenger and its been good. I haven't tried the others, so I can't comment on that.
However, I can speak on RAM usage. Your biggest savings of RAM will come from using 32-bit servers. In my experience (3x 3GB app servers), 64-bit REE/passenger processes took up to 2x as much RAM as their 32-bit counterparts. We saw a significant performance increase moving from 64 to 32 bit servers, everything else staying the same. Unless your application requires 64-bit, I would suggest running your application servers (not database) in 32-bit.
Passenger is still a very good choice to use so you are not behind the times or anything. It is also actively supported and has a very good development team that contributes a lot to the community. We have been using Unicorn and it has been very good. Our favorite functionality is to be able to upgrade apps/ruby/nginx without dropping a connection.

What do you mean Ruby on Rails is not thread safe?

I was just reading up on ROR (haven't dived into it yet), and I hear that it isn't thread safe. Obviously, this doesn't mean that more than one person can't access your site at one time, so what exactly does it mean? Where do threads come into play in ROR? Do they just mean the request handling?
Your information is out of date.
It is thread safe as of 2.2.2
Keep in mind Ruby MRI 1.8.x, the most widely used implementation of Ruby uses Green Threads, so with 1.8.x if you create 100 threads they all run on the same CPU. Therefore when hosting Rails websites using MRI, you probably want as many instances of Ruby running as you have CPUS. Stuff like passenger takes care of this for you.
This used to be a big problem for JRuby, because JRuby has Native threads, and juggling processes seems superfluous. Anyway, its sorted out now.
On an aside, Iron Ruby, the .Net Ruby interpreter runs native threads.
Note: Ruby 1.9.1 uses native threads, but there is still a global interpreter lock in place.
Basically what it's saying is that you can't have multiple copies of rails running in the same process under different threads because it is possible for some of the resources to leak between the threads unintentionally causing weird behavior such as objects seemingly changing/disappearing at random times.
Additionally, it could also be the case that classes aren't designed with any synchronization built into them, making it hard to put parts of rails into threads and have other parts be shared among threads.
It's worth mentioning that Ruby MRI 1.8.x uses Green Threads, but Ruby MRI 2 will have native threads.

Resources