Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading .net内核上ProtoBuf序列化的内存泄漏_Multithreading_Memory Leaks_Asp.net Core_Protocol Buffers_Protobuf Net - Fatal编程技术网

Multithreading .net内核上ProtoBuf序列化的内存泄漏

Multithreading .net内核上ProtoBuf序列化的内存泄漏,multithreading,memory-leaks,asp.net-core,protocol-buffers,protobuf-net,Multithreading,Memory Leaks,Asp.net Core,Protocol Buffers,Protobuf Net,我正试图找出protobuf序列化的.net核心应用程序出现问题的原因,所以我编写了一个测试应用程序并。。。有一些奇怪的问题。如果我使用任务,就会有内存泄漏;如果我使用线程,就不会有内存泄漏 任务示例: internal class Program { private static void Main(string[] args) { var data = new Person { Id = 1, N

我正试图找出protobuf序列化的.net核心应用程序出现问题的原因,所以我编写了一个测试应用程序并。。。有一些奇怪的问题。如果我使用任务,就会有内存泄漏;如果我使用线程,就不会有内存泄漏

任务示例:

internal class Program
{
    private static void Main(string[] args)
    {
        var data = new Person
        {
            Id = 1,
            Name = new string('q', 10000),
            Address = new Address
            {
                Line1 = new string('w', 10000),
                Line2 = new string('e', 10000)
            }
        };



        //for (var i = 0; i < 100; i++)
        //{
        //    var thread = new Thread(() =>
        //    {
        //        while (true)
        //            try
        //            {
        //                var b = ProtoSerialize(data);
        //                Person serializedPerson;
        //                using (Stream stream2 = new MemoryStream(b))
        //                {
        //                    serializedPerson = Serializer.Deserialize<Person>(stream2);
        //                }
        //            }
        //            catch (Exception e)
        //            {
        //                Console.WriteLine(e);
        //            }
        //    });
        //    thread.Start();
        //}

        for (var i = 0; i < 100; i++)
        {
            new Task(() =>
            {
                while (true)
                {
                    var b = ProtoSerialize(data);
                    Person serializedPerson;
                    using (Stream stream2 = new MemoryStream(b))
                    {
                        serializedPerson = Serializer.Deserialize<Person>(stream2);
                    }
                }
            }).Start();
        }

        Console.ReadLine();
    }


    public static byte[] ProtoSerialize<T>(T record) where T : class
    {
        using (var stream = new MemoryStream())
        {
            Serializer.Serialize(stream, record);
            return stream.ToArray();
        }
    }
}


[ProtoContract]
public class Person
{
    [ProtoMember(1)]
    public int Id { get; set; }

    [ProtoMember(2)]
    public string Name { get; set; }

    [ProtoMember(3)]
    public Address Address { get; set; }
}

[ProtoContract]
public class Address
{
    [ProtoMember(1)]
    public string Line1 { get; set; }

    [ProtoMember(2)]
    public string Line2 { get; set; }
}
内部类程序
{
私有静态void Main(字符串[]args)
{
var数据=新人
{
Id=1,
名称=新字符串('q',10000),
地址=新地址
{
第1行=新字符串('w',10000),
第2行=新字符串('e',10000)
}
};
//对于(变量i=0;i<100;i++)
//{
//变量线程=新线程(()=>
//    {
//while(true)
//试一试
//            {
//var b=原型序列化(数据);
//人与人;
//使用(stream2=新内存流(b))
//                {
//serializedPerson=Serializer.Deserialize(stream2);
//                }
//            }
//捕获(例外e)
//            {
//控制台写入线(e);
//            }
//    });
//thread.Start();
//}
对于(变量i=0;i<100;i++)
{
新任务(()=>
{
while(true)
{
var b=原型序列化(数据);
人与人;
使用(stream2=新内存流(b))
{
serializedPerson=Serializer.Deserialize(stream2);
}
}
}).Start();
}
Console.ReadLine();
}
公共静态字节[]原型序列化(T记录),其中T:class
{
使用(var stream=new MemoryStream())
{
序列化器。序列化(流、记录);
返回流ToArray();
}
}
}
[原始合同]
公共阶层人士
{
[原成员(1)]
公共int Id{get;set;}
[原成员(2)]
公共字符串名称{get;set;}
[原成员(3)]
公共广播地址{get;set;}
}
[原始合同]
公共课堂演讲
{
[原成员(1)]
公共字符串Line1{get;set;}
[原成员(2)]
公共字符串第2行{get;set;}
}
以及dotMemory的屏幕截图:

因此,如果我使用线程(注释代码)

for(变量i=0;i<100;i++)
{
变量线程=新线程(()=>
{
while(true)
尝试
{
var b=原型序列化(数据);
人与人;
使用(stream2=新内存流(b))
{
serializedPerson=Serializer.Deserialize(stream2);
}
}
捕获(例外e)
{
控制台写入线(e);
}
});
thread.Start();
}
那么就没有泄漏:

因此,问题是:

  • 我做错什么了吗

  • 为什么会发生这种情况

  • 赖特怎么做

  • p、 美国

    protobuf网络为2.3.2

    .net核心2.0


    UPD1:在主线程中调用GC.Collect不会更改任何内容(仍然存在内存泄漏)

    这很有趣。protobuf net对一些后台池的使用是有限的,例如,
    ProtoReader
    有一个
    [ThreadStatic]
    实例,尽管它本身是一个轻型对象;虽然它确实保留了一个
    byte[]
    池,但是
    [ThreadStatic]
    实例并没有引用该池(在此之前缓冲区被释放到池中)。因此,没有什么东西会立即浮现在脑海中;您是否尝试过执行一些强制的
    GC.Collect
    s以查看是否有任何泄漏,而不是根本没有收集?您是否尝试过用虚拟代码(例如
    Thread.Sleep(100);
    )替换所有protobuf网络,以查看您是否只是看到了TPL机器的重量?您知道(从该工具)哪些对象类型导致了开销吗


    也有可能这仅仅是线程使用非常不同的结果,这会扰乱
    GC
    任务
    代码将使用
    线程池
    ,因此线程数量有限。这既不是好的,也不是坏的,只是:不同。

    打开快照比较,打开“新”对象,看看这些对象是什么以及它们为什么保存在内存中。使用内存探查器电源。注意:昨天出现了一个新的构建,它解决了一个非常特定的内存场景-不确定这是否相关,但您可能想尝试一下itI。我遇到了完全相同的问题,正在处理大对象,并使用dotmemory,这是在Serializer类上发现的
                for (var i = 0; i < 100; i++)
            {
                var thread = new Thread(() =>
                {
                    while (true)
                        try
                        {
                            var b = ProtoSerialize(data);
                            Person serializedPerson;
                            using (Stream stream2 = new MemoryStream(b))
                            {
                                serializedPerson = Serializer.Deserialize<Person>(stream2);
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e);
                        }
                });
                thread.Start();
            }