Skip to content

Commit

Permalink
Contention profiling: add blocking thread name
Browse files Browse the repository at this point in the history
  • Loading branch information
gleocadie committed Sep 4, 2024
1 parent f5634df commit 0378b3b
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,23 +84,27 @@ std::string ContentionProvider::GetBucket(double contentionDurationNs)
// .NET Framework implementation
void ContentionProvider::OnContention(uint64_t timestamp, uint32_t threadId, double contentionDurationNs, const std::vector<uintptr_t>& stack)
{
AddContentionSample(timestamp, threadId, contentionDurationNs, 0, stack);
AddContentionSample(timestamp, threadId, contentionDurationNs, 0, WStr(""), stack);
}

void ContentionProvider::SetBlockingThread(uint64_t osThreadId)
{
ManagedThreadInfo::CurrentThreadInfo->SetBlockingThread(osThreadId);
std::shared_ptr<ManagedThreadInfo> info;
if (osThreadId != 0 && _pManagedThreadList->TryGetThreadInfo(static_cast<uint32_t>(osThreadId), info))
{
ManagedThreadInfo::CurrentThreadInfo->SetBlockingThread(osThreadId, info->GetThreadName());
}
}

// .NET synchronous implementation: we are expecting to be called from the same thread that is contending.
// It means that the current thread will be stack walking itself.
void ContentionProvider::OnContention(double contentionDurationNs)
{
auto blockingThreadId = ManagedThreadInfo::CurrentThreadInfo->SetBlockingThread(0);
AddContentionSample(0, -1, contentionDurationNs, blockingThreadId, _emptyStack);
auto [blockingThreadId, blockingThreadName] = ManagedThreadInfo::CurrentThreadInfo->SetBlockingThread(0, WStr(""));
AddContentionSample(0, -1, contentionDurationNs, blockingThreadId, std::move(blockingThreadName), _emptyStack);
}

void ContentionProvider::AddContentionSample(uint64_t timestamp, uint32_t threadId, double contentionDurationNs, uint64_t blockingThreadId, const std::vector<uintptr_t>& stack)
void ContentionProvider::AddContentionSample(uint64_t timestamp, uint32_t threadId, double contentionDurationNs, uint64_t blockingThreadId, shared::WSTRING blockingThreadName, const std::vector<uintptr_t>& stack)
{
_lockContentionsCountMetric->Incr();
_lockContentionsDurationMetric->Add(contentionDurationNs);
Expand Down Expand Up @@ -208,7 +212,8 @@ void ContentionProvider::AddContentionSample(uint64_t timestamp, uint32_t thread

rawSample.ContentionDuration = contentionDurationNs;
rawSample.Bucket = std::move(bucket);
rawSample.BlockingThread = blockingThreadId;
rawSample.BlockingThreadId = blockingThreadId;
rawSample.BlockingThreadName = std::move(blockingThreadName);

Add(std::move(rawSample));
_sampledLockContentionsCountMetric->Incr();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class ContentionProvider :
private:
static std::string GetBucket(double contentionDurationNs);
static std::vector<SampleValueType> SampleTypeDefinitions;
void AddContentionSample(uint64_t timestamp, uint32_t threadId, double contentionDurationNs, uint64_t blockingThreadId, const std::vector<uintptr_t>& stack);
void AddContentionSample(uint64_t timestamp, uint32_t threadId, double contentionDurationNs, uint64_t blockingThreadId, shared::WSTRING blockingThreadName, const std::vector<uintptr_t>& stack);

private:
static std::vector<uintptr_t> _emptyStack;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ struct ManagedThreadInfo : public IThreadInfo
inline bool IsThreadDestroyed();
inline bool IsDestroyed();
inline void SetThreadDestroyed();
inline uint64_t SetBlockingThread(uint64_t osThreadId);
inline std::pair<uint64_t, shared::WSTRING> SetBlockingThread(uint64_t osThreadId, shared::WSTRING name);

inline TraceContextTrackingInfo* GetTraceContextPointer();
inline std::uint64_t GetLocalRootSpanId() const;
Expand Down Expand Up @@ -153,6 +153,7 @@ struct ManagedThreadInfo : public IThreadInfo
std::int32_t _timerId;
#endif
uint64_t _blockingThreadId;
shared::WSTRING _blockingThreadName;
};

std::string ManagedThreadInfo::GetProfileThreadId()
Expand Down Expand Up @@ -406,9 +407,11 @@ inline void ManagedThreadInfo::SetThreadDestroyed()
_isThreadDestroyed = true;
}

