Added NoGCRegion feature
This commit is contained in:
@@ -5,6 +5,9 @@
|
||||
"profileSaveIntervalSeconds": 15,
|
||||
"sptFriendNickname": "SPT",
|
||||
"allowProfileWipe": true,
|
||||
"enableNoGCRegions": true,
|
||||
"noGCRegionMaxMemoryGB": 4,
|
||||
"noGCRegionMaxLOHMemoryGB": 3,
|
||||
"bsgLogging": {
|
||||
"verbosity": 6,
|
||||
"sendToServer": false
|
||||
|
||||
@@ -42,6 +42,44 @@ public record CoreConfig : BaseConfig
|
||||
[JsonPropertyName("features")]
|
||||
public required ServerFeatures Features { get; set; }
|
||||
|
||||
[JsonPropertyName("enableNoGCRegions")]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public required bool EnableNoGCRegions { get; set; }
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private int _noGCRegionMaxMemoryGB = 4;
|
||||
[JsonPropertyName("noGCRegionMaxMemoryGB")]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public required int NoGCRegionMaxMemoryGB
|
||||
{
|
||||
get => _noGCRegionMaxMemoryGB;
|
||||
set
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw new Exception($"Invalid value {nameof(NoGCRegionMaxMemoryGB)}: {value}. Must be greater than zero.");
|
||||
}
|
||||
_noGCRegionMaxMemoryGB = value;
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private int _noGCRegionMaxLOHMemoryGB = 3;
|
||||
[JsonPropertyName("noGCRegionMaxLOHMemoryGB")]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public required int NoGCRegionMaxLOHMemoryGB
|
||||
{
|
||||
get => _noGCRegionMaxLOHMemoryGB;
|
||||
set
|
||||
{
|
||||
if (value <= 0)
|
||||
{
|
||||
throw new Exception($"Invalid value {nameof(NoGCRegionMaxLOHMemoryGB)}: {value}. Must be greater than zero.");
|
||||
}
|
||||
_noGCRegionMaxLOHMemoryGB = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commit hash build server was created from
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Authentication;
|
||||
using System.Text;
|
||||
@@ -118,6 +119,8 @@ public static class Program
|
||||
forwardedHeadersOptions.KnownProxies.Clear();
|
||||
app.UseForwardedHeaders(forwardedHeadersOptions);
|
||||
|
||||
app.UseRequestTracking();
|
||||
|
||||
SetConsoleOutputMode();
|
||||
|
||||
await app.Services.GetRequiredService<SptServerStartupService>().Startup();
|
||||
@@ -147,16 +150,54 @@ public static class Program
|
||||
|
||||
app.UseMiddleware<SptLoggerMiddleware>();
|
||||
|
||||
app.Use(
|
||||
async (HttpContext context, RequestDelegate next) =>
|
||||
{
|
||||
await context.RequestServices.GetRequiredService<HttpServer>().HandleRequest(context, next);
|
||||
}
|
||||
);
|
||||
app.Use(async (context, next) => await HandleRequest(context, next));
|
||||
|
||||
app.UseSptBlazor();
|
||||
}
|
||||
|
||||
private static async Task HandleRequest(HttpContext context, RequestDelegate next)
|
||||
{
|
||||
var config = context.RequestServices.GetRequiredService<ConfigServer>().GetConfig<CoreConfig>();
|
||||
|
||||
// if no other requests are running, start the no GC region, otherwise dont start it
|
||||
if (!RequestTrackingMiddleware.OtherRequestsActive)
|
||||
{
|
||||
if (config.EnableNoGCRegions && GCSettings.LatencyMode != GCLatencyMode.NoGCRegion)
|
||||
{
|
||||
try
|
||||
{
|
||||
GC.TryStartNoGCRegion(
|
||||
1024L * 1024L * 1024L * config.NoGCRegionMaxMemoryGB,
|
||||
1024L * 1024L * 1024L * config.NoGCRegionMaxLOHMemoryGB,
|
||||
true
|
||||
);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored, we keep going
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await context.RequestServices.GetRequiredService<HttpServer>().HandleRequest(context, next);
|
||||
|
||||
// if no other requests are running, end the no GC region, otherwise dont stop it as other requests need it still
|
||||
if (!RequestTrackingMiddleware.OtherRequestsActive)
|
||||
{
|
||||
if (config.EnableNoGCRegions && GCSettings.LatencyMode == GCLatencyMode.NoGCRegion)
|
||||
{
|
||||
try
|
||||
{
|
||||
GC.EndNoGCRegion();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ignored, we dont care about handling this
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfigureKestrel(WebApplicationBuilder builder)
|
||||
{
|
||||
builder.WebHost.ConfigureKestrel(
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace SPTarkov.Server.Services;
|
||||
|
||||
public class RequestTrackingMiddleware
|
||||
{
|
||||
private static int _activeRequests;
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public static bool OtherRequestsActive
|
||||
{
|
||||
get
|
||||
{
|
||||
return _activeRequests > 1;
|
||||
}
|
||||
}
|
||||
|
||||
public RequestTrackingMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
Interlocked.Increment(ref _activeRequests);
|
||||
try
|
||||
{
|
||||
await _next(context);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Interlocked.Decrement(ref _activeRequests);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class RequestTrackingMiddlewareExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseRequestTracking(this IApplicationBuilder builder)
|
||||
{
|
||||
return builder.UseMiddleware<RequestTrackingMiddleware>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user