aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHannes Braun <hannesbraun@mail.de>2023-01-16 18:06:44 +0100
committerGitHub <noreply@github.com>2023-01-16 10:06:44 -0700
commit66eff8b9ca18ab1cde76196c145ad0a98d0eda99 (patch)
tree8e82d4f93a76f2e83a727e483846b6f508f3114d /src
parentbe206d4ff2d799296764c005d7bbbdb5cff7ee2c (diff)
Allow limiting parallel image encodings to reduce memory usage (#8783)
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.Drawing/ImageProcessor.cs31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/Jellyfin.Drawing/ImageProcessor.cs b/src/Jellyfin.Drawing/ImageProcessor.cs
index b381c9ae7..353a27b25 100644
--- a/src/Jellyfin.Drawing/ImageProcessor.cs
+++ b/src/Jellyfin.Drawing/ImageProcessor.cs
@@ -5,10 +5,12 @@ using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.MediaEncoding;
@@ -38,6 +40,8 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
private readonly IImageEncoder _imageEncoder;
private readonly IMediaEncoder _mediaEncoder;
+ private readonly SemaphoreSlim _parallelEncodingLimit;
+
private bool _disposed;
/// <summary>
@@ -48,18 +52,28 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
/// <param name="fileSystem">The filesystem.</param>
/// <param name="imageEncoder">The image encoder.</param>
/// <param name="mediaEncoder">The media encoder.</param>
+ /// <param name="config">The configuration.</param>
public ImageProcessor(
ILogger<ImageProcessor> logger,
IServerApplicationPaths appPaths,
IFileSystem fileSystem,
IImageEncoder imageEncoder,
- IMediaEncoder mediaEncoder)
+ IMediaEncoder mediaEncoder,
+ IServerConfigurationManager config)
{
_logger = logger;
_fileSystem = fileSystem;
_imageEncoder = imageEncoder;
_mediaEncoder = mediaEncoder;
_appPaths = appPaths;
+
+ var semaphoreCount = config.Configuration.ParallelImageEncodingLimit;
+ if (semaphoreCount < 1)
+ {
+ semaphoreCount = 2 * Environment.ProcessorCount;
+ }
+
+ _parallelEncodingLimit = new(semaphoreCount, semaphoreCount);
}
private string ResizedImageCachePath => Path.Combine(_appPaths.ImageCachePath, "resized-images");
@@ -199,7 +213,18 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
{
if (!File.Exists(cacheFilePath))
{
- string resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
+ // Limit number of parallel (more precisely: concurrent) image encodings to prevent a high memory usage
+ await _parallelEncodingLimit.WaitAsync().ConfigureAwait(false);
+
+ string resultPath;
+ try
+ {
+ resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
+ }
+ finally
+ {
+ _parallelEncodingLimit.Release();
+ }
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
{
@@ -563,6 +588,8 @@ public sealed class ImageProcessor : IImageProcessor, IDisposable
disposable.Dispose();
}
+ _parallelEncodingLimit?.Dispose();
+
_disposed = true;
}
}