dylan
July 19, 2018, 7:54pm
1
In the code of HttpResult
here , there must be a better way than having to read an entire stream into memory?
Is there not a more efficient way of writing a stream out without having it in memory? There is also a .ToArray()
on line 286 - would Spans or something not be better?
What are your thoughts?
mythz
July 19, 2018, 8:06pm
2
Where is the entire stream read in memory? This is writing from the FileStream directly to the Response Stream:
private void WriteTo(Stream responseStream, int paddingLength)
{
var response = RequestContext != null ? RequestContext.Response : null;
if (this.FileInfo != null)
{
if (response != null)
response.SetContentLength(FileInfo.Length + paddingLength);
using (var fs = this.FileInfo.OpenRead())
{
fs.WriteTo(responseStream);
return;
}
}
if (this.ResponseStream != null)
{
if (response != null)
{
var ms = ResponseStream as MemoryStream;
if (ms != null)
If you check the latest version of HttpResult
it’s no longer calling .ToArray()
:
if (this.ResponseStream != null)
{
try
{
if (response != null)
{
if (ResponseStream is MemoryStream ms)
{
response.SetContentLength(ms.Length + paddingLength);
await ms.WriteToAsync(responseStream, token:token);
return;
}
}
await ResponseStream.CopyToAsync(responseStream, token);
}
finally
{
DisposeStream();
}
It calls an efficient WriteToAsync()
which tries to access the internal buffer before falling back to ToArray()
:
var ret = encoding.GetString(ms.GetBuffer(), 0, (int) ms.Length);
return ret.InTask();
}
catch (UnauthorizedAccessException)
{
Tracer.Instance.WriteWarning("MemoryStream in ReadToEndAsync() wasn't created with a publiclyVisible:true byte[] bufffer, falling back to slow impl");
using (var reader = new StreamReader(ms, encoding, true, DefaultBufferSize, leaveOpen:true))
{
return reader.ReadToEndAsync();
}
}
}
public static string ReadToEnd(this Stream stream) => ReadToEnd(stream, JsConfig.UTF8Encoding);
public static string ReadToEnd(this Stream stream, Encoding encoding)
{
if (stream is MemoryStream ms)
return ms.ReadToEnd();
if (stream.CanSeek)
That’s as efficient as it can be made, Span doesn’t help here.