Skip to content

Commit

Permalink
[Profiler] Add Sample value type provider (#4480)
Browse files Browse the repository at this point in the history
* Add Sample value type provider
* Address comment
  • Loading branch information
gleocadie authored Aug 28, 2023
1 parent ed96327 commit b1727e6
Show file tree
Hide file tree
Showing 38 changed files with 382 additions and 152 deletions.
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

0 comments on commit b1727e6

Please sign in to comment.