diff --git a/docs/design/datacontracts/StressLog.md b/docs/design/datacontracts/StressLog.md index c761b8b06938be..d5e0f049813ccf 100644 --- a/docs/design/datacontracts/StressLog.md +++ b/docs/design/datacontracts/StressLog.md @@ -18,13 +18,8 @@ internal record struct StressLogData( internal record struct ThreadStressLogData( TargetPointer Address, - TargetPointer NextPointer, ulong ThreadId, - bool WriteHasWrapped, - TargetPointer CurrentPointer, - TargetPointer ChunkListHead, - TargetPointer ChunkListTail, - TargetPointer CurrentWriteChunk); + bool WriteHasWrapped); internal record struct StressMsgData( uint Facility, @@ -38,7 +33,7 @@ bool HasStressLog(); StressLogData GetStressLogData(); StressLogData GetStressLogData(TargetPointer stressLogPointer); IEnumerable GetThreadStressLogs(TargetPointer logs); -IEnumerable GetStressMessages(ThreadStressLogData threadLog); +IEnumerable GetStressMessages(TargetPointer threadStressLogAddress); bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer); ``` @@ -157,20 +152,15 @@ IEnumerable GetThreadStressLogs(TargetPointer logs) yield return new ThreadStressLogData( currentPointer, - threadStressLog.Next, threadStressLog.ThreadId, - threadStressLog.WriteHasWrapped, - threadStressLog.CurrentPtr, - threadStressLog.ChunkListHead, - threadStressLog.ChunkListTail, - threadStressLog.CurrentWriteChunk); + threadStressLog.WriteHasWrapped); currentPointer = threadStressLog.Next; } } // Return messages going in reverse chronological order, newest first. -IEnumerable GetStressMessages(ThreadStressLogData threadLog) +IEnumerable GetStressMessages(TargetPointer threadStressLogAddress) { // 1. Get the current message pointer from the log and the info about the current chunk the runtime is writing into. // Record our current read pointer as the current message pointer. diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IStressLog.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IStressLog.cs index 4bd41735561628..5a81b03130fe2d 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IStressLog.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IStressLog.cs @@ -19,13 +19,8 @@ public record struct StressLogData( public record struct ThreadStressLogData( TargetPointer Address, - TargetPointer NextPointer, ulong ThreadId, - bool WriteHasWrapped, - TargetPointer CurrentPointer, - TargetPointer ChunkListHead, - TargetPointer ChunkListTail, - TargetPointer CurrentWriteChunk); + bool WriteHasWrapped); public record struct StressMsgData( uint Facility, @@ -40,7 +35,7 @@ public interface IStressLog : IContract StressLogData GetStressLogData() => throw new NotImplementedException(); StressLogData GetStressLogData(TargetPointer stressLog) => throw new NotImplementedException(); IEnumerable GetThreadStressLogs(TargetPointer Logs) => throw new NotImplementedException(); - IEnumerable GetStressMessages(ThreadStressLogData threadLog) => throw new NotImplementedException(); + IEnumerable GetStressMessages(TargetPointer threadStressLogAddress) => throw new NotImplementedException(); bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer) => throw new NotImplementedException(); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StressLog.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StressLog.cs index c5d0d7b82ce7cd..4bee76f7039124 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StressLog.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StressLog.cs @@ -81,13 +81,8 @@ public IEnumerable GetThreadStressLogs(TargetPointer Logs) yield return new ThreadStressLogData( currentPointer, - threadStressLog.Next, threadStressLog.ThreadId, - threadStressLog.WriteHasWrapped, - threadStressLog.CurrentPtr, - threadStressLog.ChunkListHead, - threadStressLog.ChunkListTail, - threadStressLog.CurrentWriteChunk); + threadStressLog.WriteHasWrapped); currentPointer = threadStressLog.Next; } @@ -128,18 +123,20 @@ private TargetPointer GetFormatPointer(ulong formatOffset) return TargetPointer.Null; } - public IEnumerable GetStressMessages(ThreadStressLogData threadLog) + public IEnumerable GetStressMessages(TargetPointer threadStressLogAddress) { uint stressMsgHeaderSize = target.GetTypeInfo(DataType.StressMsgHeader).Size!.Value; uint pointerSize = (uint)target.PointerSize; + Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd(threadStressLogAddress); + Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd(threadLog.CurrentWriteChunk); TargetPointer currentReadChunk = threadLog.CurrentWriteChunk; - TargetPointer readPointer = threadLog.CurrentPointer; + TargetPointer readPointer = threadLog.CurrentPtr; bool readHasWrapped = false; uint chunkSize = target.ReadGlobal(Constants.Globals.StressLogChunkSize); - TargetPointer currentPointer = threadLog.CurrentPointer; + TargetPointer currentPointer = threadLog.CurrentPtr; // the last written log, if it wrapped around may have partially overwritten // a previous record. Update currentPointer to reflect the last safe beginning of a record, // but currentPointer shouldn't wrap around, otherwise it'll break our assumptions about stress @@ -341,7 +338,7 @@ internal sealed class StressLog_1(Target target) : IStressLog public StressLogData GetStressLogData() => traversal.GetStressLogData(); public StressLogData GetStressLogData(TargetPointer stressLog) => traversal.GetStressLogData(stressLog); public IEnumerable GetThreadStressLogs(TargetPointer Logs) => traversal.GetThreadStressLogs(Logs); - public IEnumerable GetStressMessages(ThreadStressLogData threadLog) => traversal.GetStressMessages(threadLog); + public IEnumerable GetStressMessages(TargetPointer threadStressLogAddress) => traversal.GetStressMessages(threadStressLogAddress); public bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer) => traversal.IsPointerInStressLog(stressLog, pointer); } @@ -354,6 +351,6 @@ internal sealed class StressLog_2(Target target) : IStressLog public StressLogData GetStressLogData() => traversal.GetStressLogData(); public StressLogData GetStressLogData(TargetPointer stressLog) => traversal.GetStressLogData(stressLog); public IEnumerable GetThreadStressLogs(TargetPointer Logs) => traversal.GetThreadStressLogs(Logs); - public IEnumerable GetStressMessages(ThreadStressLogData threadLog) => traversal.GetStressMessages(threadLog); + public IEnumerable GetStressMessages(TargetPointer threadStressLogAddress) => traversal.GetStressMessages(threadStressLogAddress); public bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer) => traversal.IsPointerInStressLog(stressLog, pointer); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs index 5608f9a3ede3ca..42e4f9cae1d779 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs @@ -7320,23 +7320,8 @@ int ISOSDacInterface17.GetStressLogMessageEnumerator( if (!stressLogContract.HasStressLog()) return HResults.S_FALSE; - Contracts.StressLogData logData = stressLogContract.GetStressLogData(); - - // Find the matching thread - Contracts.ThreadStressLogData? matchedThread = null; - foreach (var thread in stressLogContract.GetThreadStressLogs(logData.Logs)) - { - if (thread.Address == threadStressLogAddress.ToTargetPointer(_target)) - { - matchedThread = thread; - break; - } - } - - if (matchedThread is null) - return HResults.E_INVALIDARG; - - IEnumerable messages = stressLogContract.GetStressMessages(matchedThread.Value); + TargetPointer address = threadStressLogAddress.ToTargetPointer(_target); + IEnumerable messages = stressLogContract.GetStressMessages(address); ppEnum.Interface = new SOSStressLogMsgEnum(_target, messages); } catch (System.Exception ex) diff --git a/src/native/managed/cdac/tests/DumpTests/StressLogDumpTests.cs b/src/native/managed/cdac/tests/DumpTests/StressLogDumpTests.cs index afb3b3f3ec7bd6..7d30d45afb98b4 100644 --- a/src/native/managed/cdac/tests/DumpTests/StressLogDumpTests.cs +++ b/src/native/managed/cdac/tests/DumpTests/StressLogDumpTests.cs @@ -55,7 +55,7 @@ public void CanEnumerateThreadsAndMessages(TestConfiguration config) bool foundMessages = false; foreach (ThreadStressLogData thread in threads) { - var messages = stressLog.GetStressMessages(thread).Take(10).ToList(); + var messages = stressLog.GetStressMessages(thread.Address).Take(10).ToList(); if (messages.Count > 0) { foundMessages = true; diff --git a/src/tools/StressLogAnalyzer/src/Program.cs b/src/tools/StressLogAnalyzer/src/Program.cs index b7195a218f4afb..da521ffe4a1ecc 100644 --- a/src/tools/StressLogAnalyzer/src/Program.cs +++ b/src/tools/StressLogAnalyzer/src/Program.cs @@ -585,7 +585,7 @@ private static ContractDescriptorParser.ContractDescriptor GetDescriptor(string "StressLogModuleTable": [[ 1 ], "pointer" ], }, "contracts": { - "StressLog": 2, + "StressLog": "c2", } } """"u8)!; diff --git a/src/tools/StressLogAnalyzer/src/StressLogAnalyzer.cs b/src/tools/StressLogAnalyzer/src/StressLogAnalyzer.cs index c59bab54ecd8bc..95f0a98d522263 100644 --- a/src/tools/StressLogAnalyzer/src/StressLogAnalyzer.cs +++ b/src/tools/StressLogAnalyzer/src/StressLogAnalyzer.cs @@ -32,7 +32,7 @@ internal sealed class StressLogAnalyzer( // The "end" timestamp is the timestamp of the most recent message. timeTracker.SetEndTimestamp( logs.Select( - log => outerLogContract.GetStressMessages(log).FirstOrDefault().Timestamp) + log => outerLogContract.GetStressMessages(log.Address).FirstOrDefault().Timestamp) .Max()); if (!threadFilter.HasAnyGCThreadFilter) @@ -58,7 +58,7 @@ await Parallel.ForEachAsync(logs, parallelOptions, (log, ct) => StressMsgData? earliestMessage = null; List localMessages = []; bool includeThreadMessages = true; - foreach (StressMsgData message in stressLogContract.Value!.GetStressMessages(log)) + foreach (StressMsgData message in stressLogContract.Value!.GetStressMessages(log.Address)) { numMessagesProcessed.Value++; token.ThrowIfCancellationRequested();