Prevent Roslyn from loading prematurely on cold start

This commit is contained in:
YishaiGalatzer 2014-10-09 23:34:02 -07:00
parent 75a77e2d01
commit 275f63e91f
5 changed files with 67 additions and 17 deletions

View File

@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.Razor
// There shouldn't be any duplicates and if there are any the first will win. // There shouldn't be any duplicates and if there are any the first will win.
// If the result doesn't match the one on disk its going to recompile anyways. // If the result doesn't match the one on disk its going to recompile anyways.
_cache.TryAdd(fileInfo.RelativePath, cacheEntry); _cache.TryAdd(NormalizePath(fileInfo.RelativePath), cacheEntry);
} }
} }
} }
@ -68,8 +68,9 @@ namespace Microsoft.AspNet.Mvc.Razor
bool enableInstrumentation, bool enableInstrumentation,
[NotNull] Func<CompilationResult> compile) [NotNull] Func<CompilationResult> compile)
{ {
CompilerCacheEntry cacheEntry; CompilerCacheEntry cacheEntry;
if (!_cache.TryGetValue(fileInfo.RelativePath, out cacheEntry)) if (!_cache.TryGetValue(NormalizePath(fileInfo.RelativePath), out cacheEntry))
{ {
return OnCacheMiss(fileInfo, enableInstrumentation, compile); return OnCacheMiss(fileInfo, enableInstrumentation, compile);
} }
@ -114,9 +115,17 @@ namespace Microsoft.AspNet.Mvc.Razor
var result = compile(); var result = compile();
var cacheEntry = new CompilerCacheEntry(file, result.CompiledType, isInstrumented); var cacheEntry = new CompilerCacheEntry(file, result.CompiledType, isInstrumented);
_cache[file.RelativePath] = cacheEntry; _cache[NormalizePath(file.RelativePath)] = cacheEntry;
return result; return result;
} }
private string NormalizePath(string path)
{
path = path.Replace('/', '\\');
path = path.TrimStart('\\');
return path;
}
} }
} }

View File

@ -1,8 +1,10 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq; using System.Linq;
using Microsoft.AspNet.Razor; using Microsoft.AspNet.Razor;
using Microsoft.Framework.DependencyInjection;
namespace Microsoft.AspNet.Mvc.Razor namespace Microsoft.AspNet.Mvc.Razor
{ {
@ -14,15 +16,31 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </remarks> /// </remarks>
public class RazorCompilationService : IRazorCompilationService public class RazorCompilationService : IRazorCompilationService
{ {
private readonly IServiceProvider _serviceProvider;
private readonly CompilerCache _cache; private readonly CompilerCache _cache;
private readonly ICompilationService _baseCompilationService; private ICompilationService _compilationService;
private ICompilationService CompilationService
{
get
{
if (_compilationService == null)
{
_compilationService = _serviceProvider.GetService<ICompilationService>();
}
return _compilationService;
}
}
private readonly IMvcRazorHost _razorHost; private readonly IMvcRazorHost _razorHost;
public RazorCompilationService(ICompilationService compilationService, public RazorCompilationService(IServiceProvider serviceProvider,
IControllerAssemblyProvider _controllerAssemblyProvider, IControllerAssemblyProvider _controllerAssemblyProvider,
IMvcRazorHost razorHost) IMvcRazorHost razorHost)
{ {
_baseCompilationService = compilationService; _serviceProvider = serviceProvider;
_razorHost = razorHost; _razorHost = razorHost;
_cache = new CompilerCache(_controllerAssemblyProvider.CandidateAssemblies); _cache = new CompilerCache(_controllerAssemblyProvider.CandidateAssemblies);
} }
@ -50,7 +68,7 @@ namespace Microsoft.AspNet.Mvc.Razor
return CompilationResult.Failed(file.FileInfo, results.GeneratedCode, messages); return CompilationResult.Failed(file.FileInfo, results.GeneratedCode, messages);
} }
return _baseCompilationService.Compile(file.FileInfo, results.GeneratedCode); return CompilationService.Compile(file.FileInfo, results.GeneratedCode);
} }
} }
} }

View File

