private static ProcessMemoryCounters Merge(ProcessMemoryCounters oldData, ProcessMemoryCounters newData) { return(ProcessMemoryCounters.CreateFromMb( (int)GetMergeResult((uint)oldData.PeakVirtualMemoryUsageMb, (uint)newData.PeakVirtualMemoryUsageMb), (int)GetMergeResult((uint)oldData.PeakWorkingSetMb, (uint)newData.PeakWorkingSetMb), (int)GetMergeResult((uint)oldData.PeakCommitUsageMb, (uint)newData.PeakCommitUsageMb))); }
/// <summary> /// Gets the estimated memory counters for the process /// </summary> public ProcessMemoryCounters GetExpectedMemoryCounters(ProcessRunnablePip runnableProcess) { if (TotalRamMb == null || TotalCommitMb == null) { return(ProcessMemoryCounters.CreateFromMb(0, 0, 0, 0)); } if (runnableProcess.ExpectedMemoryCounters.HasValue) { // If there is already an expected memory counters for the process, // it means that we retry the process with another worker due to // several reasons including stopped worker, memory exhaustion. // That's why, we should reuse the expected memory counters that // are updated with recent data from last execution. return(runnableProcess.ExpectedMemoryCounters.Value); } // If there is a historic perf data, use it. if (runnableProcess.HistoricPerfData != null) { return(runnableProcess.HistoricPerfData.Value.MemoryCounters); } // If there is no historic perf data, use the defaults for the worker. return(ProcessMemoryCounters.CreateFromMb( peakWorkingSetMb: DefaultWorkingSetMbPerProcess, averageWorkingSetMb: DefaultWorkingSetMbPerProcess, peakCommitSizeMb: DefaultCommitSizeMbPerProcess, averageCommitSizeMb: DefaultCommitSizeMbPerProcess)); }
/// <summary> /// Gets the estimated memory counters for the process /// </summary> public ProcessMemoryCounters GetExpectedMemoryCounters(ProcessRunnablePip runnableProcess, bool isCancelledDueToResourceExhaustion = false) { if (TotalRamMb == null || TotalCommitMb == null) { return(ProcessMemoryCounters.CreateFromMb(0, 0, 0)); } if (runnableProcess.ExpectedMemoryCounters == null) { return(ProcessMemoryCounters.CreateFromMb( peakVirtualMemoryUsageMb: DefaultMemoryUsageMbPerProcess, peakWorkingSetMb: DefaultMemoryUsageMbPerProcess, peakCommitUsageMb: DefaultCommitUsageMbPerProcess)); } var expectedMemoryCounters = runnableProcess.ExpectedMemoryCounters.Value; // If the process is cancelled due to resource exhaustion, multiply the memory usage by 1.25; otherwise use the historic memory. double multiplier = isCancelledDueToResourceExhaustion ? 1.25 : 1; return(ProcessMemoryCounters.CreateFromMb( peakVirtualMemoryUsageMb: (int)(expectedMemoryCounters.PeakVirtualMemoryUsageMb * multiplier), peakWorkingSetMb: (int)(expectedMemoryCounters.PeakWorkingSetMb * multiplier), peakCommitUsageMb: (int)(expectedMemoryCounters.PeakCommitUsageMb * multiplier))); }
private ProcessPipHistoricPerfData(byte timeToLive, uint durationInMs, ProcessMemoryCounters memoryCounters, ushort processorsInPercents, uint diskIOInKB) { m_entryTimeToLive = timeToLive; DurationInMs = durationInMs; MemoryCounters = memoryCounters; ProcessorsInPercents = processorsInPercents; DiskIOInKB = diskIOInKB; }
public void EverythingAsync() { const int MaxExecTime = 24 * 3600 * 1000; var stream = new MemoryStream(); var r = new Random(0); for (int i = 0; i < 10; i++) { int seed = r.Next(100 * 1000); HistoricPerfDataTable table = new HistoricPerfDataTable(LoggingContext); XAssert.IsTrue(table.Count == 0); var s = new Random(seed); var buffer = new byte[sizeof(long)]; for (int j = 0; j < 10; j++) { s.NextBytes(buffer); long semiStableHash = BitConverter.ToInt64(buffer, 0); var execTime = (uint)s.Next(MaxExecTime); var processPipExecutionPerformance = new ProcessPipExecutionPerformance( PipExecutionLevel.Executed, DateTime.UtcNow, DateTime.UtcNow.AddMilliseconds(execTime), FingerprintUtilities.ZeroFingerprint, TimeSpan.FromMilliseconds(execTime), default(FileMonitoringViolationCounters), default(IOCounters), TimeSpan.FromMilliseconds(execTime), TimeSpan.FromMilliseconds(execTime / 2), ProcessMemoryCounters.CreateFromMb(1024, 1024, 1024, 1024), 1, workerId: 0, suspendedDurationMs: 0); ProcessPipHistoricPerfData runTimeData = new ProcessPipHistoricPerfData(processPipExecutionPerformance, execTime); table[semiStableHash] = runTimeData; } XAssert.IsTrue(table.Count == 10); stream.Position = 0; table.Save(stream); stream.Position = 0; table = HistoricPerfDataTable.Load(LoggingContext, stream); XAssert.IsTrue(table.Count == 10); s = new Random(seed); for (int j = 0; j < 10; j++) { s.NextBytes(buffer); long semiStableHash = BitConverter.ToInt64(buffer, 0); XAssert.IsTrue(table[semiStableHash].ExeDurationInMs >= (uint)s.Next(MaxExecTime)); } } }
private ProcessPipHistoricPerfData(byte timeToLive, uint exeDurationInMs, uint maxExeDurationInMs, uint runDurationInMs, ProcessMemoryCounters memoryCounters, ushort processorsInPercents, uint diskIOInMB) { m_entryTimeToLive = timeToLive; ExeDurationInMs = exeDurationInMs; MaxExeDurationInMs = maxExeDurationInMs; RunDurationInMs = runDurationInMs; MemoryCounters = memoryCounters; ProcessorsInPercents = processorsInPercents; DiskIOInMB = diskIOInMB; }
private static ulong GetWorkingSetSize(IntPtr processHandle) { // ReSharper disable once InlineOutVariableDeclaration var memoryCounters = new ProcessMemoryCounters() { Cb = (uint)Marshal.SizeOf(typeof(ProcessMemoryCounters)) }; return(GetProcessMemoryInfo(processHandle, out memoryCounters, memoryCounters.Cb) ? memoryCounters.WorkingSetSize : 0); }
private static ulong GetWorkingSetSize(IntPtr processHandle) { var memoryCounters = new ProcessMemoryCounters { Cb = (uint)Marshal.SizeOf <ProcessMemoryCounters>() }; return(GetProcessMemoryInfo(processHandle, out memoryCounters, memoryCounters.Cb) ? memoryCounters.WorkingSetSize : 0); }
/// <summary> /// Construct a new runtime data based on collected performance data /// </summary> public PipHistoricPerfData(ProcessPipExecutionPerformance executionPerformance) { Contract.Requires(executionPerformance.ExecutionLevel == PipExecutionLevel.Executed); m_entryTimeToLive = DefaultTimeToLive; DurationInMs = (uint)Math.Min(uint.MaxValue, Math.Max(1, executionPerformance.ProcessExecutionTime.TotalMilliseconds)); // For historical ram usage, we record the peak working set instead of the virtual memory due to the precision. MemoryCounters = executionPerformance.MemoryCounters; DiskIOInKB = (uint)Math.Min(uint.MaxValue, executionPerformance.IO.GetAggregateIO().TransferCount / 1024); ProcessorsInPercents = executionPerformance.ProcessorsInPercents; }
public long GetPeakMemory() { var pmc = new ProcessMemoryCounters(); pmc.cb = Marshal.SizeOf <ProcessMemoryCounters>(); if (!Psapi.GetProcessMemoryInfo(proc, ref pmc, pmc.cb)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return((long)pmc.PeakWorkingSetSize); }
// <inheritdoc /> internal override JobObject.AccountingInformation GetJobAccountingInfo() { if (m_processResourceUsage is null) { return(base.GetJobAccountingInfo()); } else { IOCounters ioCounters; ProcessMemoryCounters memoryCounters; uint childProcesses = 0; try { ioCounters = new IOCounters(new IO_COUNTERS() { ReadOperationCount = m_processResourceUsage.Aggregate(0UL, (acc, usage) => acc + usage.Value.DiskReadOps), ReadTransferCount = m_processResourceUsage.Aggregate(0UL, (acc, usage) => acc + usage.Value.DiskBytesRead), WriteOperationCount = m_processResourceUsage.Aggregate(0UL, (acc, usage) => acc + usage.Value.DiskWriteOps), WriteTransferCount = m_processResourceUsage.Aggregate(0UL, (acc, usage) => acc + usage.Value.DiskBytesWritten), }); memoryCounters = ProcessMemoryCounters.CreateFromBytes( m_processResourceUsage.Aggregate(0UL, (acc, usage) => acc + usage.Value.PeakWorkingSetSize), m_processResourceUsage.Aggregate(0UL, (acc, usage) => acc + usage.Value.WorkingSetSize), 0, 0); childProcesses = m_processResourceUsage.Keys.Count > 0 ? (uint)(m_processResourceUsage.Keys.Count - 1) : 0; // Exclude the root process from the child count } catch (OverflowException ex) { LogProcessState($"Overflow exception caught while calculating AccountingInformation:{Environment.NewLine}{ex.ToString()}"); ioCounters = new IOCounters(new IO_COUNTERS() { ReadOperationCount = 0, WriteOperationCount = 0, ReadTransferCount = 0, WriteTransferCount = 0 }); memoryCounters = ProcessMemoryCounters.CreateFromBytes(0, 0, 0, 0); } return(new JobObject.AccountingInformation { IO = ioCounters, MemoryCounters = memoryCounters, KernelTime = TimeSpan.FromMilliseconds(m_processResourceUsage.Aggregate(0.0, (acc, usage) => acc + usage.Value.SystemTimeNs) / NanosecondsToMillisecondsFactor), UserTime = TimeSpan.FromMilliseconds(m_processResourceUsage.Aggregate(0.0, (acc, usage) => acc + usage.Value.UserTimeNs) / NanosecondsToMillisecondsFactor), NumberOfProcesses = childProcesses, }); } }
/// <nodoc /> public static AccountingInformation Deserialize(BuildXLReader reader) { return(new AccountingInformation() { IO = IOCounters.Deserialize(reader), UserTime = reader.ReadTimeSpan(), KernelTime = reader.ReadTimeSpan(), MemoryCounters = ProcessMemoryCounters.Deserialize(reader), NumberOfProcesses = reader.ReadUInt32() }); }
private ResourceScope AcquireResourceScope(Process processPip, ProcessMemoryCounters expectedMemoryCounters, bool allowCancellation) { Interlocked.Increment(ref m_activeExecutionCount); lock (m_syncLock) { var scope = new ResourceScope(this, processPip, m_nextScopeId++, expectedMemoryCounters, allowCancellation, m_headScope); m_headScope = scope; m_pipResourceScopes[processPip.PipId] = scope; return(scope); } }
/// <summary> /// Construct a new runtime data based on collected performance data /// </summary> public ProcessPipHistoricPerfData(ProcessPipExecutionPerformance executionPerformance) { Contract.Requires(executionPerformance.ExecutionLevel == PipExecutionLevel.Executed); m_entryTimeToLive = DefaultTimeToLive; // Deduct the suspended duration from the process execution time. DurationInMs = (uint)Math.Min(uint.MaxValue, Math.Max(1, executionPerformance.ProcessExecutionTime.TotalMilliseconds - executionPerformance.SuspendedDurationMs)); // For historical ram usage, we record the peak working set instead of the virtual memory due to the precision. MemoryCounters = executionPerformance.MemoryCounters; DiskIOInMB = (uint)Math.Min(uint.MaxValue, ByteSizeFormatter.ToMegabytes(executionPerformance.IO.GetAggregateIO().TransferCount)); ProcessorsInPercents = executionPerformance.ProcessorsInPercents; }
public ResourceScope(ProcessResourceManager resourceManager, PipId pipId, int scopeId, ProcessMemoryCounters expectedMemoryCounters, bool allowCancellation, ResourceScope next) { m_resourceManager = resourceManager; PipId = pipId; ScopeId = scopeId; ExpectedMemoryCounters = expectedMemoryCounters; m_allowCancellation = allowCancellation; Next = next; if (next != null) { next.Prior = this; } }
public static bool Deserialize(BuildXLReader reader, out ProcessPipHistoricPerfData result) { Contract.Requires(reader != null); byte timeToLive = reader.ReadByte(); byte newTimeToLive = (byte)(timeToLive - 1); result = new ProcessPipHistoricPerfData( newTimeToLive, reader.ReadUInt32(), ProcessMemoryCounters.Deserialize(reader), reader.ReadUInt16(), reader.ReadUInt32()); return(newTimeToLive > 0); }
public void TimeToLive() { int execTime = 1; uint runTime = 2; var processPipExecutionPerformance = new ProcessPipExecutionPerformance( PipExecutionLevel.Executed, DateTime.UtcNow, DateTime.UtcNow.AddMilliseconds(execTime), FingerprintUtilities.ZeroFingerprint, TimeSpan.FromMilliseconds(execTime), default(FileMonitoringViolationCounters), default(IOCounters), TimeSpan.FromMilliseconds(execTime), TimeSpan.FromMilliseconds(execTime / 2), ProcessMemoryCounters.CreateFromMb(1024, 1024, 1024, 1024), 1, workerId: 0, suspendedDurationMs: 0); ProcessPipHistoricPerfData runTimeData = new ProcessPipHistoricPerfData(processPipExecutionPerformance, runTime); HistoricPerfDataTable table = new HistoricPerfDataTable(LoggingContext); var semiStableHashToKeep = 0; table[semiStableHashToKeep] = runTimeData; var semiStableHashToDrop = 1; table[semiStableHashToDrop] = runTimeData; var stream = new MemoryStream(); for (int i = 0; i < ProcessPipHistoricPerfData.DefaultTimeToLive; i++) { stream.Position = 0; table.Save(stream); stream.Position = 0; table = HistoricPerfDataTable.Load(LoggingContext, stream); Analysis.IgnoreResult(table[semiStableHashToKeep]); } stream.Position = 0; table = HistoricPerfDataTable.Load(LoggingContext, stream); XAssert.AreEqual(1u, table[semiStableHashToKeep].ExeDurationInMs); XAssert.AreEqual(0u, table[semiStableHashToDrop].ExeDurationInMs); }
public void PipHistoricPerfDataConstructorDoesntCrash() { foreach (var obj in ConstructorDoesntCrashTestData()) { var executionStart = (DateTime)obj[0]; var executionStop = (DateTime)obj[1]; var processExecutionTime = (TimeSpan)obj[2]; var fileMonitoringWarnings = (int)obj[3]; var ioCounters = (IOCounters)obj[4]; var userTime = (TimeSpan)obj[5]; var kernelTime = (TimeSpan)obj[6]; var peakMemoryUsage = (ulong)obj[7]; var numberOfProcesses = (uint)obj[8]; var workerId = (uint)obj[9]; if (executionStart > executionStop) { continue; } var performance = new ProcessPipExecutionPerformance( PipExecutionLevel.Executed, executionStart, executionStop, FingerprintUtilities.ZeroFingerprint, processExecutionTime, new FileMonitoringViolationCounters(fileMonitoringWarnings, fileMonitoringWarnings, fileMonitoringWarnings), ioCounters, userTime, kernelTime, ProcessMemoryCounters.CreateFromBytes(peakMemoryUsage, peakMemoryUsage, peakMemoryUsage, peakMemoryUsage), numberOfProcesses, workerId, 0); var data = new ProcessPipHistoricPerfData(performance, (long)processExecutionTime.TotalMilliseconds); data = data.Merge(data); Analysis.IgnoreResult(data); } }
private void StartStep(RunnablePip runnablePip, PipExecutionStep step) { var pipId = runnablePip.PipId; var processRunnable = runnablePip as ProcessRunnablePip; Tracing.Logger.Log.DistributionWorkerExecutePipRequest( runnablePip.LoggingContext, runnablePip.Pip.SemiStableHash, runnablePip.Description, runnablePip.Step.AsString()); var completionData = m_pendingPipCompletions[pipId]; completionData.StepExecutionStarted.SetResult(true); switch (step) { case PipExecutionStep.ExecuteProcess: if (runnablePip.PipType == PipType.Process) { SinglePipBuildRequest pipBuildRequest; bool found = m_pendingBuildRequests.TryGetValue(pipId, out pipBuildRequest); Contract.Assert(found, "Could not find corresponding build request for executed pip on worker"); m_pendingBuildRequests[pipId] = null; // Set the cache miss result with fingerprint so ExecuteProcess step can use it var fingerprint = pipBuildRequest.Fingerprint.ToFingerprint(); processRunnable.SetCacheResult(RunnableFromCacheResult.CreateForMiss(new WeakContentFingerprint(fingerprint))); processRunnable.ExpectedMemoryCounters = ProcessMemoryCounters.CreateFromMb( peakWorkingSetMb: pipBuildRequest.ExpectedPeakWorkingSetMb, averageWorkingSetMb: pipBuildRequest.ExpectedAverageWorkingSetMb, peakCommitSizeMb: pipBuildRequest.ExpectedPeakCommitSizeMb, averageCommitSizeMb: pipBuildRequest.ExpectedAverageCommitSizeMb); } break; } }
/// <summary> /// Attempts to execute the given function for the pip after acquiring the resources to run the pip and /// provides cancellation when resources are limited /// </summary> public async Task <T> ExecuteWithResources <T>( OperationContext operationContext, PipId pipId, ProcessMemoryCounters expectedMemoryCounters, bool allowCancellation, ManagedResourceExecute <T> execute) { ResourceScope scope; using (operationContext.StartOperation(PipExecutorCounter.AcquireResourcesDuration)) { scope = AcquireResourceScope(pipId, expectedMemoryCounters, allowCancellation); } using (scope) { var result = await execute(scope.Token, registerQueryRamUsageMb : scope.RegisterQueryRamUsageMb); scope.Complete(); return(result); } }
/// <summary> /// Attempts to execute the given function for the pip after acquiring the resources to run the pip and /// provides cancellation when resources are limited /// </summary> public async Task <T> ExecuteWithResourcesAsync <T>( OperationContext operationContext, Process processPip, ProcessMemoryCounters expectedMemoryCounters, bool allowCancellation, ManagedResourceExecute <T> execute) { ResourceScope scope; using (operationContext.StartOperation(PipExecutorCounter.AcquireResourcesDuration)) { scope = AcquireResourceScope(processPip, expectedMemoryCounters, allowCancellation); } using (scope) { var result = await execute(scope); scope.Complete(); return(result); } }
public ResourceManagerWorkItemTracker(LoggingContext loggingContext, ProcessResourceManager resourceManager, uint id, int estimatedRamUsage, bool allowCancellation) { ExecutionCompletionSource = TaskSourceSlim.Create <int>(); m_cancellationCompletionSource = TaskSourceSlim.Create <Unit>(); var context = BuildXLContext.CreateInstanceForTesting(); m_execute = () => ExecutionTask = resourceManager.ExecuteWithResourcesAsync( OperationContext.CreateUntracked(loggingContext), SchedulerTest.CreateDummyProcess(context, new PipId(id)), ProcessMemoryCounters.CreateFromMb(estimatedRamUsage, estimatedRamUsage, estimatedRamUsage, estimatedRamUsage), allowCancellation, async(resourceScope) => { m_startSemaphore.Release(); resourceScope.RegisterQueryRamUsageMb(() => RamUsage); ExecutionCount++; var currrentCancellationCompletionSource = m_cancellationCompletionSource; resourceScope.Token.Register(() => { XAssert.IsTrue(m_startSemaphore.Wait(millisecondsTimeout: 100000)); CancellationCount++; m_cancellationCompletionSource = TaskSourceSlim.Create <Unit>(); currrentCancellationCompletionSource.TrySetResult(Unit.Void); }); var result = await Task.WhenAny(currrentCancellationCompletionSource.Task, ExecutionCompletionSource.Task); resourceScope.Token.ThrowIfCancellationRequested(); XAssert.IsTrue(ExecutionCompletionSource.Task.IsCompleted, "This task should be completed since the cancellation task implies the cancellation token would throw in the preceding line of code."); return(ExecutionCompletionSource.Task.Result); }); StartExecute(); }
/// <summary> /// Gets the estimated memory counters for the process /// </summary> public ProcessMemoryCounters GetExpectedMemoryCounters(ProcessRunnablePip runnableProcess) { if (TotalRamMb == null || TotalCommitMb == null) { return(ProcessMemoryCounters.CreateFromMb(0, 0, 0)); } if (runnableProcess.ExpectedMemoryCounters == null) { return(ProcessMemoryCounters.CreateFromMb( peakVirtualMemoryUsageMb: DefaultMemoryUsageMbPerProcess, peakWorkingSetMb: DefaultMemoryUsageMbPerProcess, peakCommitUsageMb: DefaultCommitUsageMbPerProcess)); } var expectedMemoryCounters = runnableProcess.ExpectedMemoryCounters.Value; // 5% more to give some slack return(ProcessMemoryCounters.CreateFromMb( peakVirtualMemoryUsageMb: (int)(expectedMemoryCounters.PeakVirtualMemoryUsageMb * 1.05), peakWorkingSetMb: (int)(expectedMemoryCounters.PeakWorkingSetMb * 1.05), peakCommitUsageMb: (int)(expectedMemoryCounters.PeakCommitUsageMb * 1.05))); }
public static bool Deserialize(BuildXLReader reader, out ProcessPipHistoricPerfData result) { Contract.Requires(reader != null); byte timeToLive = reader.ReadByte(); byte newTimeToLive = (byte)(timeToLive - 1); uint exeDurationMs = reader.ReadUInt32(); uint maxExeDurationMs = reader.ReadUInt32(); uint runDurationMs = reader.ReadUInt32(); ProcessMemoryCounters memoryCounters = ProcessMemoryCounters.Deserialize(reader); ushort processorsInPercents = reader.ReadUInt16(); uint diskIOInMB = reader.ReadUInt32(); result = new ProcessPipHistoricPerfData( newTimeToLive, exeDurationMs, maxExeDurationMs, runDurationMs, memoryCounters, processorsInPercents, diskIOInMB); return(newTimeToLive > 0); }
public void TestProcessExecutionResultSerialization() { var reportedAccess = CreateRandomReportedFileAccess(); Fingerprint fingerprint = FingerprintUtilities.CreateRandom(); var processExecutionResult = ExecutionResult.CreateSealed( result: PipResultStatus.Succeeded, numberOfWarnings: 12, outputContent: ReadOnlyArray <(FileArtifact, FileMaterializationInfo, PipOutputOrigin)> .FromWithoutCopy(CreateRandomOutputContent(), CreateRandomOutputContent()), directoryOutputs: ReadOnlyArray <(DirectoryArtifact, ReadOnlyArray <FileArtifact>)> .FromWithoutCopy(CreateRandomOutputDirectory(), CreateRandomOutputDirectory()), performanceInformation: new ProcessPipExecutionPerformance( PipExecutionLevel.Executed, DateTime.UtcNow, DateTime.UtcNow + TimeSpan.FromMinutes(2), FingerprintUtilities.ZeroFingerprint, TimeSpan.FromMinutes(2), new FileMonitoringViolationCounters(2, 3, 4), default(IOCounters), TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3), ProcessMemoryCounters.CreateFromBytes(12324, 12325, 12326, 12326), 33, 7, 0), fingerprint: new WeakContentFingerprint(fingerprint), fileAccessViolationsNotAllowlisted: new[] { reportedAccess, CreateRandomReportedFileAccess(), // Create reported file access that uses the same process to test deduplication during deserialization CreateRandomReportedFileAccess(reportedAccess.Process), }, allowlistedFileAccessViolations: new ReportedFileAccess[0], mustBeConsideredPerpetuallyDirty: true, dynamicallyObservedFiles: ReadOnlyArray <AbsolutePath> .FromWithoutCopy( CreateSourceFile().Path, CreateSourceFile().Path ), dynamicallyProbedFiles: ReadOnlyArray <AbsolutePath> .FromWithoutCopy( CreateSourceFile().Path, CreateSourceFile().Path, CreateSourceFile().Path ), dynamicallyObservedEnumerations: ReadOnlyArray <AbsolutePath> .FromWithoutCopy( CreateSourceFile().Path ), allowedUndeclaredSourceReads: new ReadOnlyHashSet <AbsolutePath> { CreateSourceFile().Path, CreateSourceFile().Path }, absentPathProbesUnderOutputDirectories: new ReadOnlyHashSet <AbsolutePath> { CreateSourceFile().Path, CreateSourceFile().Path }, twoPhaseCachingInfo: new TwoPhaseCachingInfo( new WeakContentFingerprint(Fingerprint.Random(FingerprintUtilities.FingerprintLength)), ContentHashingUtilities.CreateRandom(), new StrongContentFingerprint(Fingerprint.Random(FingerprintUtilities.FingerprintLength)), new CacheEntry(ContentHashingUtilities.CreateRandom(), null, CreateRandomContentHashArray())), pipCacheDescriptorV2Metadata: null, converged: true, pathSet: null, cacheLookupStepDurations: null, pipProperties: new Dictionary <string, int> { { "Foo", 1 }, { "Bar", 9 } }, hasUserRetries: true); ExecutionResultSerializer serializer = new ExecutionResultSerializer(0, Context); ExecutionResult deserializedProcessExecutionResult; using (var stream = new MemoryStream()) using (var writer = new BuildXLWriter(false, stream, true, false)) using (var reader = new BuildXLReader(false, stream, true)) { serializer.Serialize(writer, processExecutionResult, preservePathCasing: false); stream.Position = 0; deserializedProcessExecutionResult = serializer.Deserialize(reader, processExecutionResult.PerformanceInformation.WorkerId); } // Ensure successful pip result is changed to not materialized. XAssert.AreEqual(PipResultStatus.NotMaterialized, deserializedProcessExecutionResult.Result); AssertEqual(processExecutionResult, deserializedProcessExecutionResult, r => r.NumberOfWarnings, r => r.Converged, r => r.OutputContent.Length, r => r.DirectoryOutputs.Length, r => r.PerformanceInformation.ExecutionLevel, r => r.PerformanceInformation.ExecutionStop, r => r.PerformanceInformation.ExecutionStart, r => r.PerformanceInformation.ProcessExecutionTime, r => r.PerformanceInformation.FileMonitoringViolations.NumFileAccessViolationsNotAllowlisted, r => r.PerformanceInformation.FileMonitoringViolations.NumFileAccessesAllowlistedAndCacheable, r => r.PerformanceInformation.FileMonitoringViolations.NumFileAccessesAllowlistedButNotCacheable, r => r.PerformanceInformation.UserTime, r => r.PerformanceInformation.KernelTime, r => r.PerformanceInformation.MemoryCounters.PeakWorkingSetMb, r => r.PerformanceInformation.MemoryCounters.AverageWorkingSetMb, r => r.PerformanceInformation.MemoryCounters.PeakCommitSizeMb, r => r.PerformanceInformation.MemoryCounters.AverageCommitSizeMb, r => r.PerformanceInformation.NumberOfProcesses, r => r.FileAccessViolationsNotAllowlisted.Count, r => r.MustBeConsideredPerpetuallyDirty, r => r.DynamicallyObservedFiles.Length, r => r.DynamicallyProbedFiles.Length, r => r.DynamicallyObservedEnumerations.Length, r => r.AllowedUndeclaredReads.Count, r => r.TwoPhaseCachingInfo.WeakFingerprint, r => r.TwoPhaseCachingInfo.StrongFingerprint, r => r.TwoPhaseCachingInfo.PathSetHash, r => r.TwoPhaseCachingInfo.CacheEntry.MetadataHash, r => r.TwoPhaseCachingInfo.CacheEntry.OriginatingCache, r => r.TwoPhaseCachingInfo.CacheEntry.ReferencedContent.Length, r => r.PipProperties.Count, r => r.HasUserRetries, r => r.RetryInfo ); for (int i = 0; i < processExecutionResult.OutputContent.Length; i++) { int j = i; AssertEqual(processExecutionResult, deserializedProcessExecutionResult, r => r.OutputContent[j].Item1, r => r.OutputContent[j].Item2 ); // Ensure that output origin from deserialzed output content is changed to not materialized. XAssert.AreEqual(PipOutputOrigin.NotMaterialized, deserializedProcessExecutionResult.OutputContent[i].Item3); } for (int i = 0; i < processExecutionResult.DirectoryOutputs.Length; i++) { var expected = processExecutionResult.DirectoryOutputs[i]; var result = deserializedProcessExecutionResult.DirectoryOutputs[i]; XAssert.AreEqual(expected.Item1, result.Item1); XAssert.AreEqual(expected.Item2.Length, result.Item2.Length); for (int j = 0; j < expected.Item2.Length; j++) { XAssert.AreEqual(expected.Item2[j], result.Item2[j]); } } for (int i = 0; i < processExecutionResult.FileAccessViolationsNotAllowlisted.Count; i++) { // Compare individual fields for ReportedFileAccess since it uses reference // equality for reported process which would not work for serialization/deserialization AssertEqual(processExecutionResult.FileAccessViolationsNotAllowlisted[i], deserializedProcessExecutionResult.FileAccessViolationsNotAllowlisted[i]); } // Ensure that reported process instances are deduplicated. XAssert.AreSame(deserializedProcessExecutionResult.FileAccessViolationsNotAllowlisted[0].Process, deserializedProcessExecutionResult.FileAccessViolationsNotAllowlisted[2].Process); for (int i = 0; i < processExecutionResult.DynamicallyObservedFiles.Length; i++) { AssertEqual(processExecutionResult.DynamicallyObservedFiles[i], deserializedProcessExecutionResult.DynamicallyObservedFiles[i]); } for (int i = 0; i < processExecutionResult.DynamicallyProbedFiles.Length; i++) { AssertEqual(processExecutionResult.DynamicallyProbedFiles[i], deserializedProcessExecutionResult.DynamicallyProbedFiles[i]); } for (int i = 0; i < processExecutionResult.DynamicallyObservedEnumerations.Length; i++) { AssertEqual(processExecutionResult.DynamicallyObservedEnumerations[i], deserializedProcessExecutionResult.DynamicallyObservedEnumerations[i]); } XAssert.AreSetsEqual(processExecutionResult.AllowedUndeclaredReads, deserializedProcessExecutionResult.AllowedUndeclaredReads, expectedResult: true); var referencedContentLength = processExecutionResult.TwoPhaseCachingInfo.CacheEntry.ReferencedContent.Length; for (int i = 0; i < referencedContentLength; i++) { XAssert.AreEqual( processExecutionResult.TwoPhaseCachingInfo.CacheEntry.ReferencedContent[i], deserializedProcessExecutionResult.TwoPhaseCachingInfo.CacheEntry.ReferencedContent[i]); } XAssert.AreEqual(9, deserializedProcessExecutionResult.PipProperties["Bar"]); }
public static extern int GetProcessMemoryInfo(IntPtr hProcess, out ProcessMemoryCounters counters, int size);
private ProcessSemaphoreInfo[] GetAdditionalResourceInfo(ProcessRunnablePip runnableProcess, ProcessMemoryCounters expectedMemoryCounters) { using (var semaphoreInfoListWrapper = s_semaphoreInfoListPool.GetInstance()) { var semaphores = semaphoreInfoListWrapper.Instance; if (runnableProcess.Process.RequiresAdmin && runnableProcess.Environment.Configuration.Sandbox.AdminRequiredProcessExecutionMode.ExecuteExternalVm() && runnableProcess.Environment.Configuration.Sandbox.VmConcurrencyLimit > 0) { semaphores.Add(new ProcessSemaphoreInfo( runnableProcess.Environment.Context.StringTable.AddString(PipInVmSemaphoreName), value: 1, limit: runnableProcess.Environment.Configuration.Sandbox.VmConcurrencyLimit)); } if (TotalRamMb == null || runnableProcess.Environment.Configuration.Schedule.UseHistoricalRamUsageInfo != true) { // Not tracking working set return(semaphores.ToArray()); } if (!m_ramSemaphoreNameId.IsValid) { m_ramSemaphoreNameId = runnableProcess.Environment.Context.StringTable.AddString(RamSemaphoreName); m_ramSemaphoreIndex = m_workerSemaphores.CreateSemaphore(m_ramSemaphoreNameId, ProcessExtensions.PercentageResourceLimit); } bool enableLessAggresiveMemoryProjection = runnableProcess.Environment.Configuration.Schedule.EnableLessAggresiveMemoryProjection; var ramSemaphoreInfo = ProcessExtensions.GetNormalizedPercentageResource( m_ramSemaphoreNameId, usage: enableLessAggresiveMemoryProjection ? expectedMemoryCounters.AverageWorkingSetMb : expectedMemoryCounters.PeakWorkingSetMb, total: TotalRamMb.Value); semaphores.Add(ramSemaphoreInfo); if (runnableProcess.Environment.Configuration.Schedule.EnableHistoricCommitMemoryProjection) { if (!m_commitSemaphoreNameId.IsValid) { m_commitSemaphoreNameId = runnableProcess.Environment.Context.StringTable.AddString(CommitSemaphoreName); m_commitSemaphoreIndex = m_workerSemaphores.CreateSemaphore(m_commitSemaphoreNameId, ProcessExtensions.PercentageResourceLimit); } var commitSemaphoreInfo = ProcessExtensions.GetNormalizedPercentageResource( m_commitSemaphoreNameId, usage: enableLessAggresiveMemoryProjection ? expectedMemoryCounters.AverageCommitSizeMb : expectedMemoryCounters.PeakCommitSizeMb, total: TotalCommitMb.Value); semaphores.Add(commitSemaphoreInfo); } return(semaphores.ToArray()); } }
private static extern bool GetProcessMemoryInfo(IntPtr hProcess, out ProcessMemoryCounters counters, uint size);
public void PipHistoricPerfDataConstructorDoesntCrash() { // TODO: Use IntelliTest/Pex for this. var times = new[] { new DateTime(DateTime.MinValue.Year + 1, 1, 1).ToUniversalTime(), new DateTime(2015, 1, 1).ToUniversalTime(), new DateTime(DateTime.MaxValue.Year, 1, 1).ToUniversalTime() }; var spans = new[] { TimeSpan.Zero, TimeSpan.FromSeconds(1), TimeSpan.MaxValue }; var ints = new[] { 0, int.MaxValue }; // Let's say that the highest possible memory usage is currently 1TB. var ulongs = new ulong[] { 0, 1, (ulong)1024 * 1024 * 1024 * 1024 }; var uints = new uint[] { 0, 1, uint.MaxValue }; foreach (var executionStart in times) { foreach (var executionStop in times) { foreach (var processExecutionTime in spans) { foreach (var fileMonitoringWarnings in ints) { foreach (var ioCounters in new[] { new IOCounters( readCounters: new IOTypeCounters(operationCount: 1, transferCount: ulong.MaxValue), writeCounters: new IOTypeCounters(operationCount: 0, transferCount: 0), otherCounters: new IOTypeCounters(operationCount: 0, transferCount: 0) ), new IOCounters( readCounters: new IOTypeCounters(operationCount: 0, transferCount: 0), writeCounters: new IOTypeCounters(operationCount: 0, transferCount: 0), otherCounters: new IOTypeCounters(operationCount: 0, transferCount: 0) ) }) { foreach (var userTime in spans) { foreach (var kernelTime in spans) { foreach (var peakMemoryUsage in ulongs) { foreach (var numberOfProcesses in uints) { foreach (var workerId in uints) { if (executionStart > executionStop) { continue; } var performance = new ProcessPipExecutionPerformance( PipExecutionLevel.Executed, executionStart, executionStop, FingerprintUtilities.ZeroFingerprint, processExecutionTime, new FileMonitoringViolationCounters(fileMonitoringWarnings, fileMonitoringWarnings, fileMonitoringWarnings), ioCounters, userTime, kernelTime, ProcessMemoryCounters.CreateFromBytes(peakMemoryUsage, peakMemoryUsage, peakMemoryUsage), numberOfProcesses, workerId); var data = new PipHistoricPerfData(performance); data = data.Merge(data); Analysis.IgnoreResult(data); } } } } } } } } } } }