瀏覽代碼

improve image serving performance slightly

Luke Pulverenti 11 年之前
父節點
當前提交
cbd767ddce

+ 56 - 38
MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs

@@ -121,7 +121,7 @@ namespace MediaBrowser.Server.Implementations.Drawing
             }
             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);
@@ -129,21 +129,24 @@ namespace MediaBrowser.Server.Implementations.Drawing
             await semaphore.WaitAsync().ConfigureAwait(false);
 
             // 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))
-                    {
-                        await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
-                        return;
-                    }
-                }
-                finally
+                using (var fileStream = new FileStream(cacheFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous))
                 {
+                    await fileStream.CopyToAsync(toStream).ConfigureAwait(false);
                     semaphore.Release();
+                    return;
                 }
             }
+            catch (IOException)
+            {
+                // Cache file doesn't exist or is currently being written to
+            }
+            catch
+            {
+                semaphore.Release();
+                throw;
+            }
 
             try
             {
@@ -188,12 +191,10 @@ namespace MediaBrowser.Server.Implementations.Drawing
 
                                         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
-                                        var cacheTask = CacheResizedImage(cacheFilePath, bytes);
-
-                                        await Task.WhenAll(outputTask, cacheTask).ConfigureAwait(false);
+                                        CacheResizedImage(cacheFilePath, bytes, semaphore);
                                     }
                                 }
                             }
@@ -202,12 +203,51 @@ namespace MediaBrowser.Server.Implementations.Drawing
                     }
                 }
             }
-            finally
+            catch
             {
                 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>
         /// Sets the color of the background.
         /// </summary>
@@ -363,28 +403,6 @@ namespace MediaBrowser.Server.Implementations.Drawing
             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>
         /// Gets the cache file path based on a set of parameters
         /// </summary>

+ 11 - 4
MediaBrowser.Server.Implementations/HttpServer/HttpServer.cs

@@ -314,6 +314,8 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// <param name="context">The CTX.</param>
         private async void ProcessHttpRequestAsync(HttpListenerContext context)
         {
+            var date = DateTime.Now;
+
             LogHttpRequest(context);
 
             if (context.Request.IsWebSocketRequest)
@@ -360,7 +362,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
                     var url = context.Request.Url.ToString();
                     var endPoint = context.Request.RemoteEndPoint;
 
-                    LogResponse(context, url, endPoint);
+                    var duration = DateTime.Now - date;
+
+                    LogResponse(context, url, endPoint, duration);
 
                 }
                 catch (Exception ex)
@@ -461,14 +465,15 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// <param name="ctx">The CTX.</param>
         /// <param name="url">The URL.</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)
             {
                 return;
             }
 
-            var statusode = ctx.Response.StatusCode;
+            var statusCode = ctx.Response.StatusCode;
 
             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])));
 
-            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);
         }