1

protobuf 직렬화로 인해 .net 핵심 응용 프로그램의 문제가 발생하는 이유를 찾으려고합니다. 따라서 테스트 응용 프로그램을 작성했으며 일부 이상한 점이 있습니다. Task를 사용하고 Thread를 사용할 경우 메모리 누수가 없다면 메모리 누수가 발생합니다. dotMemory의.net 코어에서 ProtoBuf 직렬화시 메모리 누수

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; } 
} 

및 스크린 :

작업 예는 난 스레드 (주석 코드)

  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(); 
     } 

사용할 경우 memory leak with task

정도로 일절 누설이 없다 : enter image description here

그래서 질문은 :

  1. 내가 뭔가 잘못하고 있니?

  2. 왜 이런 일이 발생합니까?

  3. 어떻게해야할까요?

p.s.

protobuf - 그물은 2.3.2

.NET 코어

UPD1 2.0

: 메인 스레드에서 GC.Collect를 호출 아무것도

+0

열린 스냅 샷 비교, "새"개체 열기,이 개체가 무엇인지, 왜 그 개체가 메모리에 저장되었는지 확인하십시오. 메모리 프로파일 러 전원을 사용하십시오. –

+1

참고 : 어제 새로운 빌드가 추가되어 * 매우 구체적인 * 메모리 시나리오를 처리했습니다. 관련이 있는지는 확실하지 않지만 시도해 볼 수는 있습니다. –

답변

0

그럼 그 재미 (메모리 누수가 여전히 존재)을 변경되지 않습니다 . protobuf-net은 일부 백그라운드 풀을 사용하도록 설정합니다. [ThreadStatic] 인스턴스는 ProtoReader입니다. 예를 들어 그 자체가 가벼운 객체 일 수도 있습니다. [ThreadStatic] 인스턴스에 의해 참조 된 상태로 유지되지 않는 byte[] 풀을 손쉽게 유지합니다 (그 전에 버퍼가 풀에 해제되었습니다). 그래서 아무 것도 없습니다 즉시로 떠나요; 당신이 약간의 GC.Collect을 수행하려고 시도했는데 이 실제로 누설되고이 누출 되었는지를 확인 했습니까? 단순히 아직 수집되지 않았습니까? 당신은 더미 코드 (예를 들어 Thread.Sleep(100);)로 모든 protobuf-net을 대체하려고 시도 했습니까? TPL 기계의 무게를보고 계신지 보시겠습니까? 오버 헤드를 계산하는 오브젝트 유형을 알 수 있습니까?

단순히 GC 여기에 열받은 매우 다른 스레딩 사용의 결과이다 가능성도 다음 Task 코드의 ThreadPool를 사용하는 스레드 때문에 제한된 수의 것입니다. 그것은 좋지도 나쁘지도 않습니다. 단지 다릅니다.