简体   繁体   English

在 C# 中使用 ArrayPool 重新使用 memory 从 String 到字节数组的转换?

[英]Re-use memory from String to byte array conversion with ArrayPool in C#?

Is it possible to re-use memory that was used in a string to byte array conversion?是否可以重新使用在字符串到字节数组转换中使用的 memory?

The application has to send large strings over.network with 60fps.应用程序必须以 60fps 的速度通过网络发送大字符串。 This seems to put way too much pressure on the GC.这似乎给 GC 带来了太大的压力。 So is it possible to re-use the byte arrays created by the string conversion somehow?那么是否有可能以某种方式重新使用字符串转换创建的字节 arrays 呢?

These are my current serialization methods:这些是我当前的序列化方法:

public static byte[] SerializeJson(DrawDescriptionLayer layer)
{
    var s = JsonConvert.SerializeObject(layer, js);
    return Encoding.UTF8.GetBytes(s); //rent from array pool here
}

Or using streams:或者使用流:

public static byte[] SerializeJson2(DrawDescriptionLayer layer)
{
    using (var ms = new MemoryStream())
    using (StreamWriter writer = new StreamWriter(ms, Encoding.UTF8))
    using (JsonTextWriter jsonWriter = new JsonTextWriter(writer))
    {
        JsonSerializer ser = JsonSerializer.Create(js);
        ser.Serialize(jsonWriter, layer);
        jsonWriter.Flush();
        return ms.ToArray(); //rent from array pool here
    }
}

I am aware that i should write a custom binary serializer, but Newtonsoft.Json worked out of the box and the app uses third party types that have no serialization attributes.我知道我应该编写一个自定义二进制序列化程序,但 Newtonsoft.Json 开箱即用,该应用程序使用没有序列化属性的第三方类型。

If performance and memory allocation are major concerns, you should strongly consider using utf8json .如果性能和 memory 分配是主要问题,您应该强烈考虑使用utf8json

Instead of using both the slow JsonConvert.SerializeObject method, followed by the allocation-heavy UTF8.GetBytes , utf8json can do this in one pass: utf8json 不是同时使用缓慢的JsonConvert.SerializeObject方法,然后是分配繁重的UTF8.GetBytes ,而是一次完成:

public byte[] SerializeJson(DrawDescriptionLayer layer)
{
    return Utf8Json.JsonSerializer.Serialize(layer, Utf8Json.Resolvers.StandardResolver.Default);
}

The library is optimized towards performance and low allocation, and it's used in software like ElasticSearch's recommended .NET client.该库针对性能和低分配进行了优化,并用于 ElasticSearch 推荐的 .NET 客户端等软件中。

Also make sure that the DrawDescriptionLayer is a DTO that is highly optimized for cheap JSON serialization and doesn't contain anything not used in the.network transfer.还要确保DrawDescriptionLayer是一个 DTO,它针对廉价的 JSON 序列化进行了高度优化,并且不包含 .network 传输中未使用的任何内容。

Good luck!祝你好运!

As far as streams, Microsoft.IO.RecyclableMemoryStream was specifically created to reduce the cost of garbage collections incurred by frequent large allocations.就流而言, Microsoft.IO.RecyclableMemoryStream是专门为减少频繁大量分配产生的垃圾 collections 的成本而创建的。 You could modify your stream example like:您可以修改您的 stream 示例,例如:

private static readonly RecyclableMemoryStreamManager _manager = new RecyclableMemoryStreamManager();

public static byte[] SerializeJson2(DrawDescriptionLayer layer)
{
    using (var ms = _manager.GetStream())
    using (StreamWriter writer = new StreamWriter(ms, Encoding.UTF8))
    using (JsonTextWriter jsonWriter = new JsonTextWriter(writer))
    {
        JsonSerializer ser = JsonSerializer.Create(js);
        ser.Serialize(jsonWriter, layer);
        jsonWriter.Flush();
        return ms.ToArray();
    }
}

The use of ToArray(), however, copies into a new array that is never pooled, which according to the docs "... wipes out many of the benefits of RecyclableMemoryStream completely.".但是,使用 ToArray() 会复制到一个从未合并的新数组中,根据文档“...完全消除了 RecyclableMemoryStream 的许多好处。”。 So look into using GetBuffer() instead.所以考虑改用 GetBuffer() 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM