Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ These settings are common across all plugins, although different implementations
| `$(MSBuildCacheMaxConcurrentCacheContentOperations)` | `int` | 64 | The maximum number of cache operations to perform concurrently |
| `$(MSBuildCacheLocalCacheRootPath)` | `string` | "\MSBuildCache" (in repo's drive root) | Base directory to use for the local cache. |
| `$(MSBuildCacheLocalCacheSizeInMegabytes)` | `int` | 102400 (100 GB) | The maximum size in megabytes of the local cache |
| `$(ForceCacheMissPercentage)` | `int` | 0 | Force a cache miss a percentage of the time. Useful for testing to simulate natural cache misses. |
| `$(MSBuildCacheIgnoredInputPatterns)` | `Glob[]` | | Files which are part of the repo which should be ignored for cache invalidation |
| `$(MSBuildCacheIgnoredOutputPatterns)` | `Glob[]` | `*.assets.cache; *assemblyreference.cache` | Files to ignore for output collection into the cache. Note that if output are ignored, the replayed cache entry will not have these files. This should be used for intermediate outputs which are not properly portable |
| `$(MSBuildCacheIdenticalDuplicateOutputPatterns)` | `Glob[]` | | Files to allow duplicate outputs, with identical content, across projects. Projects which produce files at the same path with differing content will still produce an error. Note: this setting should be used sparingly as it impacts performance |
Expand Down
7 changes: 7 additions & 0 deletions src/Common.Tests/PluginSettingsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ public void LocalCacheSizeInMegabytesSetting()
pluginSettings => pluginSettings.LocalCacheSizeInMegabytes,
new[] { 123u, 456u, 789u });

[TestMethod]
public void ForceCacheMissPercentageSetting()
=> TestBasicSetting(
nameof(PluginSettings.ForceCacheMissPercentage),
pluginSettings => pluginSettings.ForceCacheMissPercentage,
new[] { 0u, 10u, 100u });

private static IEnumerable<object[]> GlobTestData
{
get
Expand Down
24 changes: 23 additions & 1 deletion src/Common/MSBuildCachePluginBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
Expand Down Expand Up @@ -105,7 +106,8 @@ static MSBuildCachePluginBase() =>
nameof(_fileAccessRepository),
nameof(_cacheClient),
nameof(_ignoredOutputPatterns),
nameof(_identicalDuplicateOutputPatterns)
nameof(_identicalDuplicateOutputPatterns),
nameof(Settings)
)]
protected bool Initialized { get; private set; }

Expand Down Expand Up @@ -350,6 +352,26 @@ private async Task<CacheResult> GetCacheResultInnerAsync(BuildRequestData buildR
return CacheResult.IndicateNonCacheHit(CacheResultType.CacheMiss);
}

if (Settings.ForceCacheMissPercentage != 0)
{
// use a hash of the project id so that it is repeatable

#if NETFRAMEWORK
using SHA256 hasher = SHA256.Create();
byte[] projectHash = hasher.ComputeHash(Encoding.UTF8.GetBytes(nodeContext.Id));
#else
byte[] projectHash = SHA256.HashData(Encoding.UTF8.GetBytes(nodeContext.Id));
#endif

uint hashInt = BitConverter.ToUInt32(projectHash, 0);
if ((hashInt % 100) < Settings.ForceCacheMissPercentage)
{
logger.LogMessage($"Forcing an otherwise 'cache hit' to be a 'cache miss' because of ForceCacheMissPercentage.");
Interlocked.Increment(ref _cacheMissCount);
return CacheResult.IndicateNonCacheHit(CacheResultType.CacheMiss);
}
}

CheckForDuplicateOutputs(logger, nodeBuildResult.Outputs, nodeContext);

await FinishNodeAsync(logger, nodeContext, pathSet, nodeBuildResult);
Expand Down
2 changes: 2 additions & 0 deletions src/Common/PluginSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ public string LocalCacheRootPath

public uint LocalCacheSizeInMegabytes { get; init; } = 102400; // 100GB

public uint ForceCacheMissPercentage { get; init; }

public IReadOnlyCollection<Glob> IgnoredInputPatterns { get; init; } = Array.Empty<Glob>();

public IReadOnlyCollection<Glob> IgnoredOutputPatterns { get; init; } = Array.Empty<Glob>();
Expand Down
2 changes: 2 additions & 0 deletions src/Common/build/Microsoft.MSBuildCache.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<MSBuildCacheGlobalPropertiesToIgnore>$(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheMaxConcurrentCacheContentOperations</MSBuildCacheGlobalPropertiesToIgnore>
<MSBuildCacheGlobalPropertiesToIgnore>$(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheLocalCacheRootPath</MSBuildCacheGlobalPropertiesToIgnore>
<MSBuildCacheGlobalPropertiesToIgnore>$(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheLocalCacheSizeInMegabytes</MSBuildCacheGlobalPropertiesToIgnore>
<MSBuildCacheGlobalPropertiesToIgnore>$(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheForceCacheMissPercentage</MSBuildCacheGlobalPropertiesToIgnore>
<MSBuildCacheGlobalPropertiesToIgnore>$(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheIgnoredInputPatterns</MSBuildCacheGlobalPropertiesToIgnore>
<MSBuildCacheGlobalPropertiesToIgnore>$(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheIgnoredOutputPatterns</MSBuildCacheGlobalPropertiesToIgnore>
<MSBuildCacheGlobalPropertiesToIgnore>$(MSBuildCacheGlobalPropertiesToIgnore);MSBuildCacheIdenticalDuplicateOutputPatterns</MSBuildCacheGlobalPropertiesToIgnore>
Expand All @@ -29,6 +30,7 @@
<MaxConcurrentCacheContentOperations>$(MSBuildCacheMaxConcurrentCacheContentOperations)</MaxConcurrentCacheContentOperations>
<LocalCacheRootPath>$(MSBuildCacheLocalCacheRootPath)</LocalCacheRootPath>
<LocalCacheSizeInMegabytes>$(MSBuildCacheLocalCacheSizeInMegabytes)</LocalCacheSizeInMegabytes>
<ForceCacheMissPercentage>$(MSBuildCacheForceCacheMissPercentage)</ForceCacheMissPercentage>
<IgnoredInputPatterns>$(MSBuildCacheIgnoredInputPatterns)</IgnoredInputPatterns>
<IgnoredOutputPatterns>$(MSBuildCacheIgnoredOutputPatterns)</IgnoredOutputPatterns>
<IdenticalDuplicateOutputPatterns>$(MSBuildCacheIdenticalDuplicateOutputPatterns)</IdenticalDuplicateOutputPatterns>
Expand Down
1 change: 0 additions & 1 deletion src/Local/MSBuildCacheLocalPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ protected override async Task<ICacheClient> CreateCacheClientAsync(PluginLoggerB
#pragma warning restore CA2000 // Dispose objects before losing scope
Context context = new(cacheLogger);


#pragma warning disable CA2000 // Dispose objects before losing scope. Expected to be disposed by TwoLevelCache
LocalCache cache = LocalCacheFactory.Create(cacheLogger, Settings.LocalCacheRootPath, Settings.LocalCacheSizeInMegabytes);
#pragma warning restore CA2000 // Dispose objects before losing scope
Expand Down