Skip to content

Support for Streams and Iterators#2067

Merged
bbakerman merged 1 commit into
graphql-java:masterfrom
dfa1:support-for-stream-and-iterators
Oct 9, 2020
Merged

Support for Streams and Iterators#2067
bbakerman merged 1 commit into
graphql-java:masterfrom
dfa1:support-for-stream-and-iterators

Conversation

@dfa1

@dfa1 dfa1 commented Oct 2, 2020

Copy link
Copy Markdown
Contributor

Hi @bbakerman @andimarek,

please find my first attempt to be a bit more lazy during list processing in completeValueForList.

The basic idea is to avoid to "materialize" a Stream (and later maybe Iterator) into an ArrayList.

I don't like some details of this PR (notably passing -1 as listSize) but let's start the discussion anyway. Maybe someone have better ideas there.

@dfa1

dfa1 commented Oct 2, 2020

Copy link
Copy Markdown
Contributor Author

To give some more context: I tested this idea in a concrete use-case at work. It allows to serve a particularly big GQL request by allocating half of the memory (max heap usage down from 4.1GB to just 2GB). Since the domain model contains some very big POJOs (i.e. with hundreds of properties) the ability to lazily allocate those in a Stream.map would be a big win for us.

@dfa1 dfa1 changed the title Support for stream and iterators Support for streams Oct 2, 2020
@dfa1 dfa1 changed the title Support for streams Support for Streams and Iterators Oct 3, 2020
@dfa1 dfa1 force-pushed the support-for-stream-and-iterators branch from 6bf6a87 to a14f55c Compare October 3, 2020 05:46

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a mild breaking change - the input is "Object" but the actual type has changed.

I think this is ok (did we say it WOULD always be a collection??) but I just want to call it out and see others thoughts on this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this could be a breaking change.
Arrays are reallocated anymore as List (but I could easily re-introduce this behavior).

For Collections we should be fine: toIterable does not change the concrete type.
For Streams/Iterators we should be fine as well: nobody is using that right now.

@bbakerman bbakerman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks very much for this PR. I think this puts us into a better place (its possible to reduce memory usage if you use streams) without being too invasive.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a look at graphql.execution.ExecutionStrategyParameters#getListSize - we never use it.

I was worried this -1 semantics could affect some one )badly but we never use it - I think this will be ok

@dfa1 dfa1 Oct 6, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I think it is backward compatible.

Maybe we can introduce a new method that returns OptionalInt ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the end of the day we are still allocated an array the size of the list - So source of the data can be a stream but we can stay streaming all the way.

This is an improvement - as you say it greatly reduces your memory usage (nearly half??) but longer term could we have streams all the way down to the turtles?

Thinking aloud here it might be too theoretical - I know there is code out there that assumes ExecutionResult is really a Map of lists and maps and values. Would introducing "streams" in that break things?

@dfa1 dfa1 Oct 6, 2020

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the end of the day we are still allocated an array the size of the list - So source of the data can be a stream but we can stay streaming all the way.

yes, I was not able to remove this big list.

This is an improvement - as you say it greatly reduces your memory usage (nearly half??) but longer term could we have streams all the way down to the turtles?
Don't know yet: eventually everything is "materialized" in a single ExecutionResult. Would be nice to minimize everything else.

This the most big query we have so far.

Before
image

After
image

Thinking aloud here it might be too theoretical - I know there is code out there that assumes ExecutionResult is really a Map of lists and maps and values. Would introducing "streams" in that break things?

We are merely introducing streaming between datafetchers and execution strategy: so this is very conservative choice by now.

Allowing DataFetchers to return Stream<T> and Iterator<T>.
@dfa1 dfa1 force-pushed the support-for-stream-and-iterators branch from a14f55c to 101e06a Compare October 6, 2020 15:39
@dfa1

dfa1 commented Oct 8, 2020

Copy link
Copy Markdown
Contributor Author

it would be possible to merge this tomorrow? I would like to use it in our applications, to provide further feedback to you guys 😊

@bbakerman bbakerman added this to the 16.0 milestone Oct 9, 2020
@bbakerman bbakerman merged commit 8e55666 into graphql-java:master Oct 9, 2020
@andimarek

Copy link
Copy Markdown
Member

@dfa1 I want to point you to the graphql RFC which aims to add defer and stream to GraphQL: https://github.com/graphql/graphql-spec/blob/master/rfcs/DeferStream.md (in case you missed it so far)

@dfa1

dfa1 commented Oct 11, 2020

Copy link
Copy Markdown
Contributor Author

@andimarek thank you :-) yes, I was aware of this proposal and I look forward to it!

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.

3 participants