Skip to content

Commit 62f8d8a

Browse files
authored
Optimizing ReadLanguageWorkerFile to avoid LOH allocations by reading files in chunks (#11069)
* Optimizing ReadLanguageWorkerFile to avoid LOH allocations by reading in chunks. * release notes.
1 parent e5bb938 commit 62f8d8a

File tree

2 files changed

+38
-5
lines changed

2 files changed

+38
-5
lines changed

release_notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
- Fix invocation timeout when incoming request contains "x-ms-invocation-id" header (#10980)
88
- Warn if .azurefunctions folder does not exist (#10967)
99
- Memory allocation & CPU optimizations in `GrpcMessageExtensionUtilities.ConvertFromHttpMessageToExpando` (#11054)
10+
- Memory allocation optimizations in `ReadLanguageWorkerFile` by reading files in buffered chunks, preventing LOH allocations (#11069)

src/WebJobs.Script/Workers/Rpc/Configuration/RpcWorkerConfigFactory.cs

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

44
using System;
5+
using System.Buffers;
56
using System.Collections.Generic;
67
using System.IO;
78
using System.Linq;
89
using System.Text.Json;
910
using System.Text.RegularExpressions;
11+
using System.Threading.Tasks;
1012
using Microsoft.Azure.WebJobs.Script.Diagnostics;
1113
using Microsoft.Azure.WebJobs.Script.Workers.Profiles;
1214
using Microsoft.Extensions.Configuration;
@@ -357,13 +359,43 @@ internal bool ShouldAddWorkerConfig(string workerDescriptionLanguage)
357359

358360
private void ReadLanguageWorkerFile(string workerPath)
359361
{
360-
if (_environment.IsPlaceholderModeEnabled()
361-
&& !string.IsNullOrEmpty(_workerRuntime)
362-
&& File.Exists(workerPath))
362+
if (!_environment.IsPlaceholderModeEnabled()
363+
|| string.IsNullOrWhiteSpace(_workerRuntime)
364+
|| !File.Exists(workerPath))
363365
{
364-
// Read language worker file to avoid disk reads during specialization. This is only to page-in bytes.
365-
File.ReadAllBytes(workerPath);
366+
return;
366367
}
368+
369+
// Reads the file to warm up the operating system's file cache. Can run in the background.
370+
_ = Task.Run(() =>
371+
{
372+
const int bufferSize = 4096;
373+
var buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
374+
375+
try
376+
{
377+
using var fs = new FileStream(
378+
workerPath,
379+
FileMode.Open,
380+
FileAccess.Read,
381+
FileShare.Read,
382+
bufferSize,
383+
FileOptions.SequentialScan);
384+
385+
while (fs.Read(buffer, 0, bufferSize) > 0)
386+
{
387+
// Do nothing. The goal is to read the file into the OS cache.
388+
}
389+
}
390+
catch (Exception ex)
391+
{
392+
_logger.LogError(ex, "Unexpected error warming up worker file: {filePath}", workerPath);
393+
}
394+
finally
395+
{
396+
ArrayPool<byte>.Shared.Return(buffer);
397+
}
398+
});
367399
}
368400
}
369401
}

0 commit comments

Comments
 (0)