-
Notifications
You must be signed in to change notification settings - Fork 317
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support offloading the node-model while a resource is loaded
The node model consumes a lot of memory compared to the resource contents. Languages may opt-in to offload the node model into a serialized byte[] either in-memory or persisted somewhere else. It is re-attached on demand. There are some caveats, though. No strong references to original nodes must be held. Otherwise the node model cannot be detached. If a code path strictly needs to refer to a node, DetachableParseResultWrapper.externalReference(IParseResult, INode) can be used. Feature can be enabled by using the DetachableNodeModelFragment. It is subject to the language to chose a suitable moment in the life-cycle of a resource to schedule unloading the node model. DetableParseResultWrapper.acquire might be a candidate if all resources shall be marked as unloadable immediately. Also: - Improved testability of node model - New more flexible API for node model serialization/deserialization - Allow to unbind a Guice binding from a generator fragment Signed-off-by: Sebastian Zarnekow <sebastian.zarnekow@gmail.com>
- Loading branch information
Showing
78 changed files
with
2,562 additions
and
343 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
org.eclipse.xtext.tests/src/org/eclipse/xtext/enumrules/AutoDetachNodeModelTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2024 Sebastian Zarnekow and others. | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License 2.0 which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*******************************************************************************/ | ||
package org.eclipse.xtext.enumrules; | ||
|
||
import java.io.IOException; | ||
import java.time.Duration; | ||
|
||
import org.apache.log4j.Level; | ||
import org.eclipse.xtext.enumrules.parser.antlr.EnumAndReferenceTestLanguageParser; | ||
import org.eclipse.xtext.nodemodel.ICompositeNode; | ||
import org.eclipse.xtext.nodemodel.detachable.DetachableNodeModelBuilder; | ||
import org.eclipse.xtext.nodemodel.detachable.DetachableParseResult; | ||
import org.eclipse.xtext.nodemodel.detachable.GrammarElementLookup; | ||
import org.eclipse.xtext.nodemodel.impl.NodeModelBuilder; | ||
import org.eclipse.xtext.parser.IParser; | ||
import org.eclipse.xtext.parser.ParserTestHelper; | ||
import org.eclipse.xtext.resource.XtextResource; | ||
import org.eclipse.xtext.testing.logging.LoggingTester; | ||
import org.eclipse.xtext.testing.logging.LoggingTester.LogCapture; | ||
import org.junit.Test; | ||
|
||
import com.google.inject.Inject; | ||
|
||
/** | ||
* @author Sebastian - Initial contribution and API | ||
*/ | ||
public class AutoDetachNodeModelTest extends AbstractEnumRulesTest { | ||
|
||
private ParserTestHelper helper; | ||
|
||
@Override | ||
public void setUp() throws Exception { | ||
super.setUp(); | ||
with(EnumAndReferenceTestLanguageStandaloneSetup.class); | ||
helper = new ParserTestHelper(getResourceFactory(), getParser(), get(Keys.RESOURCE_SET_KEY),getCurrentFileExtension()); | ||
} | ||
|
||
static class CustomParser extends EnumAndReferenceTestLanguageParser { | ||
|
||
@Inject GrammarElementLookup grammarElementLookup; | ||
|
||
@Override | ||
protected NodeModelBuilder createNodeModelBuilder() { | ||
return new DetachableNodeModelBuilder(grammarElementLookup) { | ||
@Override | ||
protected DetachableParseResult createEmptyParseResult(GrammarElementLookup grammarElementLookup) { | ||
return new DetachableParseResult(grammarElementLookup, Duration.ofMillis(50)); | ||
} | ||
}; | ||
} | ||
} | ||
|
||
@Override | ||
protected IParser getParser() { | ||
return getInjector().getInstance(CustomParser.class); | ||
} | ||
|
||
@Test public void testNodeModelIsAutoReleased() throws Exception { | ||
LogCapture messages = LoggingTester.captureLogging(Level.TRACE, "org.eclipse.xtext.nodemodel.detachable", ()->{ | ||
try { | ||
String modelAsString = "kindOfKeyword Hoo reference Hoo"; | ||
XtextResource resource = parse(modelAsString); | ||
DetachableParseResult parseResult = (DetachableParseResult) resource.getParseResult(); | ||
ICompositeNode rootNode = parseResult.getRootNode(); | ||
parseResult.releaseNodeModel(false); | ||
|
||
Thread.sleep(200); | ||
assertNotSame(rootNode, parseResult.getRootNode()); | ||
} catch(Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
}); | ||
messages.assertNumberOfLogEntries(2, "scheduleRelease"); | ||
messages.assertLogEntry("serialize:NodeModelData"); | ||
messages.assertLogEntry("nodeModelRequested"); | ||
messages.assertLogEntry("deserialize:StandardNodeModelReference"); | ||
} | ||
|
||
@Test public void testNodeModelIsAutoReleasedAfterUsage() throws Exception { | ||
LogCapture messages = LoggingTester.captureLogging(Level.TRACE, "org.eclipse.xtext.nodemodel.detachable", ()->{ | ||
try { | ||
String modelAsString = "kindOfKeyword Hoo reference Hoo"; | ||
XtextResource resource = parse(modelAsString); | ||
DetachableParseResult parseResult = (DetachableParseResult) resource.getParseResult(); | ||
ICompositeNode rootNode = parseResult.getRootNode(); | ||
parseResult.releaseNodeModel(false); | ||
|
||
Thread.sleep(200); | ||
assertNotSame(rootNode, parseResult.getRootNode()); | ||
Thread.sleep(200); | ||
} catch(Exception e) { | ||
throw new RuntimeException(e); | ||
} | ||
}); | ||
messages.assertNumberOfLogEntries(2, "scheduleRelease"); | ||
messages.assertLogEntry("serialize:NodeModelData"); | ||
messages.assertLogEntry("nodeModelRequested"); | ||
messages.assertLogEntry("deserialize:StandardNodeModelReference"); | ||
messages.assertLogEntry("release"); | ||
} | ||
|
||
protected XtextResource parse(String modelAsString) throws IOException { | ||
return helper.getResourceFromString(modelAsString); | ||
} | ||
} |
Oops, something went wrong.