mirror of https://github.com/ErsatzTV/ErsatzTV.git
Browse Source
* regularly release memory * don't aggressively GC while legacy streaming * update changelogpull/1128/head
13 changed files with 125 additions and 8 deletions
@ -0,0 +1,3 @@ |
|||||||
|
namespace ErsatzTV.Application.Maintenance; |
||||||
|
|
||||||
|
public record ReleaseMemory(bool ForceAggressive) : IRequest<Unit>, IBackgroundServiceRequest; |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
using ErsatzTV.Core.FFmpeg; |
||||||
|
using ErsatzTV.Core.Interfaces.FFmpeg; |
||||||
|
using Microsoft.Extensions.Logging; |
||||||
|
|
||||||
|
namespace ErsatzTV.Application.Maintenance; |
||||||
|
|
||||||
|
public class ReleaseMemoryHandler : IRequestHandler<ReleaseMemory, Unit> |
||||||
|
{ |
||||||
|
private readonly IFFmpegSegmenterService _ffmpegSegmenterService; |
||||||
|
private readonly ILogger<ReleaseMemoryHandler> _logger; |
||||||
|
|
||||||
|
public ReleaseMemoryHandler( |
||||||
|
IFFmpegSegmenterService ffmpegSegmenterService, |
||||||
|
ILogger<ReleaseMemoryHandler> logger) |
||||||
|
{ |
||||||
|
_ffmpegSegmenterService = ffmpegSegmenterService; |
||||||
|
_logger = logger; |
||||||
|
} |
||||||
|
|
||||||
|
public Task<Unit> Handle(ReleaseMemory request, CancellationToken cancellationToken) |
||||||
|
{ |
||||||
|
bool hasActiveWorkers = _ffmpegSegmenterService.SessionWorkers.Any() || FFmpegProcess.ProcessCount > 0; |
||||||
|
if (request.ForceAggressive || !hasActiveWorkers) |
||||||
|
{ |
||||||
|
_logger.LogDebug("Starting aggressive garbage collection"); |
||||||
|
GC.Collect(2, GCCollectionMode.Aggressive, blocking: true, compacting: true); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
_logger.LogDebug("Starting garbage collection"); |
||||||
|
GC.Collect(2, GCCollectionMode.Forced, blocking: false); |
||||||
|
} |
||||||
|
|
||||||
|
GC.WaitForPendingFinalizers(); |
||||||
|
GC.Collect(); |
||||||
|
|
||||||
|
_logger.LogDebug("Completed garbage collection"); |
||||||
|
|
||||||
|
return Task.FromResult(Unit.Default); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
using System.Diagnostics; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.FFmpeg; |
||||||
|
|
||||||
|
public class FFmpegProcess : Process |
||||||
|
{ |
||||||
|
public static int ProcessCount; |
||||||
|
|
||||||
|
public FFmpegProcess() |
||||||
|
{ |
||||||
|
Interlocked.Increment(ref ProcessCount); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void Dispose(bool disposing) |
||||||
|
{ |
||||||
|
base.Dispose(disposing); |
||||||
|
|
||||||
|
Interlocked.Decrement(ref ProcessCount); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
using ErsatzTV.Application.Maintenance; |
||||||
|
using MediatR; |
||||||
|
using Microsoft.AspNetCore.Mvc; |
||||||
|
|
||||||
|
namespace ErsatzTV.Controllers.Api; |
||||||
|
|
||||||
|
[ApiController] |
||||||
|
public class MaintenanceController |
||||||
|
{ |
||||||
|
private readonly IMediator _mediator; |
||||||
|
|
||||||
|
public MaintenanceController(IMediator mediator) => _mediator = mediator; |
||||||
|
|
||||||
|
[HttpGet("/api/maintenance/gc")] |
||||||
|
public async Task<IActionResult> GarbageCollection([FromQuery] bool force = false) |
||||||
|
{ |
||||||
|
await _mediator.Send(new ReleaseMemory(force)); |
||||||
|
return new OkResult(); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue