Skip to content

Instantly share code, notes, and snippets.

@palkan
Created February 13, 2020 13:21
Show Gist options
  • Save palkan/f52e62aa5288dfbc27e47ae1a04c3eef to your computer and use it in GitHub Desktop.
Save palkan/f52e62aa5288dfbc27e47ae1a04c3eef to your computer and use it in GitHub Desktop.
[GraphQL] @pp profiling
# frozen_string_literal: true
module Directives
class Pp < GraphQL::Schema::Directive
class Profiler < Types::BaseEnum
graphql_name "PpProfiler"
description "Available profilers for @pp directive"
value :mem
value :stack
value :ruby
end
description "Profile the field resolving using one of the available profilers"
locations(
GraphQL::Schema::Directive::FIELD
)
argument :type, Profiler,
required: true,
description: "Profiler type"
class << self
def resolve(_object, arguments, context)
field_name = context.query.selected_operation.selections.first.name
msg = send(arguments[:type], field_name) do
yield
end
$stdout.puts "\e[34m[PP] #{msg.join}\e[0m"
context.namespace(:interpreter)[:runtime].write_in_response(["pp"], msg)
end
private
def mem(field)
require "memory_profiler"
report_path = Rails.root.join("tmp/#{field}_memory.txt")
MemoryProfiler.report { yield }.yield_self do |r|
r.pretty_print(to_file: report_path)
end
["Memory profile for #{field} is stored at: #{relative_path(report_path)}"]
end
def stack(field)
require "stackprof"
report_path = Rails.root.join("tmp/#{field}_stackprof.dump")
StackProf.run(mode: :cpu, raw: true, out: report_path) do
yield
end
[
"StackProf dump is stored at: #{relative_path(report_path)}\n",
"You can generate a JSON report by running the following command:\n\n",
" be stackprof --json #{relative_path(report_path)} > tmp/#{field}_stackprof.json\n\n",
"Go to speedscope.app and analyze it!",
]
end
def ruby(field)
require "ruby-prof"
report_path = Rails.root.join("tmp/#{field}_rubyprof.txt")
result = RubyProf.profile do
yield
end
File.open(report_path, "w") do |f|
RubyProf::FlatPrinter.new(result).print(f, min_percent: 1)
end
["RubyProf report for #{field} is stored at: #{relative_path(report_path)}"]
end
def relative_path(path)
Pathname.new(path).relative_path_from(Rails.root)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment