[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