@@ -46,9 +46,10 @@ public InstanceManager(IOptionsFactory<ScriptApplicationHostOptions> optionsFact
4646 _optionsFactory = optionsFactory ?? throw new ArgumentNullException ( nameof ( optionsFactory ) ) ;
4747 }
4848
49- public async Task < string > SpecializeMSISidecar ( HostAssignmentContext context , bool isWarmup )
49+ public async Task < string > SpecializeMSISidecar ( HostAssignmentContext context )
5050 {
51- if ( isWarmup )
51+ // No cold start optimization needed for side car scenarios
52+ if ( context . IsWarmupRequest )
5253 {
5354 return null ;
5455 }
@@ -89,16 +90,19 @@ public async Task<string> SpecializeMSISidecar(HostAssignmentContext context, bo
8990 return null ;
9091 }
9192
92- public bool StartAssignment ( HostAssignmentContext context , bool isWarmup )
93+ public bool StartAssignment ( HostAssignmentContext context )
9394 {
9495 if ( ! _webHostEnvironment . InStandbyMode )
9596 {
9697 _logger . LogError ( "Assign called while host is not in placeholder mode" ) ;
9798 return false ;
9899 }
99100
100- if ( isWarmup )
101+ if ( context . IsWarmupRequest )
101102 {
103+ // Based on profiling download code jit-ing holds up cold start.
104+ // Pre-jit to avoid paying the cost later.
105+ Task . Run ( async ( ) => await Download ( context . GetRunFromPkgContext ( ) ) ) ;
102106 return true ;
103107 }
104108 else if ( _assignmentContext == null )
@@ -134,16 +138,11 @@ public bool StartAssignment(HostAssignmentContext context, bool isWarmup)
134138 }
135139 }
136140
137- public async Task < string > ValidateContext ( HostAssignmentContext assignmentContext , bool isWarmup )
141+ public async Task < string > ValidateContext ( HostAssignmentContext assignmentContext )
138142 {
139- if ( isWarmup )
140- {
141- return null ;
142- }
143-
144- _logger . LogInformation ( $ "Validating host assignment context (SiteId: { assignmentContext . SiteId } , SiteName: '{ assignmentContext . SiteName } ')") ;
143+ _logger . LogInformation ( $ "Validating host assignment context (SiteId: { assignmentContext . SiteId } , SiteName: '{ assignmentContext . SiteName } '. IsWarmup: '{ assignmentContext . IsWarmupRequest } ')") ;
145144 RunFromPackageContext pkgContext = assignmentContext . GetRunFromPkgContext ( ) ;
146- _logger . LogInformation ( $ "Will be using { pkgContext . EnvironmentVariableName } app setting as zip url") ;
145+ _logger . LogInformation ( $ "Will be using { pkgContext . EnvironmentVariableName } app setting as zip url. IsWarmup: ' { assignmentContext . IsWarmupRequest } ') ") ;
147146
148147 if ( pkgContext . IsScmRunFromPackage ( ) )
149148 {
@@ -154,7 +153,7 @@ public async Task<string> ValidateContext(HostAssignmentContext assignmentContex
154153 {
155154 // In AppService, ZipUrl == 1 means the package is hosted in azure files.
156155 // Otherwise we expect zipUrl to be a blobUri to a zip or a squashfs image
157- ( var error , var contentLength ) = await ValidateBlobPackageContext ( pkgContext . Url ) ;
156+ ( var error , var contentLength ) = await ValidateBlobPackageContext ( pkgContext ) ;
158157 if ( string . IsNullOrEmpty ( error ) )
159158 {
160159 assignmentContext . PackageContentLength = contentLength ;
@@ -172,8 +171,12 @@ public async Task<string> ValidateContext(HostAssignmentContext assignmentContex
172171 }
173172 }
174173
175- private async Task < ( string , long ? ) > ValidateBlobPackageContext ( string blobUri )
174+ private async Task < ( string , long ? ) > ValidateBlobPackageContext ( RunFromPackageContext context )
176175 {
176+ string blobUri = context . Url ;
177+ string eventName = context . IsWarmUpRequest
178+ ? MetricEventNames . LinuxContainerSpecializationZipHeadWarmup
179+ : MetricEventNames . LinuxContainerSpecializationZipHead ;
177180 string error = null ;
178181 HttpResponseMessage response = null ;
179182 long ? contentLength = null ;
@@ -186,7 +189,7 @@ await Utility.InvokeWithRetriesAsync(async () =>
186189 {
187190 try
188191 {
189- using ( _metricsLogger . LatencyEvent ( MetricEventNames . LinuxContainerSpecializationZipHead ) )
192+ using ( _metricsLogger . LatencyEvent ( eventName ) )
190193 {
191194 var request = new HttpRequestMessage ( HttpMethod . Head , blobUri ) ;
192195 response = await _client . SendAsync ( request ) ;
@@ -199,7 +202,7 @@ await Utility.InvokeWithRetriesAsync(async () =>
199202 }
200203 catch ( Exception e )
201204 {
202- _logger . LogError ( e , $ "{ MetricEventNames . LinuxContainerSpecializationZipHead } failed") ;
205+ _logger . LogError ( e , $ "{ eventName } failed") ;
203206 throw ;
204207 }
205208 } , maxRetries : 2 , retryInterval : TimeSpan . FromSeconds ( 0.3 ) ) ; // Keep this less than ~1s total
@@ -208,7 +211,7 @@ await Utility.InvokeWithRetriesAsync(async () =>
208211 catch ( Exception e )
209212 {
210213 error = $ "Invalid zip url specified (StatusCode: { response ? . StatusCode } )";
211- _logger . LogError ( e , "ValidateContext failed" ) ;
214+ _logger . LogError ( e , $ "ValidateContext failed. IsWarmupRequest = { context . IsWarmUpRequest } ") ;
212215 }
213216
214217 return ( error , contentLength ) ;
@@ -372,25 +375,28 @@ private async Task<string> Download(RunFromPackageContext pkgContext)
372375 if ( pkgContext . PackageContentLength != null && pkgContext . PackageContentLength > 100 * 1024 * 1024 )
373376 {
374377 _logger . LogInformation ( $ "Downloading zip contents from '{ cleanedUrl } ' using aria2c'") ;
375- AriaDownload ( tmpPath , fileName , zipUri ) ;
378+ AriaDownload ( tmpPath , fileName , zipUri , pkgContext . IsWarmUpRequest ) ;
376379 }
377380 else
378381 {
379382 _logger . LogInformation ( $ "Downloading zip contents from '{ cleanedUrl } ' using httpclient'") ;
380- await HttpClientDownload ( filePath , zipUri ) ;
383+ await HttpClientDownload ( filePath , zipUri , pkgContext . IsWarmUpRequest ) ;
381384 }
382385
383386 return filePath ;
384387 }
385388
386- private async Task HttpClientDownload ( string filePath , Uri zipUri )
389+ private async Task HttpClientDownload ( string filePath , Uri zipUri , bool isWarmupRequest )
387390 {
388391 HttpResponseMessage response = null ;
389392 await Utility . InvokeWithRetriesAsync ( async ( ) =>
390393 {
391394 try
392395 {
393- using ( _metricsLogger . LatencyEvent ( MetricEventNames . LinuxContainerSpecializationZipDownload ) )
396+ var downloadMetricName = isWarmupRequest
397+ ? MetricEventNames . LinuxContainerSpecializationZipDownloadWarmup
398+ : MetricEventNames . LinuxContainerSpecializationZipDownload ;
399+ using ( _metricsLogger . LatencyEvent ( downloadMetricName ) )
394400 {
395401 var request = new HttpRequestMessage ( HttpMethod . Get , zipUri ) ;
396402 response = await _client . SendAsync ( request , HttpCompletionOption . ResponseHeadersRead ) ;
@@ -403,31 +409,36 @@ await Utility.InvokeWithRetriesAsync(async () =>
403409 _logger . LogError ( e , error ) ;
404410 throw ;
405411 }
406- _logger . LogInformation ( $ "{ response . Content . Headers . ContentLength } bytes downloaded") ;
412+ _logger . LogInformation ( $ "{ response . Content . Headers . ContentLength } bytes downloaded. IsWarmupRequest = { isWarmupRequest } ") ;
407413 } , 2 , TimeSpan . FromSeconds ( 0.5 ) ) ;
408414
409- using ( _metricsLogger . LatencyEvent ( MetricEventNames . LinuxContainerSpecializationZipWrite ) )
415+ using ( _metricsLogger . LatencyEvent ( isWarmupRequest ? MetricEventNames . LinuxContainerSpecializationZipWriteWarmup : MetricEventNames . LinuxContainerSpecializationZipWrite ) )
410416 {
411417 using ( var content = await response . Content . ReadAsStreamAsync ( ) )
412418 using ( var stream = new FileStream ( filePath , FileMode . Create , FileAccess . Write , FileShare . None , bufferSize : 4096 , useAsync : true ) )
413419 {
414420 await content . CopyToAsync ( stream ) ;
415421 }
416- _logger . LogInformation ( $ "{ response . Content . Headers . ContentLength } bytes written") ;
422+ _logger . LogInformation ( $ "{ response . Content . Headers . ContentLength } bytes written. IsWarmupRequest = { isWarmupRequest } ") ;
417423 }
418424 }
419425
420- private void AriaDownload ( string directory , string fileName , Uri zipUri )
426+ private void AriaDownload ( string directory , string fileName , Uri zipUri , bool isWarmupRequest )
421427 {
422- ( string stdout , string stderr , int exitCode ) = RunBashCommand ( $ "aria2c --allow-overwrite -x12 -d { directory } -o { fileName } '{ zipUri } '", MetricEventNames . LinuxContainerSpecializationZipDownload ) ;
428+ var metricName = isWarmupRequest
429+ ? MetricEventNames . LinuxContainerSpecializationZipDownloadWarmup
430+ : MetricEventNames . LinuxContainerSpecializationZipDownload ;
431+ ( string stdout , string stderr , int exitCode ) = RunBashCommand (
432+ $ "aria2c --allow-overwrite -x12 -d { directory } -o { fileName } '{ zipUri } '",
433+ metricName ) ;
423434 if ( exitCode != 0 )
424435 {
425436 var msg = $ "Error downloading package. stdout: { stdout } , stderr: { stderr } , exitCode: { exitCode } ";
426437 _logger . LogError ( msg ) ;
427438 throw new InvalidOperationException ( msg ) ;
428439 }
429440 var fileInfo = FileUtility . FileInfoFromFileName ( Path . Combine ( directory , fileName ) ) ;
430- _logger . LogInformation ( $ "{ fileInfo . Length } bytes downloaded") ;
441+ _logger . LogInformation ( $ "{ fileInfo . Length } bytes downloaded. IsWarmupRequest = { isWarmupRequest } ") ;
431442 }
432443
433444 private async Task UnpackPackage ( string filePath , string scriptPath , RunFromPackageContext pkgContext )
0 commit comments