|
2 | 2 | require "graphql" |
3 | 3 | ADD_WARDEN = false |
4 | 4 | TESTING_EXEC_NEXT = !!ENV["GRAPHQL_FUTURE"] |
| 5 | +TESTING_METHOD = !!ENV["TEST_METHOD"] |
5 | 6 | require "jazz" |
6 | 7 | require "benchmark/ips" |
7 | 8 | require "stackprof" |
@@ -269,33 +270,49 @@ def self.profile_large_result |
269 | 270 | schema = ProfileLargeResult::Schema |
270 | 271 | schema.use(GraphQL::Dataloader) |
271 | 272 | document = ProfileLargeResult::ALL_FIELDS |
| 273 | + method_document = ProfileLargeResult::ALL_METHOD_FIELDS |
| 274 | + |
| 275 | + r1 = schema.execute_next(document: document) |
| 276 | + r2 = schema.execute(document: document) |
| 277 | + if r1 != r2 |
| 278 | + raise "Legacy vs next mismatch" |
| 279 | + end |
| 280 | + |
| 281 | + r3 = schema.execute_next(document: method_document) |
| 282 | + if r1 != r3 |
| 283 | + raise "Method vs non-method mismatch" |
| 284 | + end |
272 | 285 | Benchmark.ips do |x| |
273 | 286 | x.config(time: 5) |
274 | | - x.report("exec #{ProfileLargeResult::DATA.size} objects") { |
| 287 | + x.report("exec ") { |
275 | 288 | schema.execute(document: document) |
276 | 289 | } |
277 | | - x.report("exec_next #{ProfileLargeResult::DATA.size} objects") { |
| 290 | + x.report("exec method") { |
| 291 | + schema.execute(document: method_document) |
| 292 | + } |
| 293 | + x.report("exec_next") { |
278 | 294 | schema.execute_next(document: document) |
279 | 295 | } |
280 | | - end |
281 | | - r1 = schema.execute_next(document: document) |
282 | | - r2 = schema.execute(document: document) |
283 | | - if r1 != r2 |
284 | | - raise "Result mismatch:\n\n#{r1.inspect}\n\n#{r2.inspect}" |
| 296 | + x.report("exec_next method") { |
| 297 | + schema.execute_next(document: method_document) |
| 298 | + } |
| 299 | + x.compare! |
285 | 300 | end |
286 | 301 |
|
| 302 | + |
287 | 303 | exec_method = TESTING_EXEC_NEXT ? :execute_next : :execute |
| 304 | + exec_doc = TESTING_METHOD ? method_document : document |
288 | 305 | result = StackProf.run(mode: :wall, interval: 1) do |
289 | | - schema.public_send(exec_method, document: document) |
| 306 | + schema.public_send(exec_method, document: exec_doc) |
290 | 307 | end |
291 | 308 | StackProf::Report.new(result).print_text |
292 | 309 |
|
293 | 310 | StackProf.run(mode: :wall, interval: 1, out: "tmp/stackprof.dump") do |
294 | | - schema.public_send(exec_method, document: document) |
| 311 | + schema.public_send(exec_method, document: exec_doc) |
295 | 312 | end |
296 | 313 |
|
297 | 314 | report = MemoryProfiler.report do |
298 | | - schema.public_send(exec_method, document: document) |
| 315 | + schema.public_send(exec_method, document: exec_doc) |
299 | 316 | end |
300 | 317 |
|
301 | 318 | report.pretty_print |
@@ -408,60 +425,102 @@ module Baz |
408 | 425 | class ExampleExtension < GraphQL::Schema::FieldExtension |
409 | 426 | end |
410 | 427 |
|
411 | | - class FooType < GraphQL::Schema::Object |
412 | | - implements Baz |
413 | | - field :id, ID, null: false, extensions: [ExampleExtension], hash_key: :id |
414 | | - field :int1, Integer, null: false, extensions: [ExampleExtension], hash_key: :int1 |
415 | | - field :int2, Integer, null: false, extensions: [ExampleExtension], hash_key: :int2 |
416 | | - field :string1, String, null: false, hash_key: :string1 do |
417 | | - argument :arg1, String, required: false |
418 | | - argument :arg2, String, required: false |
419 | | - argument :arg3, String, required: false |
420 | | - argument :arg4, String, required: false |
421 | | - end |
| 428 | + def self.generate_foo_type(name, config_key) |
| 429 | + Class.new(GraphQL::Schema::Object) do |
| 430 | + graphql_name(name) |
| 431 | + implements Baz |
| 432 | + field :id, GraphQL::Types::ID, null: false, extensions: [ExampleExtension], config_key => :id |
| 433 | + def id |
| 434 | + object[:id] |
| 435 | + end |
422 | 436 |
|
423 | | - field :string2, String, null: false, hash_key: :string2 do |
424 | | - argument :arg1, String, required: false |
425 | | - argument :arg2, String, required: false |
426 | | - argument :arg3, String, required: false |
427 | | - argument :arg4, String, required: false |
428 | | - end |
| 437 | + field :int1, Integer, null: false, extensions: [ExampleExtension], config_key => :int1 |
429 | 438 |
|
430 | | - field :boolean1, Boolean, null: false, hash_key: :boolean1 do |
431 | | - argument :arg1, String, required: false |
432 | | - argument :arg2, String, required: false |
433 | | - argument :arg3, String, required: false |
434 | | - argument :arg4, String, required: false |
435 | | - end |
436 | | - field :boolean2, Boolean, null: false, hash_key: :boolean2 do |
437 | | - argument :arg1, String, required: false |
438 | | - argument :arg2, String, required: false |
439 | | - argument :arg3, String, required: false |
440 | | - argument :arg4, String, required: false |
441 | | - end |
| 439 | + def int1 |
| 440 | + object[:int1] |
| 441 | + end |
442 | 442 |
|
443 | | - field :foos, [FooType], null: false, description: "Return a list of Foo objects", resolve_legacy_instance_method: true do |
444 | | - argument :first, Integer, default_value: DATA_SIZE |
445 | | - end |
| 443 | + field :int2, Integer, null: false, extensions: [ExampleExtension], config_key => :int2 |
446 | 444 |
|
447 | | - def foos(first:) |
448 | | - DATA.first(first) |
449 | | - end |
| 445 | + def int2 |
| 446 | + object[:int2] |
| 447 | + end |
| 448 | + |
| 449 | + field :string1, String, null: false, config_key => :string1 do |
| 450 | + argument :arg1, String, required: false |
| 451 | + argument :arg2, String, required: false |
| 452 | + argument :arg3, String, required: false |
| 453 | + argument :arg4, String, required: false |
| 454 | + end |
| 455 | + |
| 456 | + def string1(...) |
| 457 | + object[:string1] |
| 458 | + end |
| 459 | + |
| 460 | + field :string2, String, null: false, config_key => :string2 do |
| 461 | + argument :arg1, String, required: false |
| 462 | + argument :arg2, String, required: false |
| 463 | + argument :arg3, String, required: false |
| 464 | + argument :arg4, String, required: false |
| 465 | + end |
450 | 466 |
|
451 | | - field :foo, FooType, resolve_legacy_instance_method: true |
452 | | - def foo |
453 | | - DATA.sample |
| 467 | + def string2(...) |
| 468 | + object[:string2] |
| 469 | + end |
| 470 | + |
| 471 | + field :boolean1, GraphQL::Types::Boolean, null: false, config_key => :boolean1 do |
| 472 | + argument :arg1, String, required: false |
| 473 | + argument :arg2, String, required: false |
| 474 | + argument :arg3, String, required: false |
| 475 | + argument :arg4, String, required: false |
| 476 | + end |
| 477 | + |
| 478 | + def boolean1(...) |
| 479 | + object[:boolean1] |
| 480 | + end |
| 481 | + |
| 482 | + field :boolean2, GraphQL::Types::Boolean, null: false, config_key => :boolean2 do |
| 483 | + argument :arg1, String, required: false |
| 484 | + argument :arg2, String, required: false |
| 485 | + argument :arg3, String, required: false |
| 486 | + argument :arg4, String, required: false |
| 487 | + end |
| 488 | + |
| 489 | + def boolean2(...) |
| 490 | + object[:boolean2] |
| 491 | + end |
| 492 | + |
| 493 | + field :foos, [self], null: false, description: "Return a list of Foo objects", resolve_legacy_instance_method: true do |
| 494 | + argument :first, Integer, default_value: DATA_SIZE |
| 495 | + end |
| 496 | + |
| 497 | + def foos(first:) |
| 498 | + DATA.first(first) |
| 499 | + end |
| 500 | + |
| 501 | + field :foo, self, resolve_legacy_instance_method: true |
| 502 | + def foo |
| 503 | + DATA.sample |
| 504 | + end |
454 | 505 | end |
455 | 506 | end |
456 | 507 |
|
| 508 | + FooType = generate_foo_type("Foo", :hash_key) |
| 509 | + FooMethodType = generate_foo_type("MethodFoo", :resolve_legacy_instance_method) |
| 510 | + |
457 | 511 | class QueryType < GraphQL::Schema::Object |
458 | 512 | description "Query root of the system" |
459 | 513 | field :foos, [FooType], null: false, description: "Return a list of Foo objects", resolve_legacy_instance_method: true do |
460 | 514 | argument :first, Integer, default_value: DATA_SIZE |
461 | 515 | end |
| 516 | + |
462 | 517 | def foos(first:) |
463 | 518 | DATA.first(first) |
464 | 519 | end |
| 520 | + |
| 521 | + field :method_foos, [FooMethodType], null: false, resolver_method: :foos, resolve_legacy_instance_method: :foos do |
| 522 | + argument :first, Integer, default_value: DATA_SIZE |
| 523 | + end |
465 | 524 | end |
466 | 525 |
|
467 | 526 | class Schema < GraphQL::Schema |
@@ -489,6 +548,23 @@ class Schema < GraphQL::Schema |
489 | 548 | } |
490 | 549 | } |
491 | 550 | GRAPHQL |
| 551 | + |
| 552 | + ALL_METHOD_FIELDS = GraphQL.parse <<-GRAPHQL |
| 553 | + query($skip: Boolean = false) { |
| 554 | + foos: methodFoos { |
| 555 | + id @skip(if: $skip) |
| 556 | + int1 |
| 557 | + int2 |
| 558 | + string1 |
| 559 | + string2 |
| 560 | + boolean1 |
| 561 | + boolean2 |
| 562 | + stringArray |
| 563 | + intArray |
| 564 | + booleanArray |
| 565 | + } |
| 566 | + } |
| 567 | + GRAPHQL |
492 | 568 | end |
493 | 569 |
|
494 | 570 | def self.profile_to_definition |
|
0 commit comments