Skip to content

[API Proposal]: GetTotalAllocatedBytes for Thread #114789

Open
@nbcks

Description

@nbcks

Background and motivation

Currently there is a very useful method to get the allocated bytes for the current thread: GC.GetAllocatedBytesForCurrentThread. However, there is no way to get this for a given System.Threading.Thread object. This is useful for operations like iterating over threads and getting the allocations given what the thread is working on

The proposed method would be long System.Threading.Thread.GetAllocatedBytesForThread() as an instance method added to the System.Threading.Thread class.

All of this information already exists and can be accessed using csharp from the gc_alloc_context associated with the Thread_data. We have implemented this on windows using:

var plngBytesAllocated = pData.m_alloc_context.alloc_bytes + pData.m_alloc_context.alloc_bytes_uoh - (pData.m_alloc_context.alloc_limit - pData.m_alloc_context.alloc_ptr);
static unsafe ref Thread_data GetCurrentNativeThread()
{
    var currentNativeThread = GetNativeThread(Thread.CurrentThread);
    return ref Unsafe.AsRef<Thread_data>((void*)currentNativeThread);
}

[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_DONT_USE_InternalThread")]
static extern ref IntPtr GetNativeThread(Thread thread);

[StructLayout(LayoutKind.Sequential)]
unsafe struct Thread_data
{
    public nint vtable;
    public int m_state;
    public int m_fPreemptiveGCDisabled;
    public nint m_pFrame;
    public nint m_pDomain;
    public int m_ThreadId;
    public nint m_pHead;
    public LockEntry m_embeddedEntry;
    public nint m_pBlockingLock;
    public gc_alloc_context m_alloc_context;
    public nint m_thAllocContextObj;
    public nint m_pTEB;
}

[StructLayout(LayoutKind.Sequential)]
unsafe struct gc_alloc_context
{
    public nint alloc_ptr;
    public nint alloc_limit;
    public long alloc_bytes;
    public long alloc_bytes_uoh;
    public nint gc_reserved_1;
    public nint gc_reserved_2;
    public int alloc_count;
}

API Proposal

namespace System.Threading;

public class Thread
{
//....

  public long GetAllocatedBytesForThread()
  {
      // implementation
  }

}

var thread = System.Threading.Thread.CurrentThread;

Console.WriteLine($"Currently allocated bytes for thread: {thread.GetAllocatedBytesForThread()}");

API Usage

namespace System.Collections.Generic;

var thread = System.Threading.Thread.CurrentThread;

Console.WriteLine($"Currently allocated bytes for thread: {thread.GetAllocatedBytesForThread()}");

Alternative Designs

Potentially could be in GC via a static method that passes in the managed thread id: GC.GetAllocatedBytesForAThread(int threadID)

Risks

This is purely additive, so no breaking changes

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.ThreadinguntriagedNew issue has not been triaged by the area owner

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions