diff --git a/src/Microsoft.AspNet.StaticFiles/StreamCopyOperation.cs b/src/Microsoft.AspNet.StaticFiles/StreamCopyOperation.cs index c9ce5cbd74..25bbae6107 100644 --- a/src/Microsoft.AspNet.StaticFiles/StreamCopyOperation.cs +++ b/src/Microsoft.AspNet.StaticFiles/StreamCopyOperation.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Buffers; using System.Diagnostics; using System.IO; using System.Threading; @@ -12,49 +13,56 @@ namespace Microsoft.AspNet.StaticFiles // FYI: In most cases the source will be a FileStream and the destination will be to the network. internal static class StreamCopyOperation { - private const int DefaultBufferSize = 1024 * 16; + private const int DefaultBufferSize = 4096; internal static async Task CopyToAsync(Stream source, Stream destination, long? length, CancellationToken cancel) { long? bytesRemaining = length; - byte[] buffer = new byte[DefaultBufferSize]; - Debug.Assert(source != null); - Debug.Assert(destination != null); - Debug.Assert(!bytesRemaining.HasValue || bytesRemaining.Value >= 0); - Debug.Assert(buffer != null); - - while (true) + var buffer = ArrayPool.Shared.Rent(DefaultBufferSize); + try { - // The natural end of the range. - if (bytesRemaining.HasValue && bytesRemaining.Value <= 0) + Debug.Assert(source != null); + Debug.Assert(destination != null); + Debug.Assert(!bytesRemaining.HasValue || bytesRemaining.Value >= 0); + Debug.Assert(buffer != null); + + while (true) { - return; + // The natural end of the range. + if (bytesRemaining.HasValue && bytesRemaining.Value <= 0) + { + return; + } + + cancel.ThrowIfCancellationRequested(); + + int readLength = buffer.Length; + if (bytesRemaining.HasValue) + { + readLength = (int)Math.Min(bytesRemaining.Value, (long)readLength); + } + int count = await source.ReadAsync(buffer, 0, readLength, cancel); + + if (bytesRemaining.HasValue) + { + bytesRemaining -= count; + } + + // End of the source stream. + if (count == 0) + { + return; + } + + cancel.ThrowIfCancellationRequested(); + + await destination.WriteAsync(buffer, 0, count, cancel); } - - cancel.ThrowIfCancellationRequested(); - - int readLength = buffer.Length; - if (bytesRemaining.HasValue) - { - readLength = (int)Math.Min(bytesRemaining.Value, (long)readLength); - } - int count = await source.ReadAsync(buffer, 0, readLength, cancel); - - if (bytesRemaining.HasValue) - { - bytesRemaining -= count; - } - - // End of the source stream. - if (count == 0) - { - return; - } - - cancel.ThrowIfCancellationRequested(); - - await destination.WriteAsync(buffer, 0, count, cancel); + } + finally + { + ArrayPool.Shared.Return(buffer); } } } diff --git a/src/Microsoft.AspNet.StaticFiles/project.json b/src/Microsoft.AspNet.StaticFiles/project.json index 87611531d7..0b9daa1c02 100644 --- a/src/Microsoft.AspNet.StaticFiles/project.json +++ b/src/Microsoft.AspNet.StaticFiles/project.json @@ -14,7 +14,8 @@ "Microsoft.AspNet.FileProviders.Abstractions": "1.0.0-*", "Microsoft.AspNet.Hosting.Abstractions": "1.0.0-*", "Microsoft.Extensions.Logging.Abstractions": "1.0.0-*", - "Microsoft.Extensions.WebEncoders": "1.0.0-*" + "Microsoft.Extensions.WebEncoders": "1.0.0-*", + "System.Buffers": "4.0.0-*" }, "frameworks": { "net451": {},