Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Profiler] Add Sample value type provider #4480

Merged
merged 3 commits into from
Aug 28, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "Log.h"
#include "MetricsRegistry.h"
#include "OsSpecificApi.h"
#include "SampleValueTypeProvider.h"

#include "shared/src/native-src/com_ptr.h"
#include "shared/src/native-src/string.h"
Expand All @@ -22,12 +23,10 @@
std::vector<SampleValueType> AllocationsProvider::SampleTypeDefinitions(
{
{"alloc-samples", "count"},
{"alloc-size", "bytes"}
});

{"alloc-size", "bytes"}});

AllocationsProvider::AllocationsProvider(
uint32_t valueOffset,
SampleValueTypeProvider& valueTypeProvider,
ICorProfilerInfo4* pCorProfilerInfo,
IManagedThreadList* pManagedThreadList,
IFrameStore* pFrameStore,
Expand All @@ -38,7 +37,28 @@ AllocationsProvider::AllocationsProvider(
ISampledAllocationsListener* pListener,
MetricsRegistry& metricsRegistry)
:
CollectorBase<RawAllocationSample>("AllocationsProvider", valueOffset, SampleTypeDefinitions.size(), pThreadsCpuManager, pFrameStore, pAppDomainStore, pRuntimeIdStore, pConfiguration),
AllocationsProvider(
valueTypeProvider.GetOrRegister(SampleTypeDefinitions),
pCorProfilerInfo, pManagedThreadList, pFrameStore,
pThreadsCpuManager, pAppDomainStore, pRuntimeIdStore,
pConfiguration,
pListener,
metricsRegistry)
{
}

AllocationsProvider::AllocationsProvider(
std::vector<SampleValueTypeProvider::Offset> valueTypes,
ICorProfilerInfo4* pCorProfilerInfo,
IManagedThreadList* pManagedThreadList,
IFrameStore* pFrameStore,
IThreadsCpuManager* pThreadsCpuManager,
IAppDomainStore* pAppDomainStore,
IRuntimeIdStore* pRuntimeIdStore,
IConfiguration* pConfiguration,
ISampledAllocationsListener* pListener,
MetricsRegistry& metricsRegistry) :
CollectorBase<RawAllocationSample>("AllocationsProvider", std::move(valueTypes), pThreadsCpuManager, pFrameStore, pAppDomainStore, pRuntimeIdStore, pConfiguration),
_pCorProfilerInfo(pCorProfilerInfo),
_pManagedThreadList(pManagedThreadList),
_pFrameStore(pFrameStore),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class IThreadsCpuManager;
class IAppDomainStore;
class IRuntimeIdStore;
class ISampledAllocationsListener;
class SampleValueTypeProvider;


class AllocationsProvider
Expand All @@ -27,11 +28,20 @@ class AllocationsProvider
public IAllocationsListener
{
public:
static std::vector<SampleValueType> SampleTypeDefinitions;
AllocationsProvider(
SampleValueTypeProvider& valueTypeProvider,
ICorProfilerInfo4* pCorProfilerInfo,
IManagedThreadList* pManagedThreadList,
IFrameStore* pFrameStore,
IThreadsCpuManager* pThreadsCpuManager,
IAppDomainStore* pAppDomainStore,
IRuntimeIdStore* pRuntimeIdStore,
IConfiguration* pConfiguration,
ISampledAllocationsListener* pListener,
MetricsRegistry& metricsRegistry);

public:
AllocationsProvider(
uint32_t valueOffset,
std::vector<SampleValueTypeProvider::Offset> valueTypeProvider,
ICorProfilerInfo4* pCorProfilerInfo,
IManagedThreadList* pManagedThreadList,
IFrameStore* pFrameStore,
Expand All @@ -50,6 +60,8 @@ class AllocationsProvider
uint64_t allocationAmount) override;

private:
static std::vector<SampleValueType> SampleTypeDefinitions;

ICorProfilerInfo4* _pCorProfilerInfo;
IManagedThreadList* _pManagedThreadList;
IFrameStore* _pFrameStore;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "IThreadsCpuManager.h"
#include "ProviderBase.h"
#include "RawSample.h"
#include "SampleValueTypeProvider.h"

#include "shared/src/native-src/string.h"

Expand Down Expand Up @@ -51,27 +52,21 @@ class CollectorBase
public:
CollectorBase<TRawSample>(
const char* name,
uint32_t valueOffset,
std::size_t nbValues,
std::vector<SampleValueTypeProvider::Offset> valueOffsets,
IThreadsCpuManager* pThreadsCpuManager,
IFrameStore* pFrameStore,
IAppDomainStore* pAppDomainStore,
IRuntimeIdStore* pRuntimeIdStore,
IConfiguration* pConfiguration
) :
ProviderBase(name),
_valueOffset{valueOffset},
_pFrameStore{pFrameStore},
_pAppDomainStore{pAppDomainStore},
_pRuntimeIdStore{pRuntimeIdStore},
_pThreadsCpuManager{pThreadsCpuManager},
_isTimestampsAsLabelEnabled{pConfiguration->IsTimestampsAsLabelEnabled()}
{
_valueOffsets.reserve(nbValues);
for (auto i = _valueOffset; i < _valueOffset + nbValues; i++)
{
_valueOffsets.push_back(i);
}
_valueOffsets = std::move(valueOffsets);
}

// interfaces implementation
Expand Down Expand Up @@ -130,7 +125,7 @@ class CollectorBase
}

// allow inherited classes to add values and specific labels
rawSample.OnTransform(sample, _valueOffset);
rawSample.OnTransform(sample, _valueOffsets);

return sample;
}
Expand All @@ -141,7 +136,7 @@ class CollectorBase
return OpSysTools::GetHighPrecisionTimestamp();
}

