{"id":44311,"date":"2016-11-28T22:56:31","date_gmt":"2016-11-28T19:56:31","guid":{"rendered":"https:\/\/www.altoros.com\/blog\/?p=44311"},"modified":"2019-06-18T17:24:17","modified_gmt":"2019-06-18T14:24:17","slug":"performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016","status":"publish","type":"post","link":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/","title":{"rendered":"Performance Comparison of Ruby Frameworks 2016"},"content":{"rendered":"<p>The Ruby ecosystem is constantly evolving. There have been many changes in the engineering world since our <a href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-sinatra-padrino-goliath-and-ruby-on-rails\/\">comparison of Ruby frameworks<\/a> in 2014. During the two years, we received a few requests from fellow engineers asking for an updated benchmark. So, here is the 2016 edition with more things tested.<\/p>\n<p>&nbsp;<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Whats_under_evaluation\" >What&#8217;s under evaluation?<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Performance_of_Ruby_frameworks\" >Performance of Ruby frameworks<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Performance_of_Ruby_template_engines\" >Performance of Ruby template engines<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Performance_of_Rack_application_servers\" >Performance of Rack application servers<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Performance_of_ORMs\" >Performance of ORMs<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Performance_of_other_languages_and_frameworks\" >Performance of other languages and frameworks<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Conclusion\" >Conclusion<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#Further_reading\" >Further reading<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"Whats_under_evaluation\"><\/span>What&#8217;s under evaluation?<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Of course, there are a lot of performance benchmarks on the web. For instance, <a href=\"https:\/\/www.techempower.com\/benchmarks\/\" target=\"_blank\" rel=\"noopener noreferrer\">this one<\/a> is very good and compares different frameworks as they operate in a viable production configuration.<\/p>\n<p>However, we wanted to understand how Ruby frameworks behave when used as basic solutions with default settings. The idea was to measure only framework speed, not the performance of the whole setup. All the tests were extremely simple, which allowed for comparing almost anything and avoiding side effects caused by very specific optimizations.<\/p>\n<p>So, we implemented bare minimum testing samples for this benchmark and evaluated the performance of:<\/p>\n<ul>\n<li>Ruby frameworks (compared with Ruby)<\/li>\n<li>Ruby template engines<\/li>\n<li>Rack application servers<\/li>\n<li>Ruby ORM tools<\/li>\n<li>other languages and frameworks<\/li>\n<\/ul>\n<p>All of the frameworks and tools were tested in the production mode and with disabled logging. The performance of the technologies was measured, while they were executing the following tasks:<\/p>\n<ul>\n<li style=\"margin-bottom: 6px;\"><strong>Languages<\/strong>: Print a \u201cHello, World!\u201d message.<\/li>\n<li style=\"margin-bottom: 6px;\"><strong>Frameworks<\/strong>: Generate a \u201cHello, World!\u201d web page.<\/li>\n<li style=\"margin-bottom: 6px;\"><strong>Template engines<\/strong>: Render a template with one variable.<\/li>\n<li style=\"margin-bottom: 6px;\"><strong>Application servers<\/strong>: Run successively five simple apps that carry out one action each, such as using database records, showing environment variables, or just sleeping for a second.<\/li>\n<li><strong>ORMs<\/strong>: Do different database operations\u2014for example, loading all records with associations, selecting a fragment of a saved JSON object, and updating JSON.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Performance_of_Ruby_frameworks\"><\/span>Performance of Ruby frameworks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>For comparing Ruby frameworks, I chose the ones that are popular enough and quite actively developed: <a href=\"http:\/\/www.ruby-grape.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Grape<\/a>, <a href=\"https:\/\/hanamirb.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Hanami<\/a>, <a href=\"http:\/\/padrinorb.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Padrino<\/a>, <a href=\"http:\/\/rack.github.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">Rack<\/a>, <a href=\"https:\/\/rubyonrails.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Ruby on Rails<\/a>, and <a href=\"http:\/\/sinatrarb.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Sinatra<\/a>. If you have been following <a href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-sinatra-padrino-goliath-and-ruby-on-rails\/\">my series<\/a> of benchmarks, you might have noticed the absence of Goliath on the list. Sadly, it has been more than two years since its latest release, so I did not include the framework into the tests. For all Rack-based frameworks, Puma was used as an application server.<\/p>\n<p><strong>Benchmarking tool.<\/strong> I began my study from selecting a testing tool, and the search was not in vain\u2014I found <a href=\"https:\/\/github.com\/cmpxchg16\/gobench\" target=\"_blank\" rel=\"noopener noreferrer\">GoBench<\/a>. Really, I liked this tool better than ApacheBench, which hasn&#8217;t been updated for <a href=\"https:\/\/svn.apache.org\/repos\/asf\/httpd\/httpd\/trunk\/support\/ab.c\" target=\"_blank\" rel=\"noopener noreferrer\">10 years<\/a>. <a href=\"https:\/\/github.com\/wg\/wrk\" target=\"_blank\" rel=\"noopener noreferrer\">Wrk<\/a> is also good for local testing. There are <a href=\"https:\/\/gist.github.com\/denji\/8333630\" target=\"_blank\" rel=\"noopener noreferrer\">more benchmarking tools<\/a> available, which even allow you to create a cluster.<\/p>\n<p>To get started with GoBench, I ran the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">gobench -t 10 -u http:\/\/127.0.0.1<\/code> command and set the concurrency level to 100 (the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">-c<\/code> parameter).<\/p>\n<p><strong>Testing samples.<\/strong> In addition, I prepared a number of <a href=\"https:\/\/github.com\/melnikaite\/benchmarks\" target=\"_blank\" rel=\"noopener noreferrer\">\u201cHello, World!\u201d web applications<\/a> and used them to measure the number of HTTP requests that the technologies under comparison could serve per second.<\/p>\n<p><strong>Performance results.<\/strong> As you might expect, Rack and Sinatra demonstrated the best results.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-banchmark-ruby-rack-sinatra-rails-grape-padrino-hanami-v148.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-banchmark-ruby-rack-sinatra-rails-grape-padrino-hanami-v148.png\" alt=\"performance-banchmark-ruby-rack-sinatra-rails-grape-padrino-hanami-v148\" width=\"636\" class=\"aligncenter size-full wp-image-44313\" \/><\/a><\/p>\n<p>A simple, single-thread Ruby server was a bit faster than Rails 5 in API mode, while a modern Rails killer\u2014Hanami\u2014got just a bit better results. In my <a href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-sinatra-padrino-goliath-and-ruby-on-rails\/\">previous benchmark<\/a>, Sinatra was three times faster than Rails, and now it is seven times faster. Good progress, Sinatra!<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Performance_of_Ruby_template_engines\"><\/span>Performance of Ruby template engines<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The list of the tested template engines includes <a href=\"https:\/\/ruby-doc.org\/stdlib-3.1.1\/libdoc\/erb\/rdoc\/ERB.html\" target=\"_blank\" rel=\"noopener noreferrer\">ERB<\/a>, <a href=\"http:\/\/www.kuwata-lab.com\/erubis\/\" target=\"_blank\" rel=\"noopener noreferrer\">Erubis<\/a>, <a href=\"https:\/\/haml.info\/\" target=\"_blank\" rel=\"noopener noreferrer\">Haml<\/a>, <a href=\"https:\/\/shopify.github.io\/liquid\/\" target=\"_blank\" rel=\"noopener noreferrer\">Liquid<\/a>, <a href=\"http:\/\/mustache.github.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">Mustache<\/a>, and <a href=\"http:\/\/slim-lang.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Slim<\/a>. Here is the <a href=\"https:\/\/github.com\/melnikaite\/benchmarks\/tree\/master\/template_engines\" target=\"_blank\" rel=\"noopener noreferrer\">Ruby script<\/a> I used to measure their performance\u2014the number of templates that can be compiled per second. The image below sums up the results of testing the template engines speed.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-testing-ruby-template-engines.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-testing-ruby-template-engines.png\" alt=\"performance-testing-ruby-template-engines\" width=\"584\" height=\"294\" class=\"aligncenter size-full wp-image-44314\" \/><\/a><\/p>\n<p>Erubis had the best performance among the tested solutions. Slim, as always, was the most compact, and it was also faster than ERB.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Performance_of_Rack_application_servers\"><\/span>Performance of Rack application servers<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Among the Rack application servers included in the benchmark are <a href=\"https:\/\/www.phusionpassenger.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Phusion Passenger<\/a>, <a href=\"https:\/\/puma.io\/\" target=\"_blank\" rel=\"noopener noreferrer\">Puma<\/a>, <a href=\"https:\/\/github.com\/kazeburo\/rhebok\" target=\"_blank\" rel=\"noopener noreferrer\">Rhebok<\/a>, <a href=\"http:\/\/code.macournoyer.com\/thin\/\" target=\"_blank\" rel=\"noopener noreferrer\">Thin<\/a>, and <a href=\"https:\/\/yhbt.net\/unicorn\/\" target=\"_blank\" rel=\"noopener noreferrer\">Unicorn<\/a>. Similar to the frameworks, we measured the number of HTTP requests served per second when each of the servers was used. You can find the source code of the tests in <a href=\"https:\/\/github.com\/melnikaite\/app-server-arena\" target=\"_blank\" rel=\"noopener noreferrer\">this GitHub repo<\/a>.<\/p>\n<p>Five sample applications perform the following <a href=\"https:\/\/github.com\/melnikaite\/app-server-arena\/blob\/master\/app.rb\" target=\"_blank\" rel=\"noopener noreferrer\">tasks<\/a>:<\/p>\n<ul>\n<li><code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">active_record<\/code> shows a list of users from database records.<\/li>\n<li><code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">pi<\/code> calculates the pi number.<\/li>\n<li><code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">server<\/code> lists environment variables.<\/li>\n<li><code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">sleep<\/code> waits one second before responding.<\/li>\n<li><code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">random<\/code> selects which application to start: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">server<\/code>, <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">sleep<\/code>, or <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">pi<\/code>.<\/li>\n<\/ul>\n<p>As you can see in the image below, the fastest Rack application server was Passenger, and Rhebok came really close to it.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-rack-app-servers-results.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-rack-app-servers-results.png\" alt=\"performance-rack-app-servers-results\" width=\"500\" class=\"aligncenter size-full wp-image-44315\" \/><\/a><\/p>\n<p>Puma, which was recently made the default server in Rails, won just one test. Compared to my <a href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-sinatra-padrino-goliath-and-ruby-on-rails\/\">previous benchmark<\/a>, Unicorn has done a good job and now demonstrates results very similar to Thin.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Performance_of_ORMs\"><\/span>Performance of ORMs<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In this part of the benchmark, we focused on ORMs and tested how much time <a href=\"https:\/\/github.com\/rails\/rails\/tree\/master\/activerecord\" target=\"_blank\" rel=\"noopener noreferrer\">Active Record<\/a>, <a href=\"http:\/\/sequel.jeremyevans.net\/\" target=\"_blank\" rel=\"noopener noreferrer\">Sequel<\/a>, and <a href=\"https:\/\/docs.mongodb.com\/mongoid\/master\/#ruby-mongoid-tutorial\" target=\"_blank\" rel=\"noopener noreferrer\">Mongoid<\/a> needed to process a given request.<\/p>\n<p>Seven years ago, Jeremy Evans created an amazing benchmarking tool, <a href=\"https:\/\/github.com\/jeremyevans\/simple_orm_benchmark\" target=\"_blank\" rel=\"noopener noreferrer\">simple_orm_benchmark<\/a>. Our team has updated it and tested Active Record and Sequel with MySQL, PostgreSQL, and SQLite, as well as Mongoid with MongoDB. The <a href=\"https:\/\/github.com\/melnikaite\/simple_orm_benchmark\" target=\"_blank\" rel=\"noopener noreferrer\">six new tests<\/a> added to the existing 34 are related to the feature common for all the modern databases\u2014the support of JSON types.<\/p>\n<p>The versions used in this benchmark include MySQL 5.7.15, PostgreSQL 9.5.4, SQLite 3.14.2, MongoDB 3.2.9, Active Record 5, Sequel 4.38, Mongoid 6, and Ruby 2.3.1.<\/p>\n<p>In the diagram below, you will find the most interesting results of the tests (fewer seconds means better performance). Red-colored rows in the images represent measurements with transactions, while blue-colored ones represent those without transactions. You can find all the performance results for the Ruby ORMs in <a href=\"https:\/\/gist.github.com\/melnikaite\/5cb0638255b3db02c3109391cb156df0\" target=\"_blank\" rel=\"noopener noreferrer\">this CSV file<\/a>.<\/p>\n<p>Pseudocode for the test: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Party.where(id: id).update(:stuff=>{:pumpkin=>2, :candy=>1})<\/code><\/p>\n<p>The diagram below indicates the time needed to perform the test with updating a JSON field.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-testing-active-record-sequel-mongoid.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-testing-active-record-sequel-mongoid.png\" alt=\"performance-testing-active-record-sequel-mongoid\" width=\"575\" height=\"371\" class=\"aligncenter size-full wp-image-44316\" \/><\/a><\/p>\n<p>Pseudocode for the test: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Party.where(id: id).update_all([\"stuff = JSON_SET(stuff, '$.pumpkin', ?)\", '2'])<\/code><\/p>\n<p>The diagram below illustrates the time needed to perform the test with updating a record by a JSON fragment.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-ruby-frameworks-orm.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-ruby-frameworks-orm.png\" alt=\"performance-ruby-frameworks-orm\" width=\"575\" height=\"371\" class=\"aligncenter size-full wp-image-44317\" \/><\/a><\/p>\n<p>Pseudocode for the test: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Party.find_by(:id=>id)<\/code><\/p>\n<p>The diagram below demonstrates the time needed to perform the test with selecting records by a specified attribute.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-of-ruby-frameworks-orm-tests.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-of-ruby-frameworks-orm-tests.png\" alt=\"performance-of-ruby-frameworks-orm-tests\" width=\"575\" height=\"371\" class=\"aligncenter size-full wp-image-44318\" \/><\/a><\/p>\n<p>Pseudocode for the test: <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">Party.find_by(\"stuff->>'$.pumpkin' = ?\", '1')<\/code><\/p>\n<p>The diagram below illustrates the time needed to perform the test with selecting records by a JSON fragment.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/orms-performance-active-record-sequel-mongoid.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/orms-performance-active-record-sequel-mongoid.png\" alt=\"orms-performance-active-record-sequel-mongoid\" width=\"575\" height=\"371\" class=\"aligncenter size-full wp-image-44319\" \/><\/a><\/p>\n<p>Despite the fact that Active Record announced the support of JSON types, it is not quite true. In reality, the support only means creating a new JSON object painlessly and getting it back from the database. If you want to update the object in the database, it will override the whole object. To update a part of the object or select the object using a part of it, you have to use raw SQL, which is different for every database.<\/p>\n<p>Moreover, for having the support of JSON fields in SQLite, you should compile SQLite with the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">json1<\/code> module <a href=\"https:\/\/gist.github.com\/melnikaite\/57f19144b07f92e636a917b04fda5dd5\" target=\"_blank\" rel=\"noopener noreferrer\">enabled<\/a> via a SQL query. Alternatively, if you do not need Active Record, you can simply use the <a href=\"https:\/\/github.com\/copiousfreetime\/amalgalite\" target=\"_blank\" rel=\"noopener noreferrer\">Amalgalite<\/a> gem, because the <code style=\"color: #222222; background-color: #e6e6e6; padding: 1px 2px;\">activerecord-amalgalite-adapter<\/code> gem is obsolete.<\/p>\n<style type=\"text\/css\">\n.myTable { background-color:white;border-collapse:collapse; } \n.myTable th { background-color:#E0E0E0;color:black;width:25%; } \n.myTable td, .myTable th { padding:5px;border:1px solid #989898; }\n<\/style>\n<p><center><\/p>\n<table class=\"myTable\" width=\"90%\">\n<thead>\n<tr>\n<th><center>Operations<\/center><\/th>\n<th><center>Mongoid<\/center><\/th>\n<th><center>Active Record<\/center><\/th>\n<th><center>Sequel<\/center><\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong><small>Inserting JSON<\/small><\/strong><\/td>\n<td><small>Yes<\/small><\/td>\n<td><small>Yes<\/small><\/td>\n<td><small>Yes<\/small><\/td>\n<\/tr>\n<tr>\n<td><strong><small>Reading JSON<\/small><\/strong><\/td>\n<td><small>Yes<\/small><\/td>\n<td><small>Yes<\/small><\/td>\n<td><small>Yes<\/small><\/td>\n<\/tr>\n<tr>\n<td><strong><small>Supporting JSON types in models<\/small><\/strong><\/td>\n<td><small>Yes<\/small><\/td>\n<td><small>Yes (except SQLite)<\/small><\/td>\n<td><small>Yes (only for PostgreSQL)<\/small><\/td>\n<\/tr>\n<tr>\n<td><strong><small>Updating a JSON object partially<\/small><\/strong><\/td>\n<td><small>Yes<\/small><\/td>\n<td><small>Raw SQL<\/small><\/td>\n<td><small>Raw SQL<\/small><\/td>\n<\/tr>\n<tr>\n<td><strong><small>Searching by JSON fragments<\/small><\/strong><\/td>\n<td><small>Yes<\/small><\/td>\n<td><small>Raw SQL<\/small><\/td>\n<td><small>Raw SQL<\/small><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/center><\/p>\n<p>In general, Sequel was faster than Active Record and Mongoid, though the latter is more intuitively clear, and you need less time to implement the tests compared to Active Record and Sequel.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Performance_of_other_languages_and_frameworks\"><\/span>Performance of other languages and frameworks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>In the final part of the benchmark, we compared Ruby frameworks with a number of other languages and frameworks, such as Crystal, Python, Elixir, Go, Java, Express, Meteor, Django, Phoenix, and Spring.<\/p>\n<p><strong>Test environment.<\/strong> Similar to the evaluation of Ruby frameworks described earlier, GoBench was used as a testing tool, and the behavior of the frameworks was maximally close to the default. You can check out these <a href=\"https:\/\/github.com\/melnikaite\/benchmarks\" target=\"_blank\" rel=\"noopener noreferrer\">\u201cHello, World\u201d web apps<\/a> for the testing samples.<\/p>\n<p><strong>Performance results<\/strong>. Below follows the surprising part of this benchmark.<\/p>\n<p><a href=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-benchmark-ruby-frameworks-results-v666.png\"><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/performance-benchmark-ruby-frameworks-results-v666.png\" alt=\"performance-benchmark-ruby-frameworks-results-v666\" width=\"500\" class=\"aligncenter size-full wp-image-44320\" \/><\/a><\/p>\n<p>You can see that the Go language and a Go framework Iris are absolute winners that managed to handle about 60,000 requests per second. Their results are followed by Ring (Clojure), Scalatra (Scala), and Warp (Haskell). Elixir, Scala, and Crystal (a Ruby-like language inspired by the speed of C) share the third place. Then follow Spring (Java), Hyper (Rust), C, Phoenix (Elixir), Ur\/Web, Dart, and Node.js.<\/p>\n<p>Unfortunately, the Ruby frameworks\u2014Rack, Sinatra, Padrino, Grape, Rails, and Hanami\u2014have the poorest results together with Express (Node.js), Stream (Dart), Haskell, Rust, PHP, Java, Python, Meteor (Node.js), and Django (Python).<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Conclusion\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The frameworks and tools in this benchmark were configured as close as possible to their default behavior, which essentially allowed to create equal conditions for all of them.<\/p>\n<p>Even though Rack, Sinatra, Padrino, Grape, Rails, and Hanami demonstrated relatively low performance compared to other frameworks in our \u201cHello, World\u201d benchmark, it does not mean that Ruby is the wrong choice. In real life\u2014when you scale your app horizontally, use multiple workers and threads, and know all the advantages of a framework\u2014the results may be very different. It is also true that your preferences and needs may change at some point. For more details, check out the <a href=\"https:\/\/www.altoros.com\/research-papers\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms\/\">full performance benchmark<\/a>.<\/p>\n<p>However, first of all, you should enjoy your language. If you don\u2019t, just try something else.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Further_reading\"><\/span>Further reading<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li><a href=\"https:\/\/www.altoros.com\/research-papers\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms\/\">Performance Comparison of Ruby Frameworks, App Servers, Template Engines, and ORMs (2016)<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-sinatra-padrino-goliath-and-ruby-on-rails\/\">Performance Comparison of Ruby Frameworks: Sinatra, Padrino, Goliath, and Ruby on Rails<\/a><\/li>\n<\/ul>\n<hr \/>\n<p><center><small>This post was written by Eugene Melnikov with assistance from <a href=\"https:\/\/www.altoros.com\/blog\/author\/viktoryia-fedzkovich\/\">Victoria Fedzkovich<\/a> and <a href=\"https:\/\/www.altoros.com\/blog\/author\/alex\/\">Alex Khizhniak<\/a>.<\/small><\/center><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Ruby ecosystem is constantly evolving. There have been many changes in the engineering world since our comparison of Ruby frameworks in 2014. During the two years, we received a few requests from fellow engineers asking for an updated benchmark. So, here is the 2016 edition with more things tested.<\/p>\n<p>&nbsp;<\/p>\n<p>What&#8217;s [&#8230;]<\/p>\n","protected":false},"author":62,"featured_media":44337,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[214],"tags":[894,895],"class_list":["post-44311","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-benchmarking","tag-research-and-development"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Performance Comparison of Ruby Frameworks 2016 | Altoros<\/title>\n<meta name=\"description\" content=\"This blog post shares some of the performance results demonstrated by a variety of Ruby frameworks, template engines, app servers, and ORM tools.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Performance Comparison of Ruby Frameworks 2016 | Altoros\" \/>\n<meta property=\"og:description\" content=\"The Ruby ecosystem is constantly evolving. There have been many changes in the engineering world since our comparison of Ruby frameworks in 2014. During the two years, we received a few requests from fellow engineers asking for an updated benchmark. So, here is the 2016 edition with more things tested. &nbsp; What&#8217;s [...]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/\" \/>\n<meta property=\"og:site_name\" content=\"Altoros\" \/>\n<meta property=\"article:published_time\" content=\"2016-11-28T19:56:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-06-18T14:24:17+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif\" \/>\n\t<meta property=\"og:image:width\" content=\"636\" \/>\n\t<meta property=\"og:image:height\" content=\"392\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/gif\" \/>\n<meta name=\"author\" content=\"Eugene Melnikov\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Eugene Melnikov\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/\",\"name\":\"Performance Comparison of Ruby Frameworks 2016 | Altoros\",\"isPartOf\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif\",\"datePublished\":\"2016-11-28T19:56:31+00:00\",\"dateModified\":\"2019-06-18T14:24:17+00:00\",\"author\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/2347aafc28e3658aea99b1b6671f7b70\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#primaryimage\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif\",\"width\":636,\"height\":392},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.altoros.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Performance Comparison of Ruby Frameworks 2016\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\",\"url\":\"https:\/\/www.altoros.com\/blog\/\",\"name\":\"Altoros\",\"description\":\"Insight\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.altoros.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/2347aafc28e3658aea99b1b6671f7b70\",\"name\":\"Eugene Melnikov\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/03\/melnikov-96x96.jpg\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/03\/melnikov-96x96.jpg\",\"caption\":\"Eugene Melnikov\"},\"description\":\"Eugene Melnikov is a senior software engineer at Altoros. He mainly specializes in Ruby and Ruby-based frameworks, as well as in JavaScript development, including Node.js, jQuery, and AngularJS. Working at Altoros, Eugene has also designed and implemented a variety of SQL and NoSQL database solutions. He recently became engaged in creating data-driven software for IoT applications. Check out Eugene's GitHub profile.\",\"url\":\"https:\/\/www.altoros.com\/blog\/author\/eugene-melnikov\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Performance Comparison of Ruby Frameworks 2016 | Altoros","description":"This blog post shares some of the performance results demonstrated by a variety of Ruby frameworks, template engines, app servers, and ORM tools.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/","og_locale":"en_US","og_type":"article","og_title":"Performance Comparison of Ruby Frameworks 2016 | Altoros","og_description":"The Ruby ecosystem is constantly evolving. There have been many changes in the engineering world since our comparison of Ruby frameworks in 2014. During the two years, we received a few requests from fellow engineers asking for an updated benchmark. So, here is the 2016 edition with more things tested. &nbsp; What&#8217;s [...]","og_url":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/","og_site_name":"Altoros","article_published_time":"2016-11-28T19:56:31+00:00","article_modified_time":"2019-06-18T14:24:17+00:00","og_image":[{"width":636,"height":392,"url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif","type":"image\/gif"}],"author":"Eugene Melnikov","twitter_misc":{"Written by":"Eugene Melnikov","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/","url":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/","name":"Performance Comparison of Ruby Frameworks 2016 | Altoros","isPartOf":{"@id":"https:\/\/www.altoros.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#primaryimage"},"image":{"@id":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#primaryimage"},"thumbnailUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif","datePublished":"2016-11-28T19:56:31+00:00","dateModified":"2019-06-18T14:24:17+00:00","author":{"@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/2347aafc28e3658aea99b1b6671f7b70"},"breadcrumb":{"@id":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#primaryimage","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2016\/11\/performance-benchmark-ruby-frameworks-template-engines-orm-tools.gif","width":636,"height":392},{"@type":"BreadcrumbList","@id":"https:\/\/www.altoros.com\/blog\/performance-comparison-of-ruby-frameworks-app-servers-template-engines-and-orms-2016\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.altoros.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Performance Comparison of Ruby Frameworks 2016"}]},{"@type":"WebSite","@id":"https:\/\/www.altoros.com\/blog\/#website","url":"https:\/\/www.altoros.com\/blog\/","name":"Altoros","description":"Insight","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.altoros.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/2347aafc28e3658aea99b1b6671f7b70","name":"Eugene Melnikov","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/03\/melnikov-96x96.jpg","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2020\/03\/melnikov-96x96.jpg","caption":"Eugene Melnikov"},"description":"Eugene Melnikov is a senior software engineer at Altoros. He mainly specializes in Ruby and Ruby-based frameworks, as well as in JavaScript development, including Node.js, jQuery, and AngularJS. Working at Altoros, Eugene has also designed and implemented a variety of SQL and NoSQL database solutions. He recently became engaged in creating data-driven software for IoT applications. Check out Eugene's GitHub profile.","url":"https:\/\/www.altoros.com\/blog\/author\/eugene-melnikov\/"}]}},"_links":{"self":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/44311","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/users\/62"}],"replies":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/comments?post=44311"}],"version-history":[{"count":18,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/44311\/revisions"}],"predecessor-version":[{"id":44341,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/44311\/revisions\/44341"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media\/44337"}],"wp:attachment":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media?parent=44311"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/categories?post=44311"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/tags?post=44311"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}