inline uint64_t ManagedThreadInfo::SetBlockingThread(uint64_t osThreadId)
inline std::pair<uint64_t, shared::WSTRING> ManagedThreadInfo::SetBlockingThread(uint64_t osThreadId, shared::WSTRING name)
{
return std::exchange(_blockingThreadId, osThreadId);
auto oldId = std::exchange(_blockingThreadId, osThreadId);
auto oldName = std::exchange(_blockingThreadName, std::move(name));
return {oldId, oldName};
}

inline TraceContextTrackingInfo* ManagedThreadInfo::GetTraceContextPointer()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class RawContentionSample : public RawSample
inline static const std::string BucketLabelName = "Duration bucket";
inline static const std::string RawCountLabelName = "raw count";
inline static const std::string RawDurationLabelName = "raw duration";
inline static const std::string BlockingThreadInfo = "blocking thread";
inline static const std::string BlockingThreadIdLabelName = "blocking thread id";
inline static const std::string BlockingThreadNameLabelName = "blocking thread name";

public:
RawContentionSample() = default;
Expand All @@ -22,7 +23,8 @@ class RawContentionSample : public RawSample
RawSample(std::move(other)),
ContentionDuration(other.ContentionDuration),
Bucket(std::move(other.Bucket)),
BlockingThread(other.BlockingThread)
BlockingThreadId(other.BlockingThreadId),
BlockingThreadName(std::move(other.BlockingThreadName))
{
}

Expand All @@ -33,7 +35,8 @@ class RawContentionSample : public RawSample
RawSample::operator=(std::move(other));
ContentionDuration = other.ContentionDuration;
Bucket = std::move(other.Bucket);
BlockingThread = other.BlockingThread;
BlockingThreadId = other.BlockingThreadId;
BlockingThreadName = std::move(other.BlockingThreadName);
}
return *this;
}
Expand All @@ -49,13 +52,15 @@ class RawContentionSample : public RawSample
sample->AddNumericLabel(NumericLabel{RawCountLabelName, 1});
sample->AddNumericLabel(NumericLabel{RawDurationLabelName, static_cast<uint64_t>(ContentionDuration)});
sample->AddValue(static_cast<std::int64_t>(ContentionDuration), contentionDurationIndex);
if (BlockingThread != 0)
if (BlockingThreadId != 0)
{
sample->AddNumericLabel(NumericLabel{BlockingThreadInfo, BlockingThread});
sample->AddNumericLabel(NumericLabel{BlockingThreadIdLabelName, BlockingThreadId});
sample->AddLabel(Label{BlockingThreadNameLabelName, shared::ToString(BlockingThreadName)});
}
}

double ContentionDuration;
std::string Bucket;
uint64_t BlockingThread;
uint64_t BlockingThreadId;
shared::WSTRING BlockingThreadName;
};
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,19 @@ private static void AssertBlockingThreadLabel(string pprofDir)
var threadIds = SamplesHelper.GetThreadIds(pprofDir);
// get samples with lock-count value set and blocking thread info
var contentionSamples = SamplesHelper.GetSamples(pprofDir, "lock-count")
.Where(e => e.Labels.Any(x => x.Name == "blocking thread"));
.Where(e => e.Labels.Any(x => x.Name == "blocking thread id"));

contentionSamples.Should().NotBeEmpty();

foreach (var (_, labels, _) in contentionSamples)
{
var label = labels.FirstOrDefault(l => l.Name == "blocking thread");
label.Name.Should().NotBeNullOrWhiteSpace();
threadIds.Should().Contain(int.Parse(label.Value), $"Unknown blocking thread id {label.Value}");
var blockingThreadIdLabel = labels.FirstOrDefault(l => l.Name == "blocking thread id");
blockingThreadIdLabel.Name.Should().NotBeNullOrWhiteSpace();
threadIds.Should().Contain(int.Parse(blockingThreadIdLabel.Value), $"Unknown blocking thread id {blockingThreadIdLabel.Value}");

var blockingThreadNameLabel = labels.FirstOrDefault(l => l.Name == "blocking thread name");
blockingThreadIdLabel.Name.Should().NotBeNullOrWhiteSpace();
blockingThreadIdLabel.Value.Should().NotBeNullOrWhiteSpace();
}
}
}
Expand Down

0 comments on commit 0378b3b

Please sign in to comment.