Skip to content

Commit

Permalink
Optimisations: Don't keep saving state when you continually see the s…
Browse files Browse the repository at this point in the history
…ame newline during a calculation after a line of content. Avoid allocating continually in VisitChangedContainersDueToDivert. Cache output stream contents.
  • Loading branch information
joethephish committed Dec 20, 2016
1 parent 61f81ac commit f299e17
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 21 deletions.
16 changes: 12 additions & 4 deletions ink-engine-runtime/Story.cs
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,13 @@ string ContinueInternal()
// We're going to continue stepping in case we see glue or some
// non-text content such as choices.
if( canContinue ) {
stateAtLastNewline = StateSnapshot();

// Don't bother to record the state beyond the current newline.
// e.g.:
// Hello world\n // record state at the end of here
// ~ complexCalculation() // don't actually need this unless it generates text
if( stateAtLastNewline == null )
stateAtLastNewline = StateSnapshot();
}

// Can't continue, so we're about to exit - make sure we
Expand Down Expand Up @@ -510,6 +516,7 @@ void VisitContainer(Container container, bool atStart)
}
}

HashSet<Container> _prevContainerSet;
void VisitChangedContainersDueToDivert()
{
var previousContentObject = state.previousContentObject;
Expand All @@ -519,11 +526,12 @@ void VisitChangedContainersDueToDivert()
return;

// First, find the previously open set of containers
var prevContainerSet = new HashSet<Container> ();
if( _prevContainerSet == null ) _prevContainerSet = new HashSet<Container> ();
_prevContainerSet.Clear();
if (previousContentObject) {
Container prevAncestor = previousContentObject as Container ?? previousContentObject.parent as Container;
while (prevAncestor) {
prevContainerSet.Add (prevAncestor);
_prevContainerSet.Add (prevAncestor);
prevAncestor = prevAncestor.parent as Container;
}
}
Expand All @@ -532,7 +540,7 @@ void VisitChangedContainersDueToDivert()
// content step. However, we need to walk up the new ancestry to see if there are more new containers
Runtime.Object currentChildOfContainer = newContentObject;
Container currentContainerAncestor = currentChildOfContainer.parent as Container;
while (currentContainerAncestor && !prevContainerSet.Contains(currentContainerAncestor)) {
while (currentContainerAncestor && !_prevContainerSet.Contains(currentContainerAncestor)) {

// Check whether this ancestor container is being entered at the start,
// by checking whether the child object is the first.
Expand Down
68 changes: 52 additions & 16 deletions ink-engine-runtime/StoryState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,35 +147,47 @@ internal string currentText
{
get
{
var sb = new StringBuilder ();
if( _outputStreamTextDirty ) {
var sb = new StringBuilder ();

foreach (var outputObj in _outputStream) {
var textContent = outputObj as StringValue;
if (textContent != null) {
sb.Append(textContent.value);
}
}

foreach (var outputObj in _outputStream) {
var textContent = outputObj as StringValue;
if (textContent != null) {
sb.Append(textContent.value);
}
}
_currentText = sb.ToString ();

_outputStreamTextDirty = false;
}

return sb.ToString ();
return _currentText;
}
}
string _currentText;

internal List<string> currentTags
{
get
{
List<string> tags = new List<string>();
if( _outputStreamTagsDirty ) {
_currentTags = new List<string>();

foreach (var outputObj in _outputStream) {
var tag = outputObj as Tag;
if (tag != null) {
_currentTags.Add (tag.text);
}
}

foreach (var outputObj in _outputStream) {
var tag = outputObj as Tag;
if (tag != null) {
tags.Add (tag.text);
}
}
_outputStreamTagsDirty = false;
}

return tags;
return _currentTags;
}
}
List<string> _currentTags;

internal bool inExpressionEvaluation {
get {
Expand All @@ -191,6 +203,7 @@ internal StoryState (Story story)
this.story = story;

_outputStream = new List<Runtime.Object> ();
OutputStreamDirty();

evaluationStack = new List<Runtime.Object> ();

Expand Down Expand Up @@ -227,6 +240,8 @@ internal StoryState Copy()
var copy = new StoryState(story);

copy.outputStream.AddRange(_outputStream);
OutputStreamDirty();

copy._currentChoices.AddRange(_currentChoices);

if (hasError) {
Expand Down Expand Up @@ -328,6 +343,7 @@ public Dictionary<string, object> jsonToken
evaluationStack = Json.JArrayToRuntimeObjList ((List<object>)jObject ["evalStack"]);

_outputStream = Json.JArrayToRuntimeObjList ((List<object>)jObject ["outputStream"]);
OutputStreamDirty();

_currentChoices = Json.JArrayToRuntimeObjList<Choice>((List<object>)jObject ["currentChoices"]);

Expand Down Expand Up @@ -370,6 +386,7 @@ internal void ResetErrors()
internal void ResetOutput()
{
_outputStream.Clear ();
OutputStreamDirty();
}

// Push to output stream, but split out newlines in text for consistency
Expand All @@ -388,6 +405,8 @@ internal void PushToOutputStream(Runtime.Object obj)
}

PushToOutputStreamIndividual (obj);

OutputStreamDirty();
}


Expand Down Expand Up @@ -523,6 +542,8 @@ void PushToOutputStreamIndividual(Runtime.Object obj)
if (includeInOutput) {
_outputStream.Add (obj);
}

OutputStreamDirty();
}

void TrimNewlinesFromOutputStream(Glue rightGlueToStopAt)
Expand Down Expand Up @@ -582,6 +603,8 @@ void TrimNewlinesFromOutputStream(Glue rightGlueToStopAt)
}
}
}

OutputStreamDirty();
}

void TrimFromExistingGlue()
Expand All @@ -594,6 +617,8 @@ void TrimFromExistingGlue()
else
i++;
}

OutputStreamDirty();
}


Expand All @@ -608,6 +633,8 @@ void RemoveExistingGlue()
break;
}
}

OutputStreamDirty();
}

int currentGlueIndex {
Expand Down Expand Up @@ -832,11 +859,20 @@ internal void AddError(string message)
currentErrors.Add (message);
}

void OutputStreamDirty()
{
_outputStreamTextDirty = true;
_outputStreamTagsDirty = true;
}

// REMEMBER! REMEMBER! REMEMBER!
// When adding state, update the Copy method and serialisation
// REMEMBER! REMEMBER! REMEMBER!

List<Runtime.Object> _outputStream;
bool _outputStreamTextDirty = true;
bool _outputStreamTagsDirty = true;

List<Choice> _currentChoices;

// Temporary state only, during externally called function evaluation
Expand Down
2 changes: 1 addition & 1 deletion tests/Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2231,7 +2231,7 @@ public void TestVisitCountsWhenChoosing()
@"
== TestKnot ==
this is a test
+ Next -> TestKnot2
+ [Next] -> TestKnot2
== TestKnot2 ==
this is the end
Expand Down

0 comments on commit f299e17

Please sign in to comment.