From 19d82928ba2c04daa814e2d1b9c0779c4952064b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Tue, 15 May 2018 11:36:47 -0700 Subject: [PATCH] Making Razor compilation cache replaceable (#7780) --- .../IViewCompilationMemoryCacheProvider.cs | 15 +++++++++++++++ .../RazorViewCompilationMemoryCacheProvider.cs | 12 ++++++++++++ .../MvcRazorMvcCoreBuilderExtensions.cs | 1 + .../Internal/RazorViewCompiler.cs | 6 ++++-- .../Internal/RazorViewCompilerProvider.cs | 4 ++++ .../Internal/RazorViewCompilerProviderTest.cs | 2 ++ .../Internal/RazorViewCompilerTest.cs | 3 ++- 7 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 src/Microsoft.AspNetCore.Mvc.Razor/Compilation/IViewCompilationMemoryCacheProvider.cs create mode 100644 src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilationMemoryCacheProvider.cs diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/IViewCompilationMemoryCacheProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/IViewCompilationMemoryCacheProvider.cs new file mode 100644 index 0000000000..5abbd550f3 --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/IViewCompilationMemoryCacheProvider.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.Caching.Memory; + +namespace Microsoft.AspNetCore.Mvc.Razor.Compilation +{ + /// + /// Provides an instance of that is used to store compiled Razor views. + /// + public interface IViewCompilationMemoryCacheProvider + { + IMemoryCache CompilationMemoryCache { get; } + } +} diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilationMemoryCacheProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilationMemoryCacheProvider.cs new file mode 100644 index 0000000000..9a11db0b3f --- /dev/null +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Compilation/RazorViewCompilationMemoryCacheProvider.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Extensions.Caching.Memory; + +namespace Microsoft.AspNetCore.Mvc.Razor.Compilation +{ + internal class RazorViewCompilationMemoryCacheProvider : IViewCompilationMemoryCacheProvider + { + IMemoryCache IViewCompilationMemoryCacheProvider.CompilationMemoryCache { get; } = new MemoryCache(new MemoryCacheOptions()); + } +} diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs index 2eb17bc862..7dddf090bd 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/DependencyInjection/MvcRazorMvcCoreBuilderExtensions.cs @@ -172,6 +172,7 @@ namespace Microsoft.Extensions.DependencyInjection return viewEngine; }); services.TryAddSingleton(); + services.TryAddSingleton(); // In the default scenario the following services are singleton by virtue of being initialized as part of // creating the singleton RazorViewEngine instance. diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompiler.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompiler.cs index 93b871cc76..1f4d30b159 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompiler.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompiler.cs @@ -34,9 +34,9 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal private readonly IFileProvider _fileProvider; private readonly RazorProjectEngine _projectEngine; private readonly Action _compilationCallback; + private readonly IMemoryCache _cache; private readonly ILogger _logger; private readonly CSharpCompiler _csharpCompiler; - private readonly IMemoryCache _cache; public RazorViewCompiler( IFileProvider fileProvider, @@ -44,6 +44,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal CSharpCompiler csharpCompiler, Action compilationCallback, IList precompiledViews, + IMemoryCache cache, ILogger logger) { if (fileProvider == null) @@ -82,11 +83,12 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal _compilationCallback = compilationCallback; _logger = logger; + _normalizedPathCache = new ConcurrentDictionary(StringComparer.Ordinal); // This is our L0 cache, and is a durable store. Views migrate into the cache as they are requested // from either the set of known precompiled views, or by being compiled. - _cache = new MemoryCache(new MemoryCacheOptions()); + _cache = cache; // We need to validate that the all of the precompiled views are unique by path (case-insenstive). // We do this because there's no good way to canonicalize paths on windows, and it will create diff --git a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompilerProvider.cs b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompilerProvider.cs index c705a88aac..4ef67017d1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompilerProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Razor/Internal/RazorViewCompilerProvider.cs @@ -18,6 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal private readonly ApplicationPartManager _applicationPartManager; private readonly IRazorViewEngineFileProviderAccessor _fileProviderAccessor; private readonly CSharpCompiler _csharpCompiler; + private readonly IViewCompilationMemoryCacheProvider _compilationMemoryCacheProvider; private readonly RazorViewEngineOptions _viewEngineOptions; private readonly ILogger _logger; private readonly Func _createCompiler; @@ -32,12 +33,14 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal IRazorViewEngineFileProviderAccessor fileProviderAccessor, CSharpCompiler csharpCompiler, IOptions viewEngineOptionsAccessor, + IViewCompilationMemoryCacheProvider compilationMemoryCacheProvider, ILoggerFactory loggerFactory) { _applicationPartManager = applicationPartManager; _razorProjectEngine = razorProjectEngine; _fileProviderAccessor = fileProviderAccessor; _csharpCompiler = csharpCompiler; + _compilationMemoryCacheProvider = compilationMemoryCacheProvider; _viewEngineOptions = viewEngineOptionsAccessor.Value; _logger = loggerFactory.CreateLogger(); @@ -74,6 +77,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal _csharpCompiler, _viewEngineOptions.CompilationCallback, feature.ViewDescriptors, + _compilationMemoryCacheProvider.CompilationMemoryCache, _logger); } } diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerProviderTest.cs index c00237b990..9b3656aaee 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerProviderTest.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.ApplicationParts; +using Microsoft.AspNetCore.Mvc.Razor.Compilation; using Microsoft.AspNetCore.Razor.Language; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Logging.Abstractions; @@ -39,6 +40,7 @@ namespace Microsoft.AspNetCore.Mvc.Razor.Internal accessor, new CSharpCompiler(referenceManager, Mock.Of()), options, + new RazorViewCompilationMemoryCacheProvider(), NullLoggerFactory.Instance); // Act & Assert diff --git a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerTest.cs b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerTest.cs index c4df0280aa..929bf63b93 100644 --- a/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Razor.Test/Internal/RazorViewCompilerTest.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Razor.Hosting; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; +using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Moq; @@ -875,7 +876,7 @@ this should fail"; Action compilationCallback, IList precompiledViews, Func compile = null) : - base(fileProvider, projectEngine, csharpCompiler, compilationCallback, precompiledViews, NullLogger.Instance) + base(fileProvider, projectEngine, csharpCompiler, compilationCallback, precompiledViews, new MemoryCache(new MemoryCacheOptions()), NullLogger.Instance) { Compile = compile; if (Compile == null)