在.Net Runtime源码的issues看到GC一个关于新增的API,用于获取GC的配置信息. .Net 7新功能的提交已经暂停了,在八月份会发布RC1,同时新功能代码的提交到.Net 8中,后面差不多四个月的时间用来处理Bug和补充新增API的文档.
GetConfigurationVariables如何使用
GetConfigurationVariables使用是比较简单的.这里就不代码展示了,这里看目前获取到GC的配置信息:
打印GetConfigurationVariables获取到的GC配置信息
//GC配置信息类型有3种,int类型/字符串(utf-8编码)/布尔类型 在RuntimeImports.cs文件
internal enum GCConfigurationType
{
Int64,
StringUtf8,
Boolean
}
internal struct GCConfigurationContext
{
internal Dictionary Configurations; //定义一个字典变量,用于存放GC配置信息的key和value
}
[UnmanagedCallersOnly]
private static unsafe void Callback(void* configurationContext, void* name, void* publicKey, RuntimeImports.GCConfigurationType type, long data)
{
// If the public key is null, it means that the corresponding configuration isn't publicly available
// and therefore, we shouldn't add it to the configuration dictionary to return to the user.
if (publicKey == null)
{
return;
}
Debug.Assert(name != null);
Debug.Assert(configurationContext != null);
ref GCConfigurationContext context = ref Unsafe.As(ref *(byte*)configurationContext);
Debug.Assert(context.Configurations != null);
Dictionary configurationDictionary = context.Configurations!;
string nameAsString = Marshal.PtrToStringUTF8((IntPtr)name)!;
switch (type)
{
case RuntimeImports.GCConfigurationType.Int64: //处理配置value为int类型
configurationDictionary[nameAsString] = data;
break;
case RuntimeImports.GCConfigurationType.StringUtf8: //处理配置value是字符串
{
string? dataAsString = Marshal.PtrToStringUTF8((IntPtr)data);
configurationDictionary[nameAsString] = dataAsString ?? string.Empty;
break;
}
case RuntimeImports.GCConfigurationType.Boolean: //处理配置value为布尔类型
configurationDictionary![nameAsString] = data != 0;
break;
}
}
///
/// Gets the Configurations used by the Garbage Collector. The value of these configurations used don't neccessarily have to be the same as the ones that are passed by the user.
/// For example for the "GCHeapCount" configuration, if the user supplies a value higher than the number of CPUs, the configuration that will be used is that of the number of CPUs.
/// A Read Only Dictionary with configuration names and values of the configuration as the keys and values of the dictionary, respectively.
///
public static unsafe IReadOnlyDictionary GetConfigurationVariables()
{
GCConfigurationContext context = new GCConfigurationContext
{
Configurations = new Dictionary()
};
//RuntimeImports.cs 声明和定义了与CLR交互的类型和函数原型
//RhEnumerateConfigurationValues在CLR内部实现的,将GCConfigurationContext转为指针,传递到CLR中,并将Callback作为回调函数传入
//在CLR内部调用EnumerateConfigurationValues函数,每获取一次GC配置项,插入到context下的Configurations字典中
RuntimeImports.RhEnumerateConfigurationValues(Unsafe.AsPointer(ref context), &Callback);
return context.Configurations!;
}
//设置GC配置项的值
GCConfig::SetGCLargePages(gc_heap::use_large_pages_p);
GCConfig::SetGCHeapHardLimit(static_cast(gc_heap::heap_hard_limit));
GCConfig::SetGCHeapHardLimitSOH(static_cast(gc_heap::heap_hard_limit_oh[soh]));
GCConfig::SetGCHeapHardLimitLOH(static_cast(gc_heap::heap_hard_limit_oh[loh]));
GCConfig::SetGCHeapHardLimitPOH(static_cast(gc_heap::heap_hard_limit_oh[poh]));
//获取和设置 配置项的值 宏***
#define BOOL_CONFIG(name, unused_private_key, unused_public_key, default, unused_doc) \
bool GCConfig::Get##name() { return s_##name; } \
void GCConfig::Set##name(bool value) { s_Updated##name = value; } \
bool GCConfig::s_##name = default; \
bool GCConfig::s_Updated##name = default;
#define INT_CONFIG(name, unused_private_key, unused_public_key, default, unused_doc) \
int64_t GCConfig::Get##name() { return s_##name; } \
void GCConfig::Set##name(int64_t value) { s_Updated##name = value; } \
int64_t GCConfig::s_##name = default; \
int64_t GCConfig::s_Updated##name = default;
// String configs are not cached because 1) they are rare and
// not on hot paths and 2) they involve transfers of ownership
// of EE-allocated strings, which is potentially complicated.
#define STRING_CONFIG(name, private_key, public_key, unused_doc) \
GCConfigStringHolder GCConfig::Get##name() \
{ \
const char* resultStr = nullptr; \
GCToEEInterface::GetStringConfigValue(private_key, public_key, &resultStr); \
return GCConfigStringHolder(resultStr); \
}
//获取配置的值
void GCConfig::EnumerateConfigurationValues(void* context, ConfigurationValueFunc configurationValueFunc)
{
#define INT_CONFIG(name, unused_private_key, public_key, default, unused_doc) \
configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::Int64, static_cast(s_Updated##name));
#define STRING_CONFIG(name, private_key, public_key, unused_doc) \
{ \
const char* resultStr = nullptr; \
GCToEEInterface::GetStringConfigValue(private_key, public_key, &resultStr); \
GCConfigStringHolder holder(resultStr); \
configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::StringUtf8, reinterpret_cast(resultStr)); \
}
#define BOOL_CONFIG(name, unused_private_key, public_key, default, unused_doc) \
configurationValueFunc(context, (void*)(#name), (void*)(public_key), GCConfigurationType::Boolean, static_cast(s_Updated##name));
GC_CONFIGURATION_KEYS
#undef BOOL_CONFIG
#undef INT_CONFIG
#undef STRING_CONFIG
}
个人能力有限,如果您发现有什么不对,请私信我
如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流
留言与评论(共有 0 条评论) “” |