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
19 changes: 4 additions & 15 deletions docs/design/datacontracts/StressLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -38,7 +33,7 @@ bool HasStressLog();
StressLogData GetStressLogData();
StressLogData GetStressLogData(TargetPointer stressLogPointer);
IEnumerable<ThreadStressLogData> GetThreadStressLogs(TargetPointer logs);
IEnumerable<StressMsgData> GetStressMessages(ThreadStressLogData threadLog);
IEnumerable<StressMsgData> GetStressMessages(TargetPointer threadStressLogAddress);
bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer);
```

Expand Down Expand Up @@ -67,7 +62,6 @@ Data descriptors used:
| ThreadStressLog | ChunkListHead | Pointer to the head of the chunk list |
| ThreadStressLog | ChunkListTail | Pointer to the tail of the chunk list |
| ThreadStressLog | CurrentWriteChunk | Pointer to the chunk currently being written to |
| StressLogChunk | Prev | Pointer to the previous chunk |
| StressLogChunk | Next | Pointer to the next chunk |
| StressLogChunk | Buf | The data stored in the chunk |
| StressLogChunk | Sig1 | First byte of the chunk signature (to ensure validity) |
Expand Down Expand Up @@ -157,20 +151,15 @@ IEnumerable<ThreadStressLogData> 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<StressMsgData> GetStressMessages(ThreadStressLogData threadLog)
IEnumerable<StressMsgData> 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.
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/datadescriptor/datadescriptor.inc
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,6 @@ CDAC_TYPE_END(ThreadStressLog)

CDAC_TYPE_BEGIN(StressLogChunk)
CDAC_TYPE_SIZE(sizeof(StressLogChunk))
CDAC_TYPE_FIELD(StressLogChunk, T_POINTER, Prev, offsetof(StressLogChunk, prev))
CDAC_TYPE_FIELD(StressLogChunk, T_POINTER, Next, offsetof(StressLogChunk, next))
CDAC_TYPE_FIELD(StressLogChunk, T_ARRAY(T_UINT8), Buf, offsetof(StressLogChunk, buf))
CDAC_TYPE_FIELD(StressLogChunk, T_UINT32, Sig1, offsetof(StressLogChunk, dwSig1))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -40,7 +35,7 @@ public interface IStressLog : IContract
StressLogData GetStressLogData() => throw new NotImplementedException();
StressLogData GetStressLogData(TargetPointer stressLog) => throw new NotImplementedException();
IEnumerable<ThreadStressLogData> GetThreadStressLogs(TargetPointer Logs) => throw new NotImplementedException();
IEnumerable<StressMsgData> GetStressMessages(ThreadStressLogData threadLog) => throw new NotImplementedException();
IEnumerable<StressMsgData> GetStressMessages(TargetPointer threadStressLogAddress) => throw new NotImplementedException();
bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer) => throw new NotImplementedException();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ public static class Globals
public const string StressLog = nameof(StressLog);
public const string StressLogModuleTable = nameof(StressLogModuleTable);
public const string StressLogMaxModules = nameof(StressLogMaxModules);
public const string StressLogChunkMaxSize = nameof(StressLogChunkMaxSize);
public const string StressLogMaxMessageSize = nameof(StressLogMaxMessageSize);
public const string StressLogChunkSize = nameof(StressLogChunkSize);
public const string StressLogValidChunkSig = nameof(StressLogValidChunkSig);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,8 @@ public IEnumerable<ThreadStressLogData> 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;
}
Expand Down Expand Up @@ -128,18 +123,20 @@ private TargetPointer GetFormatPointer(ulong formatOffset)
return TargetPointer.Null;
}

public IEnumerable<StressMsgData> GetStressMessages(ThreadStressLogData threadLog)
public IEnumerable<StressMsgData> GetStressMessages(TargetPointer threadStressLogAddress)
{
uint stressMsgHeaderSize = target.GetTypeInfo(DataType.StressMsgHeader).Size!.Value;
uint pointerSize = (uint)target.PointerSize;

Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment on lines +126 to 134
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment on lines +126 to +135
bool readHasWrapped = false;
uint chunkSize = target.ReadGlobal<uint>(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
Expand Down Expand Up @@ -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<ThreadStressLogData> GetThreadStressLogs(TargetPointer Logs) => traversal.GetThreadStressLogs(Logs);
public IEnumerable<StressMsgData> GetStressMessages(ThreadStressLogData threadLog) => traversal.GetStressMessages(threadLog);
public IEnumerable<StressMsgData> GetStressMessages(TargetPointer threadStressLogAddress) => traversal.GetStressMessages(threadStressLogAddress);
public bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer) => traversal.IsPointerInStressLog(stressLog, pointer);
}

Expand All @@ -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<ThreadStressLogData> GetThreadStressLogs(TargetPointer Logs) => traversal.GetThreadStressLogs(Logs);
public IEnumerable<StressMsgData> GetStressMessages(ThreadStressLogData threadLog) => traversal.GetStressMessages(threadLog);
public IEnumerable<StressMsgData> GetStressMessages(TargetPointer threadStressLogAddress) => traversal.GetStressMessages(threadStressLogAddress);
public bool IsPointerInStressLog(StressLogData stressLog, TargetPointer pointer) => traversal.IsPointerInStressLog(stressLog, pointer);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ namespace Microsoft.Diagnostics.DataContractReader.Data;
internal sealed partial class StressLogChunk : IData<StressLogChunk>
{
[Field] public TargetPointer Next { get; }
[Field] public TargetPointer Prev { get; }

[FieldAddress]
public TargetPointer Buf { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Contracts.StressMsgData> messages = stressLogContract.GetStressMessages(matchedThread.Value);
TargetPointer address = threadStressLogAddress.ToTargetPointer(_target);
IEnumerable<Contracts.StressMsgData> messages = stressLogContract.GetStressMessages(address);
ppEnum.Interface = new SOSStressLogMsgEnum(_target, messages);
}
catch (System.Exception ex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/tools/StressLogAnalyzer/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ private static ContractDescriptorParser.ContractDescriptor GetDescriptor(string
"StressLogModuleTable": [[ 1 ], "pointer" ],
},
"contracts": {
"StressLog": 2,
"StressLog": "c2",
}
}
""""u8)!;
Expand Down
4 changes: 2 additions & 2 deletions src/tools/StressLogAnalyzer/src/StressLogAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -58,7 +58,7 @@ await Parallel.ForEachAsync(logs, parallelOptions, (log, ct) =>
StressMsgData? earliestMessage = null;
List<StressMsgData> 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();
Expand Down
Loading