Closed pkunze closed 1 year ago
Hi @pkunze, thanks for reporting the issue.
Have you tried specifying the Xmx for the JVM? Try it like this:
java -Xmx1024m -jar .\swagger-brake-2.3.0-cli.jar --old-api=swagger_3.1.json --new-api=swagger_3.2.json --output-formats=STDOUT,JSON,HTML
This'll give the JVM 1024 MB of memory. If still experiencing the issue, you could try increasing this number but that'll indicate a huge API file (which shouldn't be an issue, just calling it out).
Let me know.
Hi @galovics,
Thanks for the quick reply! I just did as instructed resulting in
java -Xmx1024m -jar .\swagger-brake-2.3.0-cli.jar --old-api=swagger_3.1.json --new-api=swagger_3.2.json --output-formats=STDOUT,JSON,HTML
Loading old API from swagger_3.1.json
Loading new API from swagger_3.2.json
Successfully loaded APIs
Starting the check for breaking API changes
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.stream.ReferencePipeline.map(Unknown Source)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.getSchemaAttributes(SchemaTransformer.java:119)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.transformSchema(SchemaTransformer.java:100)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.internalTransform(SchemaTransformer.java:53)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.lambda$getSchemaAttributes$0(SchemaTransformer.java:121)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer$$Lambda$138/0x0000000800e38468.apply(Unknown Source)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
at java.base/java.util.Iterator.forEachRemaining(Unknown Source)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.getSchemaAttributes(SchemaTransformer.java:126)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.transformSchema(SchemaTransformer.java:100)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.internalTransform(SchemaTransformer.java:53)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.lambda$getSchemaAttributes$0(SchemaTransformer.java:121)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer$$Lambda$138/0x0000000800e38468.apply(Unknown Source)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)
at java.base/java.util.Iterator.forEachRemaining(Unknown Source)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.getSchemaAttributes(SchemaTransformer.java:126)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.transformSchema(SchemaTransformer.java:100)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.internalTransform(SchemaTransformer.java:53)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.internalTransform(SchemaTransformer.java:43)
at io.redskap.swagger.brake.core.model.transformer.SchemaTransformer.lambda$getSchemaAttributes$0(SchemaTransformer.java:121)
The API Files are approx. 288KB If that matters. I also tried using a lower mayor version of swagger-brake with the same result. Let me knowif you need the files and if so where I can send them to :)
Also... it feels like some kind of infinite loop. The Console where I executed the command pretty much ate up all my notebooks ram (consumed more then 8GB according to task manager) and cpu (99%) 🚀🚀🚀
Thanks @pkunze, it seems like there's an infinite loop for sure. You can send the file here arnold_galovics (at) docktape (dot) com
I did, thank you!
@galovics did you already find time to have a look at this? I would gladly take a look myself if it is not a super-complicated fix, however, I guess if you want me to I would need some help getting started since I am not a Java developer ;)
@pkunze I'm playing around with it. I even tried to run your OpenAPI contracts with 10G memory but it's still not enough. I'm still trying to figure out whats going on.
I tried it with 32gb as well with the same result.
I will also try to narrow down what endpoint/schema part might cause this.
Yeah, I think it's probably a recursive schema somewhere but I wasn't able to narrow down yet either.
I'm still analyzing memory dumps but I can already see that one of the problems in the OpenAPI definition you've shared is the fact that it's having a combinatorial explosion in terms of attributes. For example let's consider this as an attribute:
declaredType.assembly.definedTypes.baseType.assembly.customAttributes.constructor.module.assembly.definedTypes.assembly.entryPoint.module.assembly.definedTypes.typeInitializer.module.assembly.entryPoint.methodHandle.value
Now imagine how many other attribute combinations there can be; and this is for many of the attributes. I've made some minor optimizations but it's still not analyzable for swagger-brake.
Are attributes a Swagger/OpenAPI concept or do you mean .NET Attributes? In the latter case I could try find and exclude the affected schema parts.
I mean the Swagger schema attributes. As you can see in my previous comment, the Assembly schema has been reused in many other schema definitions and for all of those there's a number of attribute combinations.
For some testing purposes, I've used a 2MB big API definition to see if swagger-brake can cope with it. I did introduce a few optimizations but works, even without increasing the max heap size: https://github.com/redskap/swagger-brake/pull/80
Going back, I think the reason that your definition runs out of memory is the number of attribute combinations since everything is referencing everything. I'm not really sure how to solve it short-term without refactoring the whole transformation phase along with the breaking rule checks but that'd be a huge work.
I just found this which seems to reflect what you describe. I'll play around with it next week and let you know if there is any progress (currently at the beach 😎🏝️).
Oh, so this is generated schema from C#; that answers it. Yeah, internal classes have been included in the schema definitions which in this case is wrong (I thought you want to mimic a very generic API).
Let me know if you find anything.
P.S. enjoy your time off :))
I can now confirm that swagger-break works, when fixing the mentioned issue, where sort of internal .NET System Types leaked into the checked json file.
I guess we can fix this issue. Thanks for your help!
Sounds good @pkunze, thanks for the info.
I just tried out swagger-brake and am getting the following Exception:
I would glady share both json files, but I'd rather do so privately via e-mail. If this is relevant: we are generating the everything swagger related using swashbuckle on asp.net core 6.0.