{"id":20836304,"url":"https://github.com/igrigorik/async-rails","last_synced_at":"2025-04-05T12:07:07.640Z","repository":{"id":949816,"uuid":"729930","full_name":"igrigorik/async-rails","owner":"igrigorik","description":"async Rails 3 stack demo","archived":false,"fork":false,"pushed_at":"2023-03-27T22:32:52.000Z","size":118,"stargazers_count":463,"open_issues_count":4,"forks_count":28,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-29T11:08:44.812Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/igrigorik.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2010-06-20T00:27:50.000Z","updated_at":"2024-12-31T15:48:02.000Z","dependencies_parsed_at":"2022-08-08T08:15:11.315Z","dependency_job_id":"fb41d4e6-c017-45f9-91fe-1e224b1149b7","html_url":"https://github.com/igrigorik/async-rails","commit_stats":{"total_commits":33,"total_committers":6,"mean_commits":5.5,"dds":0.4545454545454546,"last_synced_commit":"0d00f9baee66c0a81e313f8180187e76306848c2"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fasync-rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fasync-rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fasync-rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/igrigorik%2Fasync-rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/igrigorik","download_url":"https://codeload.github.com/igrigorik/async-rails/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247332609,"owners_count":20921853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T00:29:28.579Z","updated_at":"2025-04-05T12:07:07.608Z","avatar_url":"https://github.com/igrigorik.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Async Rails 3.1 stack demo\n\nImportant warning:\n  \n  You should be aware when using fibers with Rails that you can get a stack overflow error if your stack grows  \n  bigger than 4Kb (which is enough for most things though), this got even worse with the 3.1 release in which  \n  you can easily overflow the stack, here is an example [here](https://github.com/schmurfy/assets_crash).\n\nSimple async demo stack with Rails 3.1 + EventMachine and Fibers.\n\n * Hit localhost:3000/widgets to do a 1s async mysql query\n * Hit localhost:3000/widgets/http to make an HTTP call back to /widgets - recursive! :-)\n * Hit localhost:3000/twitter to load a mounted async Sinatra app (reports latests rails 3 tweets)\n\nHowto / example commits:\n\n  * Modify your config.ru to include the Rack::FiberPool middleware: [config.ru](https://github.com/igrigorik/async-rails/commit/72ea38433246cc58cd31e3863f4ed4e0c861ad28#config.ru)\n  * Configure ActiveRecord to use async mysql driver: [Gemfile](https://github.com/igrigorik/async-rails/blob/master/Gemfile#L16), and [database.yml](https://github.com/igrigorik/async-rails/blob/master/config/database.yml#L4)\n  * [Use async HTTP fetching within Rails](http://github.com/igrigorik/async-rails/commit/6307f3f416f21a40304d2f4a07509b923051744b)\n  * [Mount async Sinatra app](http://github.com/igrigorik/async-rails/commit/50c5e4fd6701dfa2b3ecfc697ca53b40f8c57827)\n\nRequirements:\n\n * Ruby 1.9.x\n * Async app server (thin)\n * Rails 3.1\n\nEnvironment setup:\n\n * rvm install 1.9.2\n * rvm gemset create async-rails\n * rvm use 1.9.2@async-rails\n * gem install rails thin\n\nStarting up Rails:\n\n * bundle install\n * bundle exec thin -D start\n\n## Concurrency\n\nab -c 5 -n 10 http://127.0.0.1:3000/widgets/\n\n        Concurrency Level:      5\n        Time taken for tests:   2.740 seconds\n        Complete requests:      10\n\nWe're running on a single reactor, so above is proof that we can execute HTTP+MySQL queries in non-blocking fashion on a single run loop / within single process:\n\n * AB opens 5 concurrent requests (10 total)\n * Each request to /widgets/http opens an async HTTP request to /widgets - aka, we ourselves spawn another 5 requests\n * Because the fiber pool is set to 10, it means we can process all 5 requests within ~1s (each mysql req takes 1s)\n * 10 requests finish in ~2s\n\nSo, keep in mind that the size of 'database pool' is basically your concurrency throttle. In example above, we spawn\n10 requests, which open another 10 internally, so in total we process 20 req's in ~2s on a single thing server. Just as expected.\n\n## Benchmarks\n\nPushing the stack on my MBP (db pool = 250; fiber pool = 250; env = production; thin 1.2.7) results in:\n\n        Concurrency Level:      220\n        Time taken for tests:   10.698 seconds\n        Complete requests:      2000\n        Failed requests:        0\n        Write errors:           0\n        Total transferred:      470235 bytes\n        HTML transferred:       12006 bytes\n        Requests per second:    186.95 [#/sec] (mean)\n        Time per request:       1176.777 [ms] (mean)\n        Time per request:       5.349 [ms] (mean, across all concurrent requests)\n        Transfer rate:          42.93 [Kbytes/sec] received\n\nFor full AB trace see [this gist](http://gist.github.com/503627)\n\nResources:\n\n * [No callbacks, No threads - RailsConf 2010 Presentation](http://www.slideshare.net/igrigorik/no-callbacks-no-threads-railsconf-2010)\n * [Rails performance needs an overhaul](http://www.igvita.com/2010/06/07/rails-performance-needs-an-overhaul/)\n * [Non-blocking ActiveRecord](http://www.igvita.com/2010/04/15/non-blocking-activerecord-rails/)\n * [Untangling evented code with Ruby fibers](http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers/)\n * [Introducing Phat, and Async Rails app](http://www.mikeperham.com/2010/04/03/introducing-phat-an-asynchronous-rails-app/)\n\nOther: \n\n * [Postgres + Async Rails driver](https://github.com/leftbee/em-postgresql-adapter)\n * [Fix: Asset Pipeline + Stack level too deep error](https://github.com/igrigorik/async-rails/wiki/Asset-Pipeline-+-Stack-Level-to-Deep)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrigorik%2Fasync-rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Figrigorik%2Fasync-rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Figrigorik%2Fasync-rails/lists"}