From cb0b8573be591aa2e812ce564e94f7e80ce32d74 Mon Sep 17 00:00:00 2001 From: Robert Mosolgo Date: Fri, 3 Feb 2023 11:40:06 -0500 Subject: [PATCH] Add a benchmark for analysis --- Rakefile | 6 ++++ benchmark/run.rb | 90 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 13 deletions(-) diff --git a/Rakefile b/Rakefile index f00b012a84..3617dec0a3 100644 --- a/Rakefile +++ b/Rakefile @@ -134,6 +134,12 @@ namespace :bench do prepare_benchmark GraphQLBenchmark.profile_large_introspection end + + desc "Run analysis on a big query" + task :profile_large_analysis do + prepare_benchmark + GraphQLBenchmark.profile_large_analysis + end end namespace :test do diff --git a/benchmark/run.rb b/benchmark/run.rb index ca47e171cd..5cf8698d97 100644 --- a/benchmark/run.rb +++ b/benchmark/run.rb @@ -72,25 +72,45 @@ def self.profile StackProf::Report.new(result).print_text end - def self.profile_large_introspection - schema = Class.new(GraphQL::Schema) do - query_t = Class.new(GraphQL::Schema::Object) do - graphql_name("Query") - 100.times do |n| - obj_t = Class.new(GraphQL::Schema::Object) do - graphql_name("Object#{n}") - 20.times do |n2| - field :"field#{n2}", String do - argument :arg, String - end + SILLY_LARGE_SCHEMA = Class.new(GraphQL::Schema) do + query_t = Class.new(GraphQL::Schema::Object) do + graphql_name("Query") + int_ts = 5.times.map do |i| + int_t = Module.new do + include GraphQL::Schema::Interface + graphql_name "Interface#{i}" + 5.times do |n2| + field :"field#{n2}", String do + argument :arg, String + end + end + end + field :"int_field_#{i}", int_t + int_t + end + + 100.times do |n| + obj_t = Class.new(GraphQL::Schema::Object) do + graphql_name("Object#{n}") + implements(*int_ts) + 20.times do |n2| + field :"field#{n2}", String do + argument :arg, String end + end - field :"rootfield#{n}", obj_t + field :self_field, self + field :int_0_field, int_ts[0] end + + field :"rootfield#{n}", obj_t end - query(query_t) end + query(query_t) + end + def self.profile_large_introspection + schema = SILLY_LARGE_SCHEMA Benchmark.ips do |x| x.report("Run large introspection") { schema.to_json @@ -109,6 +129,50 @@ def self.profile_large_introspection report.pretty_print end + def self.profile_large_analysis + query_str = "query {\n".dup + fragments = [] + 5.times do |n| + query_str << " intField#{n} { " + 20.times do |o| + query_str << "...Obj#{o}Fields " + end + query_str << "}\n" + end + query_str << "}" + + 20.times do |o| + query_str << "fragment Obj#{o}Fields on Object#{o} { " + 20.times do |f| + query_str << " field#{f}(arg: \"a\")\n" + end + query_str << " selfField { selfField { selfField { __typename } } }\n" + query_str << " int0Field { ...Int0Fields }" + query_str << "}\n" + end + query_str << "fragment Int0Fields on Interface0 { __typename }" + query = GraphQL::Query.new(SILLY_LARGE_SCHEMA, query_str) + analyzers = [GraphQL::Analysis::AST::FieldUsage] + multiplex_analyzers = [] + Benchmark.ips do |x| + x.report("Running introspection") { + GraphQL::Analysis::AST.analyze_query(query, analyzers) + } + end + + result = StackProf.run(mode: :wall, interval: 1) do + GraphQL::Analysis::AST.analyze_query(query, analyzers) + end + + StackProf::Report.new(result).print_text + + report = MemoryProfiler.report do + GraphQL::Analysis::AST.analyze_query(query, analyzers) + end + puts "\n\n" + report.pretty_print + end + # Adapted from https://github.com/rmosolgo/graphql-ruby/issues/861 def self.profile_large_result schema = ProfileLargeResult::Schema