std::vector<std::uintptr_t> const& GetValueOffsets() const
std::vector<SampleValueTypeProvider::Offset> const& GetValueOffsets() const
{
return _valueOffsets;
}
Expand Down Expand Up @@ -239,7 +234,6 @@ class CollectorBase
}

private:
uint32_t _valueOffset = 0;
IFrameStore* _pFrameStore = nullptr;
IAppDomainStore* _pAppDomainStore = nullptr;
IRuntimeIdStore* _pRuntimeIdStore = nullptr;
Expand All @@ -253,5 +247,5 @@ class CollectorBase

std::mutex _rawSamplesLock;
std::list<TRawSample> _collectedSamples;
std::vector<std::uintptr_t> _valueOffsets;
std::vector<SampleValueTypeProvider::Offset> _valueOffsets;
};
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "IUpscaleProvider.h"
#include "OsSpecificApi.h"
#include "Sample.h"
#include "SampleValueTypeProvider.h"


std::vector<SampleValueType> ContentionProvider::SampleTypeDefinitions(
Expand All @@ -22,7 +23,7 @@ std::vector<SampleValueType> ContentionProvider::SampleTypeDefinitions(


ContentionProvider::ContentionProvider(
uint32_t valueOffset,
SampleValueTypeProvider& valueTypeProvider,
ICorProfilerInfo4* pCorProfilerInfo,
IManagedThreadList* pManagedThreadList,
IFrameStore* pFrameStore,
Expand All @@ -32,7 +33,7 @@ ContentionProvider::ContentionProvider(
IConfiguration* pConfiguration,
MetricsRegistry& metricsRegistry)
:
CollectorBase<RawContentionSample>("ContentionProvider", valueOffset, SampleTypeDefinitions.size(), pThreadsCpuManager, pFrameStore, pAppDomainStore, pRuntimeIdStore, pConfiguration),
CollectorBase<RawContentionSample>("ContentionProvider", valueTypeProvider.GetOrRegister(SampleTypeDefinitions), pThreadsCpuManager, pFrameStore, pAppDomainStore, pRuntimeIdStore, pConfiguration),
_pCorProfilerInfo{pCorProfilerInfo},
_pManagedThreadList{pManagedThreadList},
_sampler(pConfiguration->ContentionSampleLimit(), pConfiguration->GetUploadInterval(), false),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,17 @@ class IFrameStore;
class IThreadsCpuManager;
class IAppDomainStore;
class IRuntimeIdStore;
class SampleValueTypeProvider;


class ContentionProvider :
public CollectorBase<RawContentionSample>,
public IContentionListener,
public IUpscaleProvider
{
public:
static std::vector<SampleValueType> SampleTypeDefinitions;

public:
ContentionProvider(
uint32_t valueOffset,
SampleValueTypeProvider& valueTypeProvider,
ICorProfilerInfo4* pCorProfilerInfo,
IManagedThreadList* pManagedThreadList,
IFrameStore* pFrameStore,
Expand All @@ -50,6 +48,8 @@ class ContentionProvider :
private:
static std::string GetBucket(double contentionDurationNs);

static std::vector<SampleValueType> SampleTypeDefinitions;

ICorProfilerInfo4* _pCorProfilerInfo;
IManagedThreadList* _pManagedThreadList;
GroupSampler<std::string> _sampler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "RuntimeIdStore.h"
#include "RuntimeInfo.h"
#include "Sample.h"
#include "SampleValueTypeProvider.h"
#include "StackSamplerLoopManager.h"
#include "ThreadsCpuManager.h"
#include "WallTimeProvider.h"
Expand Down Expand Up @@ -128,35 +129,22 @@ bool CorProfilerCallback::InitializeServices()

auto* pRuntimeIdStore = RegisterService<RuntimeIdStore>();

// Each sample contains a vector of values.
// The list of a provider value definitions is available statically.
// Based on previous providers list, an offset in the values vector is computed and passed to the provider constructor.
// So a provider knows which value slot can be used to store its value(s).
uint32_t valuesOffset = 0;
std::vector<SampleValueType> sampleTypeDefinitions;
auto valueTypeProvider = SampleValueTypeProvider();

if (_pConfiguration->IsWallTimeProfilingEnabled())
{
auto valueTypes = WallTimeProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pWallTimeProvider = RegisterService<WallTimeProvider>(valuesOffset, _pThreadsCpuManager, _pFrameStore.get(), _pAppDomainStore.get(), pRuntimeIdStore, _pConfiguration.get());
valuesOffset += static_cast<uint32_t>(valueTypes.size());
_pWallTimeProvider = RegisterService<WallTimeProvider>(valueTypeProvider, _pThreadsCpuManager, _pFrameStore.get(), _pAppDomainStore.get(), pRuntimeIdStore, _pConfiguration.get());
}

if (_pConfiguration->IsCpuProfilingEnabled())
{
auto valueTypes = CpuTimeProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pCpuTimeProvider = RegisterService<CpuTimeProvider>(valuesOffset, _pThreadsCpuManager, _pFrameStore.get(), _pAppDomainStore.get(), pRuntimeIdStore, _pConfiguration.get());
valuesOffset += static_cast<uint32_t>(valueTypes.size());
_pCpuTimeProvider = RegisterService<CpuTimeProvider>(valueTypeProvider, _pThreadsCpuManager, _pFrameStore.get(), _pAppDomainStore.get(), pRuntimeIdStore, _pConfiguration.get());
}

if (_pConfiguration->IsExceptionProfilingEnabled())
{
auto valueTypes = ExceptionsProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pExceptionsProvider = RegisterService<ExceptionsProvider>(
valuesOffset,
valueTypeProvider,
_pCorProfilerInfo,
_pManagedThreadList,
_pFrameStore.get(),
Expand All @@ -165,7 +153,6 @@ bool CorProfilerCallback::InitializeServices()
_pAppDomainStore.get(),
pRuntimeIdStore,
_metricsRegistry);
valuesOffset += static_cast<uint32_t>(valueTypes.size());
}

// _pCorProfilerInfoEvents must have been set for any CLR events-based profiler to work
Expand All @@ -176,10 +163,8 @@ bool CorProfilerCallback::InitializeServices()
{
if (_pCorProfilerInfoLiveHeap != nullptr)
{
auto valueTypes = LiveObjectsProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pLiveObjectsProvider = RegisterService<LiveObjectsProvider>(
valuesOffset,
valueTypeProvider,
_pCorProfilerInfoLiveHeap,
_pManagedThreadList,
_pFrameStore.get(),
Expand All @@ -188,12 +173,9 @@ bool CorProfilerCallback::InitializeServices()
pRuntimeIdStore,
_pConfiguration.get(),
_metricsRegistry);
valuesOffset += static_cast<uint32_t>(valueTypes.size());

valueTypes = AllocationsProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pAllocationsProvider = RegisterService<AllocationsProvider>(
valuesOffset,
valueTypeProvider,
_pCorProfilerInfo,
_pManagedThreadList,
_pFrameStore.get(),
Expand All @@ -204,7 +186,6 @@ bool CorProfilerCallback::InitializeServices()
_pLiveObjectsProvider,
_metricsRegistry
);
valuesOffset += static_cast<uint32_t>(valueTypes.size());

if (!_pConfiguration->IsAllocationProfilingEnabled())
{
Expand All @@ -220,10 +201,8 @@ bool CorProfilerCallback::InitializeServices()
// check for allocations profiling only (without heap profiling)
if (_pConfiguration->IsAllocationProfilingEnabled() && (_pAllocationsProvider == nullptr))
{
auto valueTypes = AllocationsProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pAllocationsProvider = RegisterService<AllocationsProvider>(
valuesOffset,
valueTypeProvider,
_pCorProfilerInfo,
_pManagedThreadList,
_pFrameStore.get(),
Expand All @@ -234,15 +213,12 @@ bool CorProfilerCallback::InitializeServices()
nullptr, // no listener
_metricsRegistry
);
valuesOffset += static_cast<uint32_t>(valueTypes.size());
}

if (_pConfiguration->IsContentionProfilingEnabled())
{
auto valueTypes = ContentionProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pContentionProvider = RegisterService<ContentionProvider>(
valuesOffset,
valueTypeProvider,
_pCorProfilerInfo,
_pManagedThreadList,
_pFrameStore.get(),
Expand All @@ -252,32 +228,27 @@ bool CorProfilerCallback::InitializeServices()
_pConfiguration.get(),
_metricsRegistry
);
valuesOffset += static_cast<uint32_t>(valueTypes.size());
}

if (_pConfiguration->IsGarbageCollectionProfilingEnabled())
{
// Use the same value type for timeline
auto valueTypes = GarbageCollectionProvider::SampleTypeDefinitions;
sampleTypeDefinitions.insert(sampleTypeDefinitions.end(), valueTypes.cbegin(), valueTypes.cend());
_pStopTheWorldProvider = RegisterService<StopTheWorldGCProvider>(
valuesOffset,
valueTypeProvider,
_pFrameStore.get(),
_pThreadsCpuManager,
_pAppDomainStore.get(),
pRuntimeIdStore,
_pConfiguration.get()
);
_pGarbageCollectionProvider = RegisterService<GarbageCollectionProvider>(
valuesOffset,
valueTypeProvider,
_pFrameStore.get(),
_pThreadsCpuManager,
_pAppDomainStore.get(),
pRuntimeIdStore,
_pConfiguration.get(),
_metricsRegistry
);
valuesOffset += static_cast<uint32_t>(valueTypes.size());
}
else
{
Expand Down Expand Up @@ -311,6 +282,7 @@ bool CorProfilerCallback::InitializeServices()

// Avoid iterating twice on all providers in order to inject this value in each constructor
// and store it in CollectorBase so it can be used in TransformRawSample (where the sample is created)
auto const& sampleTypeDefinitions = valueTypeProvider.GetValueTypes();
Sample::ValuesCount = sampleTypeDefinitions.size();

// compute enabled profilers based on configuration and receivable CLR events
Expand All @@ -333,7 +305,7 @@ bool CorProfilerCallback::InitializeServices()
// The different elements of the libddprof pipeline are created and linked together
// i.e. the exporter is passed to the aggregator and each provider is added to the aggregator.
_pExporter = std::make_unique<LibddprofExporter>(
std::move(sampleTypeDefinitions),
sampleTypeDefinitions,
_pConfiguration.get(),
_pApplicationStore,
_pRuntimeInfo.get(),
Expand Down
Loading