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

A fix for huge memory usage for larger files. #393

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
76 changes: 59 additions & 17 deletions src/source/RazorEngine.Core/Templating/TemplateBase.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.IO.IsolatedStorage;

namespace RazorEngine.Templating
{
using System;
Expand Down Expand Up @@ -150,7 +152,7 @@ public virtual TemplateWriter Include(string name, object model = null, Type mod
#if RAZOR4
.Wait()
#endif
);
);
}

/// <summary>
Expand Down Expand Up @@ -211,28 +213,40 @@ private static void StreamToTextWriter(MemoryStream memory, TextWriter writer)
/// Runs the template and returns the result.
/// </summary>
/// <param name="context">The current execution context.</param>
/// <param name="reader"></param>
/// <param name="outputWriter"></param>
/// <returns>The merged result of the template.</returns>
#if RAZOR4
public async Task Run(ExecuteContext context, TextWriter reader)
public async Task Run(ExecuteContext context, TextWriter outputWriter)
#else
void ITemplate.Run(ExecuteContext context, TextWriter reader)
void ITemplate.Run(ExecuteContext context, TextWriter outputWriter)
#endif
{
_context = context;

StringBuilder builder = new StringBuilder();
using (var writer = new StringWriter(builder))
var storage = IsolatedStorageFile.GetUserStoreForApplication();

if (storage.DirectoryExists("temp") == false)
{
storage.CreateDirectory("temp");
}

string tempFilePath = Path.Combine("temp", string.Concat("RazorTempFilePath", Guid.NewGuid()));

try
{
_context.CurrentWriter = writer;

using (var stream = new IsolatedStorageFileStream(tempFilePath, FileMode.Create))
using(var writer = new StreamWriter(stream))
{
_context.CurrentWriter = writer;
#if RAZOR4
await Execute();
#else
Execute();
Execute();
#endif
writer.Flush();
_context.CurrentWriter = null;

writer.Flush();
_context.CurrentWriter = null;
}

if (Layout != null)
{
Expand All @@ -241,23 +255,51 @@ void ITemplate.Run(ExecuteContext context, TextWriter reader)

if (layout == null)
{
throw new ArgumentException("Template you are trying to run uses layout, but no layout found in cache or by resolver.");
throw new ArgumentException(
"Template you are trying to run uses layout, but no layout found in cache or by resolver.");
}

// Push the current body instance onto the stack for later execution.
var body = new TemplateWriter(tw => tw.Write(builder.ToString()));
var body = new TemplateWriter(
tw =>
{
var buffer = new char[2000];
using (var stream = new IsolatedStorageFileStream(tempFilePath, FileMode.Open))
using(var reader = new StreamReader(stream)) {
// Push the current body instance onto the stack for later execution.
while (!reader.EndOfStream)
{
var charsRead = reader.Read(buffer, 0, 2000);
tw.Write(buffer, 0, charsRead);
}
}
});

context.PushBody(body);

context.PushSections();

#if RAZOR4
await layout.Run(context, reader);
await layout.Run(context, outputWriter);
#else
layout.Run(context, reader);
layout.Run(context, outputWriter);
#endif
return;
}

reader.Write(builder.ToString());
using (var stream = new IsolatedStorageFileStream(tempFilePath, FileMode.Open))
using(var reader = new StreamReader(stream)) {
var buffer = new char[2000];
// Push the current body instance onto the stack for later execution.
while (!reader.EndOfStream)
{
var charsRead = reader.Read(buffer, 0, 2000);
outputWriter.Write(buffer, 0, charsRead);
}
}
}
finally
{
storage.DeleteFile(tempFilePath);
}
}

Expand Down