@ -163,7 +163,9 @@ namespace Microsoft.AspNet.Mvc.Razor
viewName, viewName,
controllerName, controllerName,
areaName); areaName);
var page = _pageFactory.CreateInstance(transformedPath, IsInstrumentationEnabled(context));
var isInstrumentated = IsInstrumentationEnabled(context);
var page = _pageFactory.CreateInstance(transformedPath, isInstrumentated);
if (page != null) if (page != null)
{ {
// 3a. We found a page. Cache the set of values that produced it and return a found result. // 3a. We found a page. Cache the set of values that produced it and return a found result.

View File

@ -12,17 +12,28 @@ namespace Microsoft.AspNet.Mvc.Razor
/// </summary> /// </summary>
public class VirtualPathRazorPageFactory : IRazorPageFactory public class VirtualPathRazorPageFactory : IRazorPageFactory
{ {
private readonly IRazorCompilationService _compilationService; private IRazorCompilationService _compilationService;
private IRazorCompilationService CompilationService
{
get
{
if (_compilationService == null)
{
_compilationService = _serviceProvider.GetService<IRazorCompilationService>();
}
return _compilationService;
}
}
private readonly ITypeActivator _activator; private readonly ITypeActivator _activator;
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IFileInfoCache _fileInfoCache; private readonly IFileInfoCache _fileInfoCache;
public VirtualPathRazorPageFactory(IRazorCompilationService compilationService, public VirtualPathRazorPageFactory(ITypeActivator typeActivator,
ITypeActivator typeActivator,
IServiceProvider serviceProvider, IServiceProvider serviceProvider,
IFileInfoCache fileInfoCache) IFileInfoCache fileInfoCache)
{ {
_compilationService = compilationService;
_activator = typeActivator; _activator = typeActivator;
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_fileInfoCache = fileInfoCache; _fileInfoCache = fileInfoCache;
@ -47,7 +58,7 @@ namespace Microsoft.AspNet.Mvc.Razor
RelativePath = relativePath, RelativePath = relativePath,
}; };
var result = _compilationService.Compile(relativeFileInfo, enableInstrumentation); var result = CompilationService.Compile(relativeFileInfo, enableInstrumentation);
var page = (IRazorPage)_activator.CreateInstance(_serviceProvider, result.CompiledType); var page = (IRazorPage)_activator.CreateInstance(_serviceProvider, result.CompiledType);
page.Path = relativePath; page.Path = relativePath;

View File

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
@ -34,10 +35,16 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
var fileInfo = new Mock<IFileInfo>(); var fileInfo = new Mock<IFileInfo>();
fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath); fileInfo.Setup(f => f.PhysicalPath).Returns(viewPath);
fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null); fileInfo.Setup(f => f.CreateReadStream()).Returns(Stream.Null);
var compiler = new Mock<ICompilationService>(); var compiler = new Mock<ICompilationService>();
compiler.Setup(c => c.Compile(fileInfo.Object, It.IsAny<string>())) compiler.Setup(c => c.Compile(fileInfo.Object, It.IsAny<string>()))
.Returns(CompilationResult.Successful(typeof(RazorCompilationServiceTest))); .Returns(CompilationResult.Successful(typeof(RazorCompilationServiceTest)));
var razorService = new RazorCompilationService(compiler.Object, ap.Object, host.Object);
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(sp => sp.GetService(It.Is<Type>(t => t == typeof(ICompilationService))))
.Returns(compiler.Object);
var razorService = new RazorCompilationService(serviceProvider.Object, ap.Object, host.Object);
var relativeFileInfo = new RelativeFileInfo() var relativeFileInfo = new RelativeFileInfo()
{ {
@ -61,8 +68,7 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
var host = new Mock<IMvcRazorHost>(); var host = new Mock<IMvcRazorHost>();
host.SetupAllProperties(); host.SetupAllProperties();
host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>())) host.Setup(h => h.GenerateCode(It.IsAny<string>(), It.IsAny<Stream>()))
.Returns(GetGeneratorResult()); .Returns(GetGeneratorResult()); var assemblyProvider = new Mock<IControllerAssemblyProvider>();
var assemblyProvider = new Mock<IControllerAssemblyProvider>();
assemblyProvider.SetupGet(e => e.CandidateAssemblies) assemblyProvider.SetupGet(e => e.CandidateAssemblies)
.Returns(Enumerable.Empty<Assembly>()); .Returns(Enumerable.Empty<Assembly>());
@ -70,7 +76,11 @@ namespace Microsoft.AspNet.Mvc.Razor.Test
compiler.Setup(c => c.Compile(It.IsAny<IFileInfo>(), It.IsAny<string>())) compiler.Setup(c => c.Compile(It.IsAny<IFileInfo>(), It.IsAny<string>()))
.Returns(CompilationResult.Successful(GetType())); .Returns(CompilationResult.Successful(GetType()));
var razorService = new RazorCompilationService(compiler.Object, assemblyProvider.Object, host.Object); var serviceProvider = new Mock<IServiceProvider>();
serviceProvider.Setup(sp => sp.GetService(It.Is<Type>(t => t == typeof(ICompilationService))))
.Returns(compiler.Object);
var razorService = new RazorCompilationService(serviceProvider.Object, assemblyProvider.Object, host.Object);
var relativeFileInfo = new RelativeFileInfo() var relativeFileInfo = new RelativeFileInfo()
{ {
FileInfo = Mock.Of<IFileInfo>(), FileInfo = Mock.Of<IFileInfo>(),