Description
Describe the bug
I've been working on deploying an upgrade to one of our internal systems, and discovered that using GraphQL::Schema::Visibility
is much slower than the GraphQL::Schema::Warden
plugin that we've been using. According to my benchmark, it's more than 20x slower for a very simple query!
Versions
graphql
version: 2.5.2
rails
(or other framework): N/A
other applicable versions (graphql-batch
, etc): N/A
GraphQL schema
https://gist.github.com/myronmarston/ee6fa2d92d2941b7071459708f7d46d1
(Apologies for the large anonymized schema, but I didn't think I should share our proprietary internal schema and I wasn't able to come up with a smaller schema that reproduced this issue--so I just replaced all the type names and field names to anonymize it.).
GraphQL query
query {
field264(
field265: [ENUM_VALUE1000]
) {
__typename
}
}
Steps to reproduce
Create a ruby script with this code:
require "bundler/inline"
gemfile do
source "https://rubygems.org"
gem "graphql", "2.5.2"
gem "benchmark-ips"
end
require "benchmark/ips"
require "graphql"
require "open-uri"
SCHEMA_STRING = URI("https://gist.githubusercontent.com/myronmarston/ee6fa2d92d2941b7071459708f7d46d1/raw/8b99a4d9723dc99a7a921cf787c8e6b31a8fc6b7/anonymized_schema.graphql").read
class Application
def initialize(using: {})
@schema = ::GraphQL::Schema.from_definition(
SCHEMA_STRING,
default_resolve: self,
using: using
)
end
def call(parent_type, field, object, args, context)
nil
end
def execute_query(query_string)
response = ::GraphQL::Query.new(@schema, query_string, variables: {}).result
unless response.fetch("errors", []).empty?
raise "Query failed: #{response.to_h.inspect}"
end
response
end
end
warden_app = Application.new(using: {
GraphQL::Schema::Warden => {}
})
visibility_app = Application.new(using: {
GraphQL::Schema::Visibility => {preload: true}
})
query = <<~EOS
query {
field264(
field265: [ENUM_VALUE1000]
) {
__typename
}
}
EOS
Benchmark.ips do |x|
x.report("Using Visibility") do
visibility_app.execute_query(query)
end
x.report("Using Warden") do
warden_app.execute_query(query)
end
x.compare!
end
Run it.
Expected behavior
I expect the new GraphQL::Schema::Visibility
plugin to be as performant as GraphQL::Schema::Warden
. (At least, I need it to be as performant before I can switch to the new plugin, and I'm expecting Warden
to be removed in a future version.)
Actual behavior
The Visibility
plugin is ~20x slower:
ruby 3.2.7 (2025-02-04 revision 02ec315244) [arm64-darwin24]
Warming up --------------------------------------
Using Visibility 13.000 i/100ms
Using Warden 253.000 i/100ms
Calculating -------------------------------------
Using Visibility 127.969 (± 0.8%) i/s (7.81 ms/i) - 650.000 in 5.079653s
Using Warden 2.742k (± 2.8%) i/s (364.70 μs/i) - 13.915k in 5.079058s
Comparison:
Using Warden: 2742.0 i/s
Using Visibility: 128.0 i/s - 21.43x slower