-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Performance issues #87
Comments
Upon closer inspection, the culprit seems to be We should add a performance test to ensure that this isn't a problem going forward (a test that consists of several large ActiveRecord objects, ideally). |
On this note I just tried this gem for the first time and we have specs using results = OurSchema.execute(...)
expect(results).to match hash_including(...) For just a single one of these, Is there any option to simply disable |
Yeah I can see how that would be annoying. There is a way to configure super_diff to process objects in a custom way, but it depends on which matcher you're using to match that object and which objects are being compared to each other. However, this customization works best if you're using Regardless, it seems like you ran into the slowdown you mentioned because you were trying to use expect(results).to have_attributes(
to_h: a_hash_including(
# ...
)
) Or, using something that was closer to what you went with: expect(results.to_h).to include(
# ...
) In the future, you might have to be more careful about which matchers you use, so as to prevent super_diff from doing more work than is needed to generate a diff. That said, I would be curious to know what output you got to confirm the assumption I'm making above and see how I could make super_diff better for you. I would not be surprised if the way super_diff inspects full objects is slow itself and needs some fine-tuning to make it more performant. So if there's a way you can go into more detail about what sort of output super_diff generated then that would help me! |
Thanks for the reply! Yeah, I already spent some time combing through our graphql specs adding Possibly worth the tradeoff though. After all I have been thinking about having something like this for more than a decade 😅 |
Ah... okay. I'm all for that too, I definitely don't want people rewriting their tests to accommodate this tool. So now I'm curious — if you turn off |
Hey, just hit this same issue in a fairly large GraphQL codebase within a federated graph spanning 10+ projects. Had a simple seeming test that I expected to fail and it completely locked rspec generating the many megabytes of colored stdout text. Pegged a CPU on a 2021 macbook pro and printed for more than a minute :P Basically: let(:query) do
execute_query(query: "query { things { id } }")
# returning: <GraphQL::Query::Result @to_h={"data" => {"things" => [{"id" => "1"}]}}>
end
let(:expectation) do
{"data" => {"things" => [{"id" => "1"}, {"id" => "2"}]}}
end
it "matches expectation" do
expect(query).to eq(expectation)
end One really really simple dumb fix is to add an class GraphQL::Query::Result
def attributes_for_super_diff
to_h
end
end But that doesn't give the nice diff'd output:
I've tried reverse engineering the custom differ + object tree builder + object tree + object tree flattener code in the library and ended up with the same output but way more code. I feel like all I really want to say is "replace this object with its |
Ahhhhh, answering my own question after writing ~100 lines of code and then deleting ~80 of 'em. This seems to be the minimal custom SuperDiff code for treating a My spec/support/super_diff.rb file looks like this: class GraphQL::Query::Result
def attributes_for_super_diff
to_h
end
end
module GraphQL
class Differ < ::SuperDiff::Differs::Base
def self.applies_to?(expected, actual)
expected.is_a?(::Hash) &&
actual.is_a?(::GraphQL::Query::Result)
end
def operation_tree_builder_class
GraphQL::OperationTreeBuilder
end
end
class OperationTreeBuilder < SuperDiff::OperationTreeBuilders::Hash
def self.applies_to?(value)
value.is_a?(::GraphQL::Query::Result)
end
def initialize(actual:, **rest)
@actual = actual.to_h
super
end
end
end
SuperDiff.configure do |config|
config.add_extra_differ_class(GraphQL::Differ)
end Which produces this output:
Which is exactly what I wanted! |
Awesome, I'm happy you were able to figure it out @abachman! |
I have recently noticed some performance issues with the gem when dealing with large diffs with deeply nested structures, which I've confirmed by temporarily switching off
require "super_diff/rspec"
at work. I don't have anything that points to what would be causing this, but for context the test looked like:where
some_record
is an instance of a god model. I should look into this to see if there's any low-hanging fruit. It's also probably worth adding a benchmark as a test to ensure that this doesn't become a problem in the future once a fix is implemented.The text was updated successfully, but these errors were encountered: