Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,12 +1,42 @@
# frozen_string_literal: true

require 'rake/testtask'
require "bundler/gem_helper"
Bundler::GemHelper.install_tasks

require "rake/testtask"

Rake::TestTask.new(:test) do |t, args|
puts args
t.libs << "test"
t.libs << "lib"
t.test_files = FileList['test/**/*_test.rb']
t.test_files = FileList["test/**/*_test.rb"]
end

# Load rake tasks from lib/tasks
Dir.glob("lib/tasks/*.rake").each { |r| load r }

namespace :benchmark do
def prepare_benchmark
require_relative("./benchmark/run.rb")
end

desc "Benchmark execution"
task :execution do
prepare_benchmark
GraphQLBenchmark.benchmark_execution
end

desc "Benchmark lazy execution"
task :lazy_execution do
prepare_benchmark
GraphQLBenchmark.benchmark_lazy_execution
end

desc "Memory profile"
task :memory do
prepare_benchmark
GraphQLBenchmark.memory_profile
end
end

task :default => :test
task default: :test
163 changes: 163 additions & 0 deletions benchmark/run.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# frozen_string_literal: true
#
require "debug"
require "graphql"
require "graphql/batch"
require "graphql/cardinal"

require "benchmark/ips"
require "memory_profiler"
require_relative '../test/fixtures'

class GraphQLBenchmark
DOCUMENT = GraphQL.parse(BASIC_DOCUMENT)
CARDINAL_SCHEMA = SCHEMA

class Schema < GraphQL::Schema
lazy_resolve(Proc, :call)
end

class DataloaderSchema < GraphQL::Schema
use GraphQL::Dataloader
end

class BatchLoaderSchema < GraphQL::Schema
use GraphQL::Batch
end

GRAPHQL_GEM_SCHEMA = Schema.from_definition(SDL, default_resolve: GEM_RESOLVERS)
GRAPHQL_GEM_LAZY_SCHEMA = Schema.from_definition(SDL, default_resolve: GEM_LAZY_RESOLVERS)
GRAPHQL_GEM_DATALOADER_SCHEMA = DataloaderSchema.from_definition(SDL, default_resolve: GEM_DATALOADER_RESOLVERS)
GRAPHQL_GEM_DATALOADER_SCHEMA.use(GraphQL::Dataloader)

GRAPHQL_GEM_BATCH_LOADER_SCHEMA = BatchLoaderSchema.from_definition(SDL, default_resolve: GEM_BATCH_LOADER_RESOLVERS)
GRAPHQL_GEM_BATCH_LOADER_SCHEMA.use(GraphQL::Batch)

class << self
def benchmark_execution
default_data_sizes = "10, 100, 1000, 10000"
sizes = ENV.fetch("SIZES", default_data_sizes).split(",").map(&:to_i)

with_data_sizes(sizes) do |data_source, num_objects|
Benchmark.ips do |x|
x.report("graphql-ruby: #{num_objects} resolvers") do
GRAPHQL_GEM_SCHEMA.execute(document: DOCUMENT, root_value: data_source)
end

x.report("graphql-cardinal #{num_objects} resolvers") do
GraphQL::Cardinal::Executor.new(
SCHEMA,
BREADTH_RESOLVERS,
DOCUMENT,
data_source
).perform
end

x.compare!
end
end
end

def benchmark_lazy_execution
default_data_sizes = "10, 100, 1000, 10000"
sizes = ENV.fetch("SIZES", default_data_sizes).split(",").map(&:to_i)

with_data_sizes(sizes) do |data_source, num_objects|
Benchmark.ips do |x|
x.report("graphql-ruby lazy: #{num_objects} resolvers") do
GRAPHQL_GEM_LAZY_SCHEMA.execute(document: DOCUMENT, root_value: data_source)
end

x.report("graphql-ruby dataloader: #{num_objects} resolvers") do
GRAPHQL_GEM_DATALOADER_SCHEMA.execute(document: DOCUMENT, root_value: data_source)
end

x.report("graphql-ruby batch: #{num_objects} resolvers") do
GRAPHQL_GEM_BATCH_LOADER_SCHEMA.execute(document: DOCUMENT, root_value: data_source)
end

x.report("graphql-cardinal: #{num_objects} lazy resolvers") do
GraphQL::Cardinal::Executor.new(
SCHEMA,
BREADTH_DEFERRED_RESOLVERS,
DOCUMENT,
data_source
).perform
end

x.compare!
end
end
end

def memory_profile
default_data_sizes = "10, 1000"
sizes = ENV.fetch("SIZES", default_data_sizes).split(",").map(&:to_i)

with_data_sizes(sizes) do |data_source, num_objects|
report = MemoryProfiler.report do
GRAPHQL_GEM_SCHEMA.execute(document: DOCUMENT, root_value: data_source)
end

puts "\n\ngraphql-ruby memory profile: #{num_objects} resolvers"
puts "=" * 50
report.pretty_print
end

with_data_sizes(sizes) do |data_source, num_objects|
report = MemoryProfiler.report do
GraphQL::Cardinal::Executor.new(
SCHEMA,
BREADTH_RESOLVERS,
DOCUMENT,
data_source
).perform
end

puts "\n\ngraphql-cardinal memory profile: #{num_objects} resolvers"
puts "=" * 50
report.pretty_print
end
end

def with_data_sizes(sizes = [10])
sizes.each do |size|
products = (1..size).map do |i|
{
"id" => i.to_s,
"title" => "Product #{i}",
"variants" => {
"nodes" => (1..5).map do |j|
{
"id" => "#{i}-#{j}",
"title" => "Variant #{j}"
}
end
}
}
end

data = {
"products" => {
"nodes" => products
}
}

num_objects = object_count(data)

yield data, num_objects
end
end

def object_count(obj)
case obj
when Hash
obj.size + obj.values.sum { |value| object_count(value) }
when Array
obj.sum { |item| object_count(item) }
else
0
end
end
end
end
12 changes: 8 additions & 4 deletions graphql-cardinal.gemspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'graphql/cardinal/version'
# frozen_string_literal: true

require_relative 'lib/graphql/cardinal/version'

Gem::Specification.new do |spec|
spec.name = 'graphql-cardinal'
Expand All @@ -27,8 +26,13 @@ Gem::Specification.new do |spec|
spec.require_paths = ['lib']

spec.add_runtime_dependency 'graphql', '>= 2.0'
spec.add_runtime_dependency 'ostruct'

spec.add_development_dependency 'bundler', '~> 2.0'
spec.add_development_dependency 'rake', '~> 12.0'
spec.add_development_dependency 'minitest', '~> 5.12'
spec.add_development_dependency 'benchmark-ips', '~> 2.0'
spec.add_development_dependency 'memory_profiler'
spec.add_development_dependency 'debug'
spec.add_development_dependency 'graphql-batch'
end
Loading