From 45d6a2b3981330f1bb3093b9a9c3eb9f14cc3bb2 Mon Sep 17 00:00:00 2001 From: Sean McGivern Date: Fri, 19 Jan 2018 13:04:30 +0000 Subject: [PATCH] Add bin/profile-url tool and docs --- bin/profile-url | 57 ++++++++++++++++++++++++++++++++++ doc/development/performance.md | 3 +- doc/development/profiling.md | 45 +++++++++++++++++++++------ 3 files changed, 94 insertions(+), 11 deletions(-) create mode 100755 bin/profile-url diff --git a/bin/profile-url b/bin/profile-url new file mode 100755 index 00000000000..d8d09641624 --- /dev/null +++ b/bin/profile-url @@ -0,0 +1,57 @@ +#!/usr/bin/env ruby +require 'optparse' + +options = {} + +opt_parser = OptionParser.new do |opt| + opt.banner = < --sql= [--user=] [--post=] + +Example: + #{__FILE__} /dashboard/issues --output=dashboard-profile.html --sql=dashboard.log --user=root +DOCSTRING + opt.separator '' + opt.separator 'Options:' + + opt.on('-o', '--output=/tmp/profile.html', 'profile output filename') do |output| + options[:profile_output] = output + end + + opt.on('-s', '--sql=/tmp/profile_sql.txt', 'SQL output filename') do |sql| + options[:sql_output] = sql + end + + opt.on('-u', '--user=root', 'User to authenticate as') do |username| + options[:username] = username + end + + opt.on('-p', "--post='user=john&pass=test'", 'Send HTTP POST data') do |post_data| + options[:post_data] = post_data + end +end + +opt_parser.parse! +options[:url] = ARGV[0] + +if options[:url].nil? || + options[:profile_output].nil? || + options[:sql_output].nil? + puts opt_parser + exit +end + +require File.expand_path('../config/environment', File.dirname(__FILE__)) + +result = Gitlab::Profiler.profile(options[:url], + logger: Logger.new(options[:sql_output]), + post_data: options[:post_data], + user: User.find_by_username(options[:username]), + private_token: ENV['PRIVATE_TOKEN']) + +printer = RubyProf::CallStackPrinter.new(result) +file = File.open(options[:profile_output], 'w') +printer.print(file) +file.close diff --git a/doc/development/performance.md b/doc/development/performance.md index e7c5a6ca07a..c4162a05b77 100644 --- a/doc/development/performance.md +++ b/doc/development/performance.md @@ -36,7 +36,8 @@ graphs/dashboards. GitLab provides built-in tools to aid the process of improving performance: -* [Sherlock](profiling.md#sherlock) +* [Profiling](profiling.md) + * [Sherlock](profiling.md#sherlock) * [GitLab Performance Monitoring](../administration/monitoring/performance/index.md) * [Request Profiling](../administration/monitoring/performance/request_profiling.md) * [QueryRecoder](query_recorder.md) for preventing `N+1` regressions diff --git a/doc/development/profiling.md b/doc/development/profiling.md index af79353b721..97c997e0568 100644 --- a/doc/development/profiling.md +++ b/doc/development/profiling.md @@ -4,6 +4,41 @@ To make it easier to track down performance problems GitLab comes with a set of profiling tools, some of these are available by default while others need to be explicitly enabled. +## Profiling a URL + +There is a `Gitlab::Profiler.profile` method, and corresponding +`bin/profile-url` script, that enable profiling a GET or POST request to a +specific URL, either as an anonymous user (the default) or as a specific user. + +When using the script, command-line documentation is available by passing no +arguments. + +When using the method in an interactive console session, any changes to the +application code within that console session will be reflected in the profiler +output. + +For example: + +```ruby +Gitlab::Profiler.profile('/my-user') +# Returns a RubyProf::Profile for the regular operation of this request +class UsersController; def show; sleep 100; end; end +Gitlab::Profiler.profile('/my-user') +# Returns a RubyProf::Profile where 100 seconds is spent in UsersController#show +``` + +Passing a `logger:` keyword argument to `Gitlab::Profiler.profile` will send +ActiveRecord and ActionController log output to that logger. Further options are +documented with the method source. + +[GitLab-Profiler](https://gitlab.com/gitlab-com/gitlab-profiler) is a project +that builds on this to add some additional niceties, such as allowing +configuration with a single Yaml file for multiple URLs, and uploading of the +profile and log output to S3. + +For GitLab.com, you can find the latest results here: + + ## Sherlock Sherlock is a custom profiling tool built into GitLab. Sherlock is _only_ @@ -27,13 +62,3 @@ Bullet will log query problems to both the Rails log as well as the Chrome console. As a follow up to finding `N+1` queries with Bullet, consider writing a [QueryRecoder test](query_recorder.md) to prevent a regression. - -## GitLab Profiler - - -[Gitlab-Profiler](https://gitlab.com/gitlab-com/gitlab-profiler) was built to -help developers understand why specific URLs of their application may be slow -and to provide hard data that can help reduce load times. - -For GitLab.com, you can find the latest results here: -