Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
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 numberDiff line numberDiff 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 DownExpand 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 DownExpand 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 numberDiff line numberDiff line change
Expand Up@@ -651,7 +651,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 numberDiff line numberDiff 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);
Comment thread
jkotas marked this conversation as resolved.

public record struct StressMsgData(
uint Facility,
Expand All@@ -44,7 +39,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();
IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => throw new NotImplementedException();
}
Expand Down
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff 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 DownExpand 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;

Comment thread
max-charlamb marked this conversation as resolved.
Data.ThreadStressLog threadLog = target.ProcessedData.GetOrAdd<Data.ThreadStressLog>(threadStressLogAddress);

Data.StressLogChunk currentChunkData = target.ProcessedData.GetOrAdd<Data.StressLogChunk>(threadLog.CurrentWriteChunk);
TargetPointer currentReadChunk = threadLog.CurrentWriteChunk;
Comment thread
max-charlamb marked this conversation as resolved.
TargetPointer readPointer = threadLog.CurrentPointer;
TargetPointer readPointer = threadLog.CurrentPtr;
Comment thread
max-charlamb marked this conversation as resolved.
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 DownExpand Up@@ -351,7 +348,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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Expand All@@ -365,7 +362,7 @@ 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);
public IEnumerable<StressLogMemoryRange> GetStressLogMemoryRanges(StressLogData stressLog) => traversal.GetStressLogMemoryRanges(stressLog);
}
Original file line numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -7327,23 +7327,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 numberDiff line numberDiff 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 numberDiff line numberDiff line change
Expand Up@@ -586,7 +586,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 numberDiff line numberDiff 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