Skip to content

[API Proposal]: GetTotalAllocatedBytes for Thread #114789

@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

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions