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

Support filtering ObjectAllocated callback for pinned object heap allocation only #53134

Closed
cshung opened this issue May 23, 2021 · 2 comments · Fixed by #55448
Closed

Support filtering ObjectAllocated callback for pinned object heap allocation only #53134

cshung opened this issue May 23, 2021 · 2 comments · Fixed by #55448
Labels
area-Diagnostics-coreclr enhancement Product code improvement that does NOT require public API changes/additions
Milestone

Comments

@cshung
Copy link
Member

cshung commented May 23, 2021

Problem

In ICorProfiler, we can have the runtime to notify the profiler when an object is allocated on the large object heap only. We should have a similar option for the pinned object heap.

The remainder of the issue is meant for explaining to @Yauk how to contribute to this issue.

Background

If we wanted to capture the object allocations in an ICorProfiler based profiler, we can enable it when the profiler initialize as follow:

pCorProfilerInfo->SetEventMask2(COR_PRF_ENABLE_OBJECT_ALLOCATED, COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)

And then the profiler's implementation for ObjectAllocated will be invoked when a large object is allocated.

A prototype that illustrates how that can be done is available in my private branch here.

How to run the prototype

Build for the first time

The build instruction should be clear about how to install the prerequisites, build the product and run the tests. Here is just a summary of the commands to run the prototype.

For building the CoreCLR runtime and the libraries:

build.cmd -s clr
build.cmd -c release -s libs /p:RuntimeConfiguration=Debug

To build ALL the tests:

cd src\tests
build.cmd
cd ..\..

To run all the gcallocate test case:

set CORE_ROOT=C:\Dev\runtime\artifacts\tests\coreclr\Windows.x64.Debug\Tests\Core_Root
cd C:\Dev\runtime\artifacts\tests\coreclr\windows.x64.Debug\profiler\gc\gcallocate
gcallocate.cmd

If all is well, we should hit an assert here because the ObjectAllocated callback is called as we expect it to.

https://github.com/cshung/runtime/blob/a1752998e2284d20a393d429390bfe7ab0ff2d5c/src/tests/profiler/native/gcallocateprofiler/gcallocateprofiler.cpp#L29

To make changes

I understand the building process takes a lot of time, and it would be bad if we have to wait that long for any changes, fortunately, we don't have to.

Rebuilding the CoreCLR, note that we need to update the test layouts (aka CORE_ROOT):

build.cmd -s clr
cd src\coreclr
build.cmd generatelayoutonly
cd ..\..

Changing the profiler is a bit more involved, but not all that hard, we need to setup the build system once.

cd C:\Dev\runtime\src\tests\profiler\native
mkdir build
cd build
cmake ..

And then we can just build, note that we need to make sure the test is running the built profiler.

cd C:\Dev\runtime\src\tests\profiler\native\build
msbuild ALL_BUILD.vcxproj
copy /y C:\Dev\runtime\src\tests\profiler\native\build\Debug\Profiler.dll C:\Dev\runtime\artifacts\tests\coreclr\windows.x64.Debug\profiler\gc\gcallocate\

Last but not least, we might want to change the managed test code, in that case we need to remove the dependency to the CMakeLists.txt here

https://github.com/cshung/runtime/blob/a1752998e2284d20a393d429390bfe7ab0ff2d5c/src/tests/profiler/gc/gcallocate.csproj#L21

and then run this:

cd C:\Dev\runtime\src\tests\profiler\gc
c:\dev\runtime\dotnet.cmd build gcallocate.csproj

How to get started

Here is where the COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED event mask is consumed.

inline BOOL CORProfilerTrackLargeAllocations()
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
CANNOT_TAKE_LOCK;
}
CONTRACTL_END;
return
(CORProfilerPresent() &&
((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED));
}

and therefore it is checked here during allocation to fire callbacks

if (TrackAllocations() ||
(TrackLargeAllocations() && flags & GC_ALLOC_LARGE_OBJECT_HEAP))
{
OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
GCPROTECT_BEGIN(objref);
ProfilerObjectAllocatedCallback(objref, (ClassID) orObject->GetTypeHandle().AsPtr());
GCPROTECT_END();
orObject = (TObj*) OBJECTREFToObject(objref);
}

There we should have a different case for GC_ALLOC_PINNED_OBJECT_HEAP

If all goes well, we should be able to add a GC.AllocateArray in the gcallocate test case and have the assertion fired for it (together with some runtime internal pinned object heap allocation)

Testing

Last but not least, we should have some testing for this capability, we should be able to reuse this test case for it, of course, we should not be doing assert(false), change it to something like counting the number of events fired for the object allocated event should be sufficient. (Do not hard code counts as things changes, check > 0 should be good enough)

@davmason

@ghost
Copy link

ghost commented May 23, 2021

Tagging subscribers to this area: @tommcdon
See info in area-owners.md if you want to be subscribed.

Issue Details

Problem

In ICorProfiler, we can have the runtime to notify the profiler when an object is allocated on the large object heap only. We should have a similar option for the pinned object heap.

The remainder of the issue is meant for explaining to our external contributors how to contribute to this issue.

Background

If we wanted to capture the object allocations in an ICorProfiler based profiler, we can enable it when the profiler initialize as follow:

pCorProfilerInfo->SetEventMask2(COR_PRF_ENABLE_OBJECT_ALLOCATED, COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)

And then the profiler's implementation for ObjectAllocated will be invoked when a large object is allocated.

A prototype that illustrates how that can be done is available in my private branch here.

How to run the prototype

Build for the first time

The build instruction should be clear about how to install the prerequisites, build the product and run the tests. Here is just a summary of the commands to run the prototype.

For building the CoreCLR runtime and the libraries:

build.cmd -s clr
build.cmd -c release -s libs /p:RuntimeConfiguration=Debug

To build ALL the tests:

cd src\coreclr
build.cmd
cd ..\..

To run all the gcallocate test case:

set CORE_ROOT=C:\Dev\runtime\artifacts\tests\coreclr\Windows.x64.Debug\Tests\Core_Root
cd C:\Dev\runtime\artifacts\tests\coreclr\windows.x64.Debug\profiler\gc\gcallocate
gcallocate.cmd

If all is well, we should hit an assert here because the ObjectAllocated callback is called as we expect it to.

https://github.com/cshung/runtime/blob/a1752998e2284d20a393d429390bfe7ab0ff2d5c/src/tests/profiler/native/gcallocateprofiler/gcallocateprofiler.cpp#L29

To make changes

I understand the building process takes a lot of time, and it would be bad if we have to wait that long for any changes, fortunately, we don't have to.

Rebuilding the CoreCLR, note that we need to update the test layouts (aka CORE_ROOT):

build.cmd -s clr
cd src\coreclr
build.cmd generatelayoutonly
cd ..\..

Changing the profiler is a bit more involved, but not all that hard, we need to setup the build system once.

C:\Dev\runtime\src\tests\profiler\native
mkdir build
cd build
cmake ..

And then we can just build, note that we need to make sure the test is running the built profiler.

C:\Dev\runtime\src\tests\profiler\native\build
msbuild ALL_BUILD.vcxproj
copy /y C:\Dev\runtime\src\tests\profiler\native\build\Debug\Profiler.dll C:\Dev\runtime\artifacts\tests\coreclr\windows.x64.Debug\profiler\gc\gcallocate\

Last but not least, we might want to change the managed test code, in that case we need to remove the dependency to the CMakeLists.txt here

https://github.com/cshung/runtime/blob/a1752998e2284d20a393d429390bfe7ab0ff2d5c/src/tests/profiler/gc/gcallocate.csproj#L21

and then run this:

cd C:\Dev\runtime\src\tests\profiler\gc
c:\dev\runtime\dotnet.cmd build gcallocate.csproj

How to get started

Here is where the COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED event mask is consumed.

inline BOOL CORProfilerTrackLargeAllocations()
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
CANNOT_TAKE_LOCK;
}
CONTRACTL_END;
return
(CORProfilerPresent() &&
((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED));
}

and therefore it is checked here during allocation to fire callbacks

if (TrackAllocations() ||
(TrackLargeAllocations() && flags & GC_ALLOC_LARGE_OBJECT_HEAP))
{
OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
GCPROTECT_BEGIN(objref);
ProfilerObjectAllocatedCallback(objref, (ClassID) orObject->GetTypeHandle().AsPtr());
GCPROTECT_END();
orObject = (TObj*) OBJECTREFToObject(objref);
}

There we should have a different case for GC_ALLOC_PINNED_OBJECT_HEAP

If all goes well, we should be able to add a GC.AllocateArray in the gcallocate test case and have the assertion fired for it (together with some runtime internal pinned object heap allocation)

Testing

Last but not least, we should have some testing for this capability, we should be able to reuse this test case for it, of course, we should not be doing assert(false), change it to something like counting the number of events fired for the object allocated event should be sufficient. (Do not hard code counts as things changes, check > 0 should be good enough)

@davmason

Author: cshung
Assignees: -
Labels:

area-Diagnostics-coreclr

Milestone: -

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label May 23, 2021
@tommcdon tommcdon added the enhancement Product code improvement that does NOT require public API changes/additions label May 23, 2021
@tommcdon tommcdon added this to the 6.0.0 milestone May 23, 2021
@tommcdon tommcdon removed the untriaged New issue has not been triaged by the area owner label May 23, 2021
@Yauk
Copy link
Contributor

Yauk commented Jun 8, 2021

Thanks for the detailed info, @cshung. This helps a lot and I am now working on this issue.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Diagnostics-coreclr enhancement Product code improvement that does NOT require public API changes/additions
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants