Skip to content

Commit 6cd5bc6

Browse files
authored
[PlaceholderMode]Read RuntimeAssemblyFiles (#8341)
1 parent 6119116 commit 6cd5bc6

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

src/WebJobs.Script.WebHost/Middleware/HostWarmupMiddleware.cs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.IO;
6+
using System.Linq;
67
using System.Threading;
78
using System.Threading.Tasks;
89
using Microsoft.AspNetCore.Http;
@@ -20,6 +21,7 @@ public class HostWarmupMiddleware
2021
private readonly IEnvironment _environment;
2122
private readonly IScriptHostManager _hostManager;
2223
private readonly ILogger _logger;
24+
private string _assemblyLocalPath;
2325

2426
public HostWarmupMiddleware(RequestDelegate next, IScriptWebHostEnvironment webHostEnvironment, IEnvironment environment, IScriptHostManager hostManager, ILogger<HostWarmupMiddleware> logger)
2527
{
@@ -28,6 +30,7 @@ public HostWarmupMiddleware(RequestDelegate next, IScriptWebHostEnvironment webH
2830
_environment = environment;
2931
_hostManager = hostManager;
3032
_logger = logger;
33+
_assemblyLocalPath = Path.GetDirectoryName(new Uri(typeof(HostWarmupMiddleware).Assembly.CodeBase).LocalPath);
3134
}
3235

3336
public async Task Invoke(HttpContext httpContext)
@@ -40,17 +43,58 @@ public async Task Invoke(HttpContext httpContext)
4043
PreJitPrepare(WarmUpConstants.LinuxJitTraceFileName);
4144
}
4245

46+
ReadRuntimeAssemblyFiles();
47+
4348
await WarmUp(httpContext.Request);
4449
}
4550

4651
await _next.Invoke(httpContext);
4752
}
4853

54+
internal void ReadRuntimeAssemblyFiles()
55+
{
56+
try
57+
{
58+
string[] allFiles = Directory.GetFiles(_assemblyLocalPath, "*.dll", SearchOption.TopDirectoryOnly);
59+
foreach (string file in allFiles)
60+
{
61+
// Read file content to avoid disk reads during specialization. This is only to page-in bytes.
62+
ReadFileInChunks(file);
63+
}
64+
_logger.LogDebug(new EventId(100, nameof(ReadRuntimeAssemblyFiles)), $"Number of files read: {allFiles.Count()}.");
65+
}
66+
catch (Exception ex)
67+
{
68+
_logger.LogDebug(new EventId(100, nameof(ReadRuntimeAssemblyFiles)), ex, "Reading ReadRuntimeAssemblyFiles failed");
69+
}
70+
}
71+
72+
private void ReadFileInChunks(string file)
73+
{
74+
try
75+
{
76+
// Read File content in 4K chunks
77+
const int MAX_BUFFER = 4 * 1024;
78+
byte[] chunk = new byte[MAX_BUFFER];
79+
int bytesRead;
80+
using (FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read))
81+
{
82+
while ((bytesRead = fileStream.Read(chunk, 0, MAX_BUFFER)) != 0)
83+
{
84+
}
85+
}
86+
}
87+
catch (Exception ex)
88+
{
89+
_logger.LogDebug(new EventId(100, nameof(ReadFileInChunks)), ex, $"Reading file '{file}' failed");
90+
}
91+
}
92+
4993
private void PreJitPrepare(string jitTraceFileName)
5094
{
5195
// This is to PreJIT all methods captured in coldstart.jittrace file to improve cold start time
5296
var path = Path.Combine(
53-
Path.GetDirectoryName(new Uri(typeof(HostWarmupMiddleware).Assembly.CodeBase).LocalPath),
97+
_assemblyLocalPath,
5498
WarmUpConstants.PreJitFolderName, jitTraceFileName);
5599

56100
var file = new FileInfo(path);

test/WebJobs.Script.Tests/Middleware/HostWarmupMiddlewareTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Linq;
6+
using Microsoft.AspNetCore.Hosting;
57
using Microsoft.Azure.WebJobs.Script.WebHost;
8+
using Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.Extensions;
69
using Microsoft.Azure.WebJobs.Script.WebHost.Middleware;
10+
using Microsoft.Extensions.Logging;
711
using Microsoft.WebJobs.Script.Tests;
812
using Moq;
913
using Xunit;
@@ -53,5 +57,21 @@ public void IsWarmUpRequest_ReturnsExpectedValue()
5357
Assert.True(environment.IsLinuxConsumption());
5458
Assert.True(HostWarmupMiddleware.IsWarmUpRequest(request, hostEnvironment.InStandbyMode, environment));
5559
}
60+
61+
[Fact]
62+
public void ReadRuntimeAssemblyFiles_VerifyLogs()
63+
{
64+
var environment = new TestEnvironment();
65+
var hostEnvironment = new ScriptWebHostEnvironment(environment);
66+
var testLoggerFactory = new LoggerFactory();
67+
TestLoggerProvider testLoggerProvider = new TestLoggerProvider();
68+
testLoggerFactory.AddProvider(testLoggerProvider);
69+
ILogger<HostWarmupMiddleware> testLogger = testLoggerFactory.CreateLogger<HostWarmupMiddleware>();
70+
HostWarmupMiddleware hostWarmupMiddleware = new HostWarmupMiddleware(null, new Mock<IScriptWebHostEnvironment>().Object, environment, new Mock<IScriptHostManager>().Object, testLogger);
71+
hostWarmupMiddleware.ReadRuntimeAssemblyFiles();
72+
// Assert
73+
var traces = testLoggerProvider.GetAllLogMessages();
74+
Assert.True(traces.Any(m => m.FormattedMessage.Contains("Number of files read:")));
75+
}
5676
}
5777
}

0 commit comments

Comments
 (0)