Skip to content

Conversation

xuorig
Copy link

@xuorig xuorig commented Jun 23, 2025

For schemas with a large amount of object extensions, makeSchema can allocate a lot of memory due to the immutable nature of TypeRegistry.*extensions().

The main culprit is src/main/java/graphql/schema/idl/ImplementingTypesChecker.java which repeatedly calls objectTypeExtensions and interfaceTypeExtensions. (first commit)

buildObjectType is also an issue. (second commit).

First commit fix on ImplementingTypesChecker should make a lot of sense, but for buildObjectType, I'd love your opinions. I can cache all kinds of extensions on BuildContext (only did object type for now, as that was our issue).

Can also discuss if there should be cheaper getters on TypeRegistry. I welcome your thoughts!

@bbakerman
Copy link
Member

I think this PR is a good work around. However cheaper accessors is the way forward really

Can also discuss if there should be cheaper getters on TypeRegistry. I welcome your thoughts!

yeah the code today is old and crusty

    public Map<String, List<ObjectTypeExtensionDefinition>> objectTypeExtensions() {
        return new LinkedHashMap<>(objectTypeExtensions);
    }

This idea of copying the objects should be replaced by ImmutableXX collections - we have embraced this elsewhere in the graphql code base but not here is seems.

if we had immutables in place then

return buildCtx.getTypeRegistry().objectTypeExtensions().getOrDefault(typeDefinition.getName(), emptyList());

and

        return buildCtx.objectTypeExtensions.getOrDefault(typeDefinition.getName(), emptyList());

would be the same cost

@bbakerman
Copy link
Member

Ahh I just had a look at the code - its embraced mutability up the wazoo

typeRegistry.add(x)
typeRegistry.merge(otherTypeReg)

Hmmm immutability is now tricky because its relying on mutability when being built (versus being read)

I am wary that we could make this embrace immutability and not break everyone - is the juice worth the squeeze ??

We need some new structure when its passed in as a "read only" world to say SchemaGenerator and so on

Spitballing this could be

ImmutableTypeRegistry locked =  typeRegistry.readOnly()

and then key code could be hanged to used here. In some ways this is what you did when you threaded the "copied" lists into the read only places

Hmmmm tricky to fix systemically

@bbakerman
Copy link
Member

ok this PR is probably more systemic

#4021

Now the code covered in this PR gets a graphql.schema.idl.ImmutableTypeDefinitionRegistry and hence asking for the values repeatedly give out the same object and not a copy of the maps

@xuorig
Copy link
Author

xuorig commented Jun 24, 2025

That's great @bbakerman 🚀🚢

@xuorig
Copy link
Author

xuorig commented Jun 24, 2025

Closing in favor of #4021

@xuorig xuorig closed this Jun 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants