{"id":10255,"date":"2019-03-25T18:32:48","date_gmt":"2019-03-25T18:32:48","guid":{"rendered":"https:\/\/blog.jetbrains.com\/ruby\/?p=8705"},"modified":"2021-11-22T13:23:37","modified_gmt":"2021-11-22T12:23:37","slug":"rubymine-profiler","status":"publish","type":"ruby","link":"https:\/\/blog.jetbrains.com\/fr\/ruby\/2019\/03\/rubymine-profiler","title":{"rendered":"Profile Ruby &#038; Rails Apps With rbspy in RubyMine"},"content":{"rendered":"<p><a href=\"https:\/\/www.jetbrains.com\/ruby\/nextversion\/\" target=\"_blank\" rel=\"noopener\"><strong>RubyMine 2019.1<\/strong><\/a> adds support for <a href=\"https:\/\/github.com\/rbspy\/rbspy\" target=\"_blank\" rel=\"noopener\">rbspy<\/a> \u2013 a great sampling profiler for Ruby (many thanks to&nbsp;<a href=\"https:\/\/github.com\/jvns\" target=\"_blank\" rel=\"noopener\">@jvns<\/a>!). This post will help you start profiling your Ruby\/Rails apps with RubyMine in 5 minutes. Here are the exact steps:<\/p>\n<ul>\n<li><a href=\"https:\/\/blog.jetbrains.com\/ruby\/2019\/03\/rubymine-profiler\/#scenario\">Identify the scenario to be analyzed<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/ruby\/2019\/03\/rubymine-profiler\/#configuration\">Create a profiler configuration<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/ruby\/2019\/03\/rubymine-profiler\/#run_profiler\">Run the program with the profiler attached<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/ruby\/2019\/03\/rubymine-profiler\/#analyze_data\">Analyze the profiled data<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/ruby\/2019\/03\/rubymine-profiler\/#export_import_data\">Export\/Import the profiled data<\/a><\/li>\n<li><a href=\"https:\/\/blog.jetbrains.com\/ruby\/2019\/03\/rubymine-profiler\/#other\">Other options<\/a><\/li>\n<\/ul>\n<p><strong>First things first:<\/strong> make sure you have rbspy installed. If it\u2019s not, <a href=\"https:\/\/rbspy.github.io\/installing\/\" target=\"_blank\" rel=\"noopener\">see this guide to install it<\/a> for Ma\u0441, Linux, and Windows. Now you\u2019re set. Run <a href=\"https:\/\/www.jetbrains.com\/ruby\/nextversion\/\" target=\"_blank\" rel=\"noopener\">RubyMine 2019.1<\/a> and follow these steps to start profiling:<!--more--><\/p>\n<h3 id=\"scenario\">Identify the scenario to be analyzed<\/h3>\n<p>For demonstration purposes, we\u2019ve added an inefficient piece of code to our toy Rails blog*. The newly added feature checks whether a single author has different articles with the same title. However, after some testing it turned out that some pages take several seconds to load, which is pretty slow. It\u2019s time to apply our new profiler.<\/p>\n<h3 id=\"configuration\">Create a profiler configuration<\/h3>\n<p>Go to <em>Preferences | Build, Execution, Deployment | Ruby Profiler <\/em>to add your rbspy profiler configuration:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-add_rbspy_configuration.png.png\" alt=\"\" width=\"800\"><\/p>\n<p>If the configuration is grayed out after your add it, then double-check your rbspy installation.<\/p>\n<p>Note that with rbspy, you can create several profiler configurations if you want different profiler rates. The more <em>samples per second<\/em> you set, the more precision and, alas, overhead, you get, and vice versa:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-add_another_configuration.png.png\" alt=\"\" width=\"800\"><\/p>\n<h3 id=\"run_profiler\">Run the program with the profiler attached<\/h3>\n<p>This can be done with <a href=\"https:\/\/blog.jetbrains.com\/ruby\/2017\/06\/navigate-in-rubymine-like-a-pro\/#go-to-anything\" target=\"_blank\" rel=\"noopener\"><em>Navigate to<\/em><\/a> action, or by clicking the <em>Run with Profiler <\/em>icon on the <em>Run toolbar<\/em>:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-run_profiler.png\" alt=\"\" width=\"800\"><\/p>\n<p>The application will run and the profiler will start collecting data. We want to find the source of the slow page generation which bothers us, so we will reproduce the problem (we\u2019ll open the slow page in the browser) while the profiler is running. After reproducing the problem, we\u2019ll click the <em>Stop <\/em>icon so that the profiler stops collecting data, and navigates us to the profiling tool window.<\/p>\n<p>Here&#8217;s a 30-second gif that depicts these steps:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-start_profiler.png\" alt=\"\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-start_profiler.gif\"><\/p>\n<h3 id=\"analyze_data\">Analyze the profiled data<\/h3>\n<p>By surfing through different threads and their flame charts, we will eventually encounter a method `has_duplicate_titles` that takes 754 samples to complete, and, consequently, slows our application down. If we look it up in the method list, we will find out why: the current algorithm for finding duplicate titles is inefficient, as it requires loading from the database too often. But fixing this issue is out of scope of this blog post :)<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-analyze_profiler_data.png\" alt=\"\" width=\"800\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-analyze_profiler_data.gif\"><\/p>\n<p>Note that you can invoke <em>Jump to Source <\/em>from the context menu to quickly navigate to the definition of the desired method:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-jump_to_source.png\" alt=\"\" width=\"800\"><\/p>\n<h3 id=\"export_import_data\">Export\/Import the profiled data<\/h3>\n<p>Exporting\/importing allows you to send&nbsp;the data&nbsp;to your colleagues or analyze it later (<em>Run | Export \/ Import Profiler Results):<\/em><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-import_profiler_results.png\" alt=\"\" width=\"800\"><\/p>\n<h3 id=\"other\">Other options<\/h3>\n<p>Finally, you can&nbsp;attach to a running process with the profiler on Linux and MacOS (For Windows, see <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/RUBY-23795\" target=\"_blank\" rel=\"noopener\">RUBY-23795<\/a>):<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-attach_profiler_upd.png\" alt=\"\" width=\"800\"><\/p>\n<p>And profile tests:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2019\/03\/ruby-profile_tests_upd.png\" alt=\"\" width=\"800\"><\/p>\n<p><em>This profiler is one of the major features in RubyMine 2019.1 We\u2019ll highly appreciate it if you try it and let us know about any issues in the comments section. You can also <\/em><a href=\"https:\/\/youtrack.jetbrains.com\/issues\/ruby\" target=\"_blank\" rel=\"noopener\"><em>submit an issue in YouTrack<\/em><\/a><em>. Thank you!<\/em><\/p>\n<p style=\"text-align: center;\"><a class=\"jb-download-button\" href=\"https:\/\/www.jetbrains.com\/ruby\/nextversion\/\" target=\"_blank\" rel=\"noopener\">Download RubyMine 2019.1 BETA<\/a><\/p>\n<p>As usual, check out our <a href=\"https:\/\/confluence.jetbrains.com\/display\/RUBYDEV\/RubyMine+2019.1\" target=\"_blank\" rel=\"noopener\">release notes<\/a> for the full list of improvements inside this build.<\/p>\n<p>*Check out the <a href=\"https:\/\/rbspy.github.io\/using-rbspy\/\" target=\"_blank\" rel=\"noopener\">rbspy documentation<\/a> to learn more about profiling Ruby\/Rails apps.<br \/>\n*Thanks to the authors of&nbsp;<a href=\"https:\/\/github.com\/udemyrailscourse\/alpha-blog\" target=\"_blank\" rel=\"noopener\">Alpha Blog which our sample blog is based on<\/a>.<\/p>\n<p>Cheers,<br \/>\nYour RubyMine Team<\/p>\n","protected":false},"author":574,"featured_media":0,"comment_status":"open","ping_status":"open","template":"","categories":[826,808,1264,2347],"tags":[744,600,743,1123],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/ruby\/10255"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/ruby"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/types\/ruby"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/users\/574"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/comments?post=10255"}],"version-history":[{"count":1,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/ruby\/10255\/revisions"}],"predecessor-version":[{"id":204179,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/ruby\/10255\/revisions\/204179"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/media?parent=10255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/categories?post=10255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/tags?post=10255"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/fr\/wp-json\/wp\/v2\/cross-post-tag?post=10255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}