首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >.NET 7 JsonDocument内存泄漏?

.NET 7 JsonDocument内存泄漏?
EN

Stack Overflow用户
提问于 2022-11-21 07:54:57
回答 1查看 68关注 0票数 -2

最初的内存使用量为4660 K,然后增加到6920 K,但最终没有减少。

演示

代码语言:javascript
复制
static void Main(string[] args)
{
    string data = File.ReadAllText("./generated.json");
    Console.WriteLine("Begin parsing data...");
    for (var i = 0; i < 100; i++)
    {
        using (JsonDocument jsonDocument = JsonDocument.Parse(data))
        {
        }
        Thread.Sleep(650);
    }
    Console.WriteLine("Batch task ends...");
    GC.Collect();
    Console.ReadLine();
}

这是我的generated.json

EN

回答 1

Stack Overflow用户

发布于 2022-11-21 08:15:19

如果有漏洞,每个.NET Core都会注意到,因为System.Text.Json是ASP.NET核心的核心。事实上,这个问题的代码将内存消耗减少了99倍。

构建System.Text.Json命名空间中的类是为了尽可能减少分配,这不仅是为了减少内存消耗,也是为了提高速度。分配和垃圾收集缓冲区是昂贵的,特别是对于大型缓冲区。与其只为下一次调用创建一个新的类似缓冲区,不如重用缓冲区。

他们这样做的方法之一是使用池缓冲区,而不是每次分配一个新的缓冲区。JsonDocument的处置释放它使用的共享缓冲区,因此可以重用它们:

代码语言:javascript
复制
    public void Dispose()
    {
        int length = _utf8Json.Length;
        if (length == 0 || !IsDisposable)
        {
            return;
        }

        _parsedData.Dispose();
        _utf8Json = ReadOnlyMemory<byte>.Empty;

        if (_extraRentedArrayPoolBytes != null)
        {
            byte[]? extraRentedBytes = Interlocked.Exchange<byte[]?>(ref _extraRentedArrayPoolBytes, null);

            if (extraRentedBytes != null)
            {
                // When "extra rented bytes exist" it contains the document,
                // and thus needs to be cleared before being returned.
                extraRentedBytes.AsSpan(0, length).Clear();
                ArrayPool<byte>.Shared.Return(extraRentedBytes);
            }
        }
        else if (_extraPooledByteBufferWriter != null)
        {
            PooledByteBufferWriter? extraBufferWriter = Interlocked.Exchange<PooledByteBufferWriter?>(ref _extraPooledByteBufferWriter, null);
            extraBufferWriter?.Dispose();
        }
    }

所有调用都涉及返回池的池缓冲区和对象。即使是_parsedData.Dispose(),最终调用ArrayPool.Shared.Return(数据)

代码语言:javascript
复制
        public void Dispose()
        {
            byte[]? data = Interlocked.Exchange(ref _data, null!);
            if (data == null)
            {
                return;
            }

            Debug.Assert(!_isLocked, "Dispose called on a locked database");

            // The data in this rented buffer only conveys the positions and
            // lengths of tokens in a document, but no content; so it does not
            // need to be cleared.
            ArrayPool<byte>.Shared.Return(data);
            Length = 0;
        }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74515735

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档