redoc icon indicating copy to clipboard operation
redoc copied to clipboard

Schema causing ReDoc to run out of memory

Open AlexRichter opened this issue 6 years ago • 11 comments

We have a rather large schema that is causing Redoc to fail to render as the browser runs out of memory.

I have tried utilising redoc-cli to bundle but this will run seemingly forever and never complete.

The schema can be found here: https://gist.github.com/AlexRichter/001f64d9c5ac17a8a0bfdb1a771eef71

I have tried creating a minimal use case but can't as I believe the issue is due to the complexity of the schema.

You can fix it by removing some of the oneOf and discriminator in CheckResource. If you only have 3 it will render quickly, up to 5 and it takes ~18 seconds. All of them and it will never complete.

Your help is much appreciated!

AlexRichter avatar Nov 02 '18 19:11 AlexRichter

I have done further testing and you can actually get it to fail with just CheckResource having two oneOf:

"CheckResource": {
                "description": "A single check run against a profile",
                "oneOf": [
                    {
                        "$ref": "#/components/schemas/CheckResourceCompanyFilingPurchase"
                    },
                    {
                        "$ref": "#/components/schemas/CheckResourceCompanyPepsAndSanctionsScreen"
                    }
                ],
                "title": "CheckResource",
                "discriminator": {
                    "propertyName": "check_type",
                    "mapping": {
                        "COMPANY_FILING_PURCHASE": "#/components/schemas/CheckResourceCompanyFilingPurchase",
                        "COMPANY_PEPS_AND_SANCTIONS_SCREEN": "#/components/schemas/CheckResourceCompanyPepsAndSanctionsScreen"
                    }
                }
            },

Specifically what seems to be causing the issue is both CheckResourceCompanyFilingPurchase and CheckResourceCompanyPepsAndSanctionsScreen have this:

"input_data": {
 "$ref": "#/components/schemas/CompanyData"
},

Removing input_data from either will result in it rendering it about 14 seconds. Seems there is something about this that is causing an infinite cycle.

I've tried renaming input_data in one and it still runs out of memory so something about both referencing the same component.

Hope you can help!

AlexRichter avatar Nov 02 '18 19:11 AlexRichter

Thanks for the detailed issue report. I will look into it asap.

RomanHotsiy avatar Nov 05 '18 13:11 RomanHotsiy

Thanks @RomanGotsiy

I found that the further cause for this is that CompanyData references itself in ownership_structure and officers. If you remove these two fields from CompanyData then the schema will also render.

AlexRichter avatar Nov 05 '18 14:11 AlexRichter

Hi @RomanGotsiy have you made any progress on this?

Many thanks

AlexRichter avatar Nov 28 '18 13:11 AlexRichter

I have the same issue. When I try to render this spec: https://raw.githubusercontent.com/Picturepark/Picturepark.SDK.DotNet/master/swagger/PictureparkSwagger.json

I get this exception when using the cli: FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 1: node_module_register 2: v8::internal::FatalProcessOutOfMemory 3: v8::internal::FatalProcessOutOfMemory 4: v8::internal::Factory::NewRawTwoByteString 5: v8::internal::Smi::SmiPrint 6: v8::internal::StackGuard::HandleInterrupts 7: v8::internal::interpreter::BytecodeArrayRandomIterator::UpdateOffsetFromIndex 8: 0000014ED0D043C1

When I try to render the docs in Chrome, the Browser crashes.

Many thanks

neotek avatar Mar 27 '19 12:03 neotek

Any update on this issue? I'm running into the same thing.

shauntarves avatar Dec 11 '19 15:12 shauntarves

Not really, those issues are hard to debug and fix. It's mainly due to the complexity of the OpenAPI definition (usually when using heavily discriminator)

@neotek I will look into your example once I have time

RomanHotsiy avatar Dec 12 '19 10:12 RomanHotsiy

The same issue with 2,5MB schema:

$ redoc-cl) bundle openapi.json 
Prerendering docs
<--- Last few GCs --->

[13127:0x4db9f90]   233579 ms: Scavenge 7964.5 (8009.0) -> 7964.1 (8009.2) MB, 2552.7 / 0.0 ms  (average mu = 0.234, current mu = 0.183) allocation failure 
[13127:0x4db9f90]   239768 ms: Mark-sweep 7964.9 (8009.2) -> 7964.4 (8009.2) MB, 6187.4 / 0.0 ms  (average mu = 0.269, current mu = 0.292) allocation failure scavenge might not succeed

<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0x145ce19]
    1: StubFrame [pc: 0x14cd159]
Security context: 0x36f2b3400921 <JSObject>
    2: buildFields(aka buildFields) [0x22cee6a05c09] [/usr/local/lib/node_modules/redoc-cli/node_modules/redoc/bundles/redoc.lib.js:1] [bytecode=0xc69b6096d71 offset=0](this=0x3fe3297804b9 <undefined>,0x3bb22a740159 <OpenAPIParser map = 0x103bee953041>,0x1709cf221131 <Object map = 0x21a5f77ad1>,0x1b51dd086039 <String[46]: #/compon...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory

Writing Node.js report to file: report.20200212.141729.13127.0.001.json
Node.js report completed
 1: 0xa9d570 node::Abort() [node]
 2: 0xa9f832 node::OnFatalError(char const*, char const*) [node]
 3: 0xc0772e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xc07aa9 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xdb5fb5  [node]
 6: 0xdb6646 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [node]
 7: 0xdc4eb9 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
 8: 0xdc5cf5 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 9: 0xdc87cc v8::internal::Heap::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
10: 0xd8f3a4 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
11: 0x10dc6ce v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
12: 0x145ce19  [node]

Moreover, when I set bigger node heap limit I have other issue:

$ node --max_old_space_size=16000 $(which redoc-cli) bundle openapi.json 
Prerendering docs
RangeError: Invalid string length
    at ReactDOMServerRenderer.read (/usr/local/lib/node_modules/redoc-cli/node_modules/react-dom/cjs/react-dom-server.node.development.js:3567:36)
    at Object.renderToString (/usr/local/lib/node_modules/redoc-cli/node_modules/react-dom/cjs/react-dom-server.node.development.js:4245:27)
    at /usr/local/lib/node_modules/redoc-cli/index.js:192:29
    at Generator.next (<anonymous>)
    at fulfilled (/usr/local/lib/node_modules/redoc-cli/index.js:5:58)

marc1n avatar Feb 12 '20 13:02 marc1n

same issue swagger: https://api.stage.opentact.org/swagger.json

alucky4eg avatar Oct 08 '20 14:10 alucky4eg

We experience this issue as well. Swagger: https://contao.github.io/contao-manager/api/swagger.yaml

fritzmg avatar Dec 17 '20 11:12 fritzmg

I am experiencing this issue as well. I can't share the swagger but after testing on my local I've concluded that this issue is due to bi-directional oneOf relationships present in the spec. Attempting to server render with cli yields "out of memory error" and attempting to do the same in the browser uses ~100% CPU & eventually crashes.

j-gibweb avatar Mar 25 '22 21:03 j-gibweb