Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OOM when we try to compile module with 1000 classes #32204

Closed
warunalakshitha opened this issue Aug 17, 2021 · 5 comments · Fixed by #40015
Closed

OOM when we try to compile module with 1000 classes #32204

warunalakshitha opened this issue Aug 17, 2021 · 5 comments · Fixed by #40015
Assignees
Labels
NBalNeeds Priority/Blocker Team/Observability Observability in general, Metrics, Tracing & Logging Type/Bug

Comments

@warunalakshitha
Copy link
Contributor

warunalakshitha commented Aug 17, 2021

Description:
I have a module with 1000 class definitions as below.

class Person1 {
    string name;
    int age;
    function init(string name, int age) {
        self.name = name;
        self.age = age;
    }
    function getAge() returns int {
        return self.age;

    }
}

class Person2 {
    string name;
    int age;
    function init(string name, int age) {
        self.name = name;
        self.age = age;
    }
    function getAge() returns int {
        return self.age;

    }
}

.
.
.
class Person1000 {
    string name;
    int age;
    function init(string name, int age) {
        self.name = name;
        self.age = age;
    }
    function getAge() returns int {
        return self.age;

    }
}

Getting OOM when try to compile the program.

[2021-08-17 22:35:07,980] SEVERE {b7a.log.crash} - Java heap space 
java.lang.OutOfMemoryError: Java heap space
        at java.base/java.util.Arrays.copyOf(Arrays.java:3745)
        at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:172)
        at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:748)
        at java.base/java.lang.StringBuilder.append(StringBuilder.java:241)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serializeString(JsonCanonicalizer.java:92)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:127)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:110)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:121)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:110)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:110)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:121)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:110)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:121)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.serialize(JsonCanonicalizer.java:110)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.<init>(JsonCanonicalizer.java:37)
        at org.ballerinalang.observability.anaylze.JsonCanonicalizer.getEncodedString(JsonCanonicalizer.java:45)
        at org.ballerinalang.observability.anaylze.DefaultObservabilitySymbolCollector.generateCanonicalJsonString(DefaultObservabilitySymbolCollector.java:177)
        at org.ballerinalang.observability.anaylze.DefaultObservabilitySymbolCollector.writeToExecutable(DefaultObservabilitySymbolCollector.java:114)
        at io.ballerina.projects.JarResolver.getJarFilePathsRequiredForExecution(JarResolver.java:105)
        at io.ballerina.projects.JBallerinaBackend.emitExecutable(JBallerinaBackend.java:510)
        at io.ballerina.projects.JBallerinaBackend.emit(JBallerinaBackend.java:202)
        at io.ballerina.cli.task.CreateExecutableTask.execute(CreateExecutableTask.java:97)
        at io.ballerina.cli.TaskExecutor.executeTasks(TaskExecutor.java:40)
        at io.ballerina.cli.cmd.BuildCommand.execute(BuildCommand.java:330)
        at io.ballerina.cli.launcher.Main$$Lambda$22/0x00000001000bc040.accept(Unknown Source)
        at java.base/java.util.Optional.ifPresent(Optional.java:183)
        at io.ballerina.cli.launcher.Main.main(Main.java:53)
@warunalakshitha warunalakshitha added Type/Bug Team/Observability Observability in general, Metrics, Tracing & Logging labels Aug 17, 2021
@warunalakshitha warunalakshitha changed the title OOM when we try to compile module with 1000 objects OOM when we try to compile module with 1000 classes Aug 17, 2021
@manuranga
Copy link
Contributor

Workaround: pass --observability-included=false to CLI

@warunalakshitha
Copy link
Contributor Author

This will be a blocker if someone needs observability too.

@nadundesilva
Copy link
Contributor

nadundesilva commented Oct 6, 2021

This is most probably happening due to the JSON canonicalizer added to make the ST JSON deterministic during compilation a deterministic JSON (if the same code is compiled multiple times, the JSON needs to be the same). Without the canonicalizer, this used to change due to usages of data structures such as HashMaps, HashSets, within the compiler, which doesn't gaurantee any ordering of the elements inserted into them.

While we have optimized this process as much as possible, the only remaining improvement for this would be to ensure that the compilation logic is deterministic. We would not be able to fix this completely without ensuring the above.

@gabilang
Copy link
Contributor

gabilang commented Mar 2, 2023

The Java class added for JSON canonicalization uses a StringBuilder to create the canonicalized (standardize) JSON from the input JSON data. If the input string is extremely large, it may consume a large amount of memory and may result in OOM error. Additionally the JsonDecoder class also stores the entire input string in memory, which could also be a potential threat for OOM error if the string is very large.
Anyway we cannot fully guarantee that enhancing the usages of HashMaps, HashSets etc for ordering will help to achieve the normalized JSON (It may also broken by future changes and may add an additional overhead on compilation). So it may be the better option to provide the standardized form of the JSON.

@github-actions
Copy link

This issue is NOT closed with a proper Reason/ label. Make sure to add proper reason label before closing. Please add or leave a comment with the proper reason label now.

      - Reason/EngineeringMistake - The issue occurred due to a mistake made in the past.
      - Reason/Regression - The issue has introduced a regression.
      - Reason/MultipleComponentInteraction - Issue occured due to interactions in multiple components.
      - Reason/Complex - Issue occurred due to complex scenario.
      - Reason/Invalid - Issue is invalid.
      - Reason/Other - None of the above cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NBalNeeds Priority/Blocker Team/Observability Observability in general, Metrics, Tracing & Logging Type/Bug
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

4 participants