From 7fcc127a84ccfbe43d7c7e3ba9e786a33e29676b Mon Sep 17 00:00:00 2001 From: David Fowler Date: Tue, 16 Jun 2020 18:42:46 -0700 Subject: [PATCH] Use sync IO when the physical path is available (#37846) * Use sync IO when the physical path is available - This should remove the overhead of doing async io for the synchronous configuration system --- .../src/FileConfigurationProvider.cs | 38 +++++++++++++++++----- .../tests/Common/TestStreamHelpers.cs | 6 ++-- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs index d136114..f8b62b3 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.FileExtensions/src/FileConfigurationProvider.cs @@ -8,6 +8,7 @@ using System.IO; using System.Runtime.ExceptionServices; using System.Text; using System.Threading; +using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Primitives; namespace Microsoft.Extensions.Configuration @@ -35,7 +36,8 @@ namespace Microsoft.Extensions.Configuration { _changeTokenRegistration = ChangeToken.OnChange( () => Source.FileProvider.Watch(Source.Path), - () => { + () => + { Thread.Sleep(Source.ReloadDelay); Load(reload: true); }); @@ -46,7 +48,7 @@ namespace Microsoft.Extensions.Configuration /// The source settings for this provider. /// public FileConfigurationSource Source { get; } - + /// /// Generates a string representing this provider name and relevant details. /// @@ -80,16 +82,34 @@ namespace Microsoft.Extensions.Configuration { Data = new Dictionary(StringComparer.OrdinalIgnoreCase); } - using (var stream = file.CreateReadStream()) + + static Stream OpenRead(IFileInfo fileInfo) { - try + if (fileInfo.PhysicalPath != null) { - Load(stream); - } - catch (Exception e) - { - HandleException(ExceptionDispatchInfo.Capture(e)); + // The default physical file info assumes asynchronous IO which results in unnecessary overhead + // especally since the configuration system is synchronous. This uses the same settings + // and disables async IO. + return new FileStream( + fileInfo.PhysicalPath, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite, + bufferSize: 1, + FileOptions.SequentialScan); } + + return fileInfo.CreateReadStream(); + } + + using Stream stream = OpenRead(file); + try + { + Load(stream); + } + catch (Exception e) + { + HandleException(ExceptionDispatchInfo.Capture(e)); } } // REVIEW: Should we raise this in the base as well / instead? diff --git a/src/libraries/Microsoft.Extensions.Configuration/tests/Common/TestStreamHelpers.cs b/src/libraries/Microsoft.Extensions.Configuration/tests/Common/TestStreamHelpers.cs index 8af3930..28eca52 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/tests/Common/TestStreamHelpers.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/tests/Common/TestStreamHelpers.cs @@ -56,7 +56,7 @@ namespace Microsoft.Extensions.Configuration.Test { get { - throw new NotImplementedException(); + return 0; } } @@ -64,7 +64,7 @@ namespace Microsoft.Extensions.Configuration.Test { get { - throw new NotImplementedException(); + return null; } } @@ -72,7 +72,7 @@ namespace Microsoft.Extensions.Configuration.Test { get { - throw new NotImplementedException(); + return null; } } -- 2.7.4