Improvements around streams

* Use ArrayPool instead of allocating new buffers each time
* Remove NetworkStream copy
* Remove some dead code
This commit is contained in:
Bond-009
2019-03-13 17:51:33 +01:00
parent 1d443d2ff5
commit e64aaebbac
11 changed files with 269 additions and 451 deletions

View File

@@ -23,7 +23,6 @@ using MediaBrowser.Model.IO;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Querying;
using MediaBrowser.Model.Services;
using MediaBrowser.Model.System;
using Microsoft.Net.Http.Headers;
namespace MediaBrowser.Api.LiveTv
@@ -695,27 +694,36 @@ namespace MediaBrowser.Api.LiveTv
private readonly IHttpClient _httpClient;
private readonly ILibraryManager _libraryManager;
private readonly IDtoService _dtoService;
private readonly IFileSystem _fileSystem;
private readonly IAuthorizationContext _authContext;
private readonly ISessionContext _sessionContext;
private ICryptoProvider _cryptographyProvider;
private IStreamHelper _streamHelper;
private IMediaSourceManager _mediaSourceManager;
private readonly ICryptoProvider _cryptographyProvider;
private readonly IStreamHelper _streamHelper;
private readonly IMediaSourceManager _mediaSourceManager;
public LiveTvService(ICryptoProvider crypto, IMediaSourceManager mediaSourceManager, IStreamHelper streamHelper, ILiveTvManager liveTvManager, IUserManager userManager, IServerConfigurationManager config, IHttpClient httpClient, ILibraryManager libraryManager, IDtoService dtoService, IFileSystem fileSystem, IAuthorizationContext authContext, ISessionContext sessionContext)
public LiveTvService(
ICryptoProvider crypto,
IMediaSourceManager mediaSourceManager,
IStreamHelper streamHelper,
ILiveTvManager liveTvManager,
IUserManager userManager,
IServerConfigurationManager config,
IHttpClient httpClient,
ILibraryManager libraryManager,
IDtoService dtoService,
IAuthorizationContext authContext,
ISessionContext sessionContext)
{
_cryptographyProvider = crypto;
_mediaSourceManager = mediaSourceManager;
_streamHelper = streamHelper;
_liveTvManager = liveTvManager;
_userManager = userManager;
_config = config;
_httpClient = httpClient;
_libraryManager = libraryManager;
_dtoService = dtoService;
_fileSystem = fileSystem;
_authContext = authContext;
_sessionContext = sessionContext;
_cryptographyProvider = crypto;
_streamHelper = streamHelper;
_mediaSourceManager = mediaSourceManager;
}
public object Get(GetTunerHostTypes request)
@@ -729,7 +737,7 @@ namespace MediaBrowser.Api.LiveTv
var user = request.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(request.UserId);
var folders = _liveTvManager.GetRecordingFolders(user);
var returnArray = _dtoService.GetBaseItemDtos(folders.ToArray(), new DtoOptions(), user);
var returnArray = _dtoService.GetBaseItemDtos(folders, new DtoOptions(), user);
var result = new QueryResult<BaseItemDto>
{
@@ -754,7 +762,7 @@ namespace MediaBrowser.Api.LiveTv
[HeaderNames.ContentType] = Model.Net.MimeTypes.GetMimeType(path)
};
return new ProgressiveFileCopier(_fileSystem, _streamHelper, path, outputHeaders, Logger)
return new ProgressiveFileCopier(_streamHelper, path, outputHeaders, Logger)
{
AllowEndOfFile = false
};

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
@@ -11,22 +12,17 @@ namespace MediaBrowser.Api.LiveTv
{
public class ProgressiveFileCopier : IAsyncStreamWriter, IHasHeaders
{
private readonly IFileSystem _fileSystem;
private readonly ILogger _logger;
private readonly string _path;
private readonly Dictionary<string, string> _outputHeaders;
const int StreamCopyToBufferSize = 81920;
public long StartPosition { get; set; }
public bool AllowEndOfFile = true;
private readonly IDirectStreamProvider _directStreamProvider;
private IStreamHelper _streamHelper;
public ProgressiveFileCopier(IFileSystem fileSystem, IStreamHelper streamHelper, string path, Dictionary<string, string> outputHeaders, ILogger logger)
public ProgressiveFileCopier(IStreamHelper streamHelper, string path, Dictionary<string, string> outputHeaders, ILogger logger)
{
_fileSystem = fileSystem;
_path = path;
_outputHeaders = outputHeaders;
_logger = logger;
@@ -43,18 +39,6 @@ namespace MediaBrowser.Api.LiveTv
public IDictionary<string, string> Headers => _outputHeaders;
private Stream GetInputStream(bool allowAsyncFileRead)
{
var fileOpenOptions = FileOpenOptions.SequentialScan;
if (allowAsyncFileRead)
{
fileOpenOptions |= FileOpenOptions.Asynchronous;
}
return _fileSystem.GetFileStream(_path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.ReadWrite, fileOpenOptions);
}
public async Task WriteToAsync(Stream outputStream, CancellationToken cancellationToken)
{
if (_directStreamProvider != null)
@@ -63,28 +47,23 @@ namespace MediaBrowser.Api.LiveTv
return;
}
var eofCount = 0;
var fileOptions = FileOptions.SequentialScan;
// use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039
var allowAsyncFileRead = true;
using (var inputStream = GetInputStream(allowAsyncFileRead))
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
if (StartPosition > 0)
{
inputStream.Position = StartPosition;
}
fileOptions |= FileOptions.Asynchronous;
}
using (var inputStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 4096, fileOptions))
{
var emptyReadLimit = AllowEndOfFile ? 20 : 100;
var eofCount = 0;
while (eofCount < emptyReadLimit)
{
int bytesRead;
bytesRead = await _streamHelper.CopyToAsync(inputStream, outputStream, cancellationToken).ConfigureAwait(false);
//var position = fs.Position;
//_logger.LogDebug("Streamed {0} bytes to position {1} from file {2}", bytesRead, position, path);
if (bytesRead == 0)
{
eofCount++;