Skip to content

Large memory allocations and very slow execution when type errors occur in complex inputs #1753

Closed
@SoyYoRafa

Description

@SoyYoRafa

Hi,

We have a rather large complex object as an input. A single request with hundreds of type errors in the input took 9 seconds in graphql.execute. The majority of the time spent (>95%) was spent in the inspect() call, specifically its recursive object string construction. There were huge amount of memory allocations. With 20 concurrent requests, we can consistently cause node to run out of memory. Changing inspect() to return an empty string lowered the total execution time of our process to low hundreds of milliseconds and the process was stable. I don't know the exact latency of graphql.execute with inspect effectively disabled. Given this finding, I am proposing three changes.

  1. inspect() should never be in the execution path as currently written. At the very least, it should not be recursive and/or have a maximum string length. In our case, each inspect grew to be over 100KB.
  2. There should be a maximum amount of errors in getVariableValues(). If the number of errors reaches the maximum, no additional varDefNodes are processed. This grew to be ~1500. Cap at 5?
  3. If inspect() must be kept, there should also be a maximum total amount of error lengths between error messages in getVariableValues(). If the limit is reached, no more varDefNodes should be processed. This would prevent large single errors from multiplying by the cap.

Given that we had ~1500 errors, each error was ~100KB and there were 20 concurrent requests, that is 3GB of memory. That is more than the default max-old-space-size.

Item 2 is an easy fix but 1 and 3 will make the execution path much more robust. We are in an air-gapped environment so I cannot easily provide a reproducible case.

        const properties = Object.keys(value)
          .map(k => `${k}: ${inspect(value[k])}`)
          .join(', ');

graphql 14.1.1
node 8.11.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions