C# 非托管内存中的可变字符串在托管空间中可用
注意:我的案例是在一个只处理字符串的旧API生态系统中,没有现代的.NET添加。 所以我非常需要一个没有分配的可变字符串。字符串每X毫秒更新一次,这样您就可以在几分钟内计算出它可以产生多少垃圾(StringBuilder在这里根本不相关)。我目前的方法是预先分配固定大小的字符串,并通过钉住、直接写入字符和在达到容量时自动脱落或抛出来对其进行变异 这个很好用。分配的字符串是长期存在的,因此最终GC会将其升级到Gen2,并且固定不会太麻烦它,从而最小化开销。但有两个主要问题:C# 非托管内存中的可变字符串在托管空间中可用,c#,.net,string,pointers,unmanaged-memory,C#,.net,String,Pointers,Unmanaged Memory,注意:我的案例是在一个只处理字符串的旧API生态系统中,没有现代的.NET添加。 所以我非常需要一个没有分配的可变字符串。字符串每X毫秒更新一次,这样您就可以在几分钟内计算出它可以产生多少垃圾(StringBuilder在这里根本不相关)。我目前的方法是预先分配固定大小的字符串,并通过钉住、直接写入字符和在达到容量时自动脱落或抛出来对其进行变异 这个很好用。分配的字符串是长期存在的,因此最终GC会将其升级到Gen2,并且固定不会太麻烦它,从而最小化开销。但有两个主要问题: 因为字符串是固定的,所
\0
填充它,虽然到目前为止,这在所有默认的网络/单声道功能和第三方的东西上都运行得很好,但是当字符串的长度为1024时,没有办法知道其他东西会有什么反应,但最后100个是\0
char[]
缓冲区和Span
/内存对字符串进行切片。当传递给其他方法时,可以将字符串的一部分转换为实际的字符串对象。当调用诸如Console.WriteLine
或UI方法之类的方法时,分配字符串对象的开销与正在进行的其他事情相比是无关紧要的
如果您有只接受string
的旧代码,您可能需要接受它所带来的限制,或者重写代码以接受内存/span表示
我强烈建议进行分析,看看这是否是频繁分配的实际问题。只要字符串适合小对象堆(SOH,即小于87kb),并且没有升级到gen 2,开销可能不会很大。SOH上的分配速度很快,运行第0代GC的时间不会直接与分配的数量成比例。因此,每隔几毫秒更新一次可能并不可怕。如果你说的是微秒,我会更担心。“GC会将它升级到Gen2,钉扎不会太麻烦它,从而最小化开销。”——这不一定是真的。如果字符串在gen0中被固定,那么GC可能会决定根本不升级它!如果它被推广,它仍然会阻碍压实。如果它是在gen2中被固定的,你可能是对的。我真的鼓励你不要走变异字符串的路线——有很多事情假设字符串不会变异。你不能用字符数组吗。NET字符串以长度开头,因此不能将字符数组的任意位分割成字符串,因为它没有相应的头。如果可以,我会在内存中保留一个经过变异的char[]
。当您需要将其转换为字符串以传递到控制台.WriteLine
等(我假设您不是每X ms这么做!)时,请使用string.Create
将char[]
的相关部分复制到新字符串中。不,我有一个只接受字符串的旧API/生态系统。如果我有能力使用字符数组或跨度,这个问题就不存在了。你提到的所有这些建议我已经说过很多次了,它们在这个具体案例中根本不相关。是的,但是因为你没有提到它们,人们会建议它们。我不是一个读心术的人!