mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-08 23:00:51 +02:00
improve image serving performance slightly
This commit is contained in:
parent
bb281d4bcc
commit
cbd767ddce
|
@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
|
||||||
}
|
}
|
||||||
catch (IOException)
|
catch (IOException)
|
||||||
{
|
{
|
||||||
// Cache file doesn't exist or is currently being written ro
|
// Cache file doesn't exist or is currently being written to
|
||||||
}
|
}
|
||||||
|
|
||||||
var semaphore = GetLock(cacheFilePath);
|
var semaphore = GetLock(cacheFilePath);
|
||||||
|
@ -129,21 +129,24 @@ namespace MediaBrowser.Server.Implementations.Drawing
|
||||||
await semaphore.WaitAsync().ConfigureAwait(false);
|
await semaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
// Check again in case of lock contention
|
// Check again in case of lock contention
|
||||||
if (File.Exists(cacheFilePath))
|
try
|
||||||
{
|
{
|
||||||
try
|
using (var fileStream = new FileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
|
||||||
{
|
|
||||||
using (var fileStream = new FileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
|
|
||||||
{
|
|
||||||
await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
{
|
||||||
|
await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
// Cache file doesn't exist or is currently being written to
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -188,12 +191,10 @@ namespace MediaBrowser.Server.Implementations.Drawing
|
||||||
|
|
||||||
var bytes = outputMemoryStream.ToArray();
|
var bytes = outputMemoryStream.ToArray();
|
||||||
|
|
||||||
var outputTask = toStream.WriteAsync(bytes, 0, bytes.Length);
|
await toStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
|
||||||
|
|
||||||
// kick off a task to cache the result
|
// kick off a task to cache the result
|
||||||
var cacheTask = CacheResizedImage(cacheFilePath, bytes);
|
CacheResizedImage(cacheFilePath, bytes, semaphore);
|
||||||
|
|
||||||
await Task.WhenAll(outputTask, cacheTask).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,12 +203,51 @@ namespace MediaBrowser.Server.Implementations.Drawing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
catch
|
||||||
{
|
{
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
|
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Caches the resized image.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cacheFilePath">The cache file path.</param>
|
||||||
|
/// <param name="bytes">The bytes.</param>
|
||||||
|
/// <param name="semaphore">The semaphore.</param>
|
||||||
|
private void CacheResizedImage(string cacheFilePath, byte[] bytes, SemaphoreSlim semaphore)
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var parentPath = Path.GetDirectoryName(cacheFilePath);
|
||||||
|
|
||||||
|
if (!Directory.Exists(parentPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(parentPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save to the cache location
|
||||||
|
using (var cacheFileStream = new FileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
|
||||||
|
{
|
||||||
|
// Save to the filestream
|
||||||
|
await cacheFileStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.ErrorException("Error writing to image cache file {0}", ex, cacheFilePath);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
semaphore.Release();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the color of the background.
|
/// Sets the color of the background.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -363,28 +403,6 @@ namespace MediaBrowser.Server.Implementations.Drawing
|
||||||
return croppedImagePath;
|
return croppedImagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Caches the resized image.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="cacheFilePath">The cache file path.</param>
|
|
||||||
/// <param name="bytes">The bytes.</param>
|
|
||||||
private async Task CacheResizedImage(string cacheFilePath, byte[] bytes)
|
|
||||||
{
|
|
||||||
var parentPath = Path.GetDirectoryName(cacheFilePath);
|
|
||||||
|
|
||||||
if (!Directory.Exists(parentPath))
|
|
||||||
{
|
|
||||||
Directory.CreateDirectory(parentPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save to the cache location
|
|
||||||
using (var cacheFileStream = new FileStream(cacheFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
|
|
||||||
{
|
|
||||||
// Save to the filestream
|
|
||||||
await cacheFileStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the cache file path based on a set of parameters
|
/// Gets the cache file path based on a set of parameters
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -314,6 +314,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
/// <param name="context">The CTX.</param>
|
/// <param name="context">The CTX.</param>
|
||||||
private async void ProcessHttpRequestAsync(HttpListenerContext context)
|
private async void ProcessHttpRequestAsync(HttpListenerContext context)
|
||||||
{
|
{
|
||||||
|
var date = DateTime.Now;
|
||||||
|
|
||||||
LogHttpRequest(context);
|
LogHttpRequest(context);
|
||||||
|
|
||||||
if (context.Request.IsWebSocketRequest)
|
if (context.Request.IsWebSocketRequest)
|
||||||
|
@ -360,7 +362,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
var url = context.Request.Url.ToString();
|
var url = context.Request.Url.ToString();
|
||||||
var endPoint = context.Request.RemoteEndPoint;
|
var endPoint = context.Request.RemoteEndPoint;
|
||||||
|
|
||||||
LogResponse(context, url, endPoint);
|
var duration = DateTime.Now - date;
|
||||||
|
|
||||||
|
LogResponse(context, url, endPoint, duration);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -461,14 +465,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
/// <param name="ctx">The CTX.</param>
|
/// <param name="ctx">The CTX.</param>
|
||||||
/// <param name="url">The URL.</param>
|
/// <param name="url">The URL.</param>
|
||||||
/// <param name="endPoint">The end point.</param>
|
/// <param name="endPoint">The end point.</param>
|
||||||
private void LogResponse(HttpListenerContext ctx, string url, IPEndPoint endPoint)
|
/// <param name="duration">The duration.</param>
|
||||||
|
private void LogResponse(HttpListenerContext ctx, string url, IPEndPoint endPoint, TimeSpan duration)
|
||||||
{
|
{
|
||||||
if (!EnableHttpRequestLogging)
|
if (!EnableHttpRequestLogging)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var statusode = ctx.Response.StatusCode;
|
var statusCode = ctx.Response.StatusCode;
|
||||||
|
|
||||||
var log = new StringBuilder();
|
var log = new StringBuilder();
|
||||||
|
|
||||||
|
@ -476,7 +481,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
|
||||||
|
|
||||||
log.AppendLine("Headers: " + string.Join(",", ctx.Response.Headers.AllKeys.Select(k => k + "=" + ctx.Response.Headers[k])));
|
log.AppendLine("Headers: " + string.Join(",", ctx.Response.Headers.AllKeys.Select(k => k + "=" + ctx.Response.Headers[k])));
|
||||||
|
|
||||||
var msg = "Http Response Sent (" + statusode + ") to " + endPoint;
|
var responseTime = string.Format(". Response time: {0} ms", duration.TotalMilliseconds);
|
||||||
|
|
||||||
|
var msg = "Response code " + statusCode + " sent to " + endPoint + responseTime;
|
||||||
|
|
||||||
_logger.LogMultiline(msg, LogSeverity.Debug, log);
|
_logger.LogMultiline(msg, LogSeverity.Debug, log);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue