2013-05-05 2 views
0

Возможно, это не очень хороший вопрос, но я отчаянный. У меня есть небольшая часть кода, и у меня есть утечка памяти, но я не знаю, как ее преодолеть. пожалуйста помоги.Я не могу найти утечку памяти

 var nPiece = stream.Length/BufferLen; 
     var lastPieceLen = stream.Length - (nPiece * BufferLen); 

     for (int i = 0; i < nPiece + 1; i++) 
     { 
      var buffer = new byte[i != nPiece ? BufferLen : lastPieceLen]; 
      stream.Read(buffer, 0, buffer.Length); 
      using (var chunk = new MemoryStream(buffer)) 
       SsClient.SendChunk(i != nPiece ? (i + 1).ToString() : ((i + 1) + "last"), SsSession, chunk); 
      buffer = null; 
      GC.Collect(); 
     } 

я разделить большой поток на более мелкие куски и отправить их на службу WCF по методу SsClient.SendChunk(). Предположим, у меня есть файл размером 700 мб, я разделил его на 7 кусков 100 мб кусков и отправлю их по одному. но после того, как этот метод будет выполнен, в памяти будет около 400 мб, что я вижу как утечку памяти. когда я отлаживаю его, я вижу, что память заполняется куском сразу после метода веб-службы SendChunk. Когда метод закончен здесь, я остался с утечкой памяти. GC.collect() тоже не работает. Я даже не понял, почему осталось 400 МБ файла 700 МБ? возможно, это может дать некоторые подсказки, которые я не знаю.

любые идеи?

+0

Возможно, клиент WCF держится за него. Каково поведение, если вы создаете нового клиента на каждой итерации? – leppie

+0

Вы говорите, что я должен создать нового клиента на каждой итерации? Это звучит неплохо. Нет никаких проблем при этом, я просто сделал это так, потому что он выглядел более аккуратным для меня. –

+2

Что значит «видеть это как утечку памяти»? (И почему вы не ждете ожидающих финализаторов?) И вы закрываете поток? –

ответ

3
for (int i = 0; i < nPiece + 1; i++) 
    { 
     var buffer = new byte[i != nPiece ? BufferLen : lastPieceLen]; 

У вас нет утечки памяти. У вас просто плохой случай с munchies. Вы торопите память в спешке, выделяя буфер внутри цикла for(). Это тоже не тонко, буферы 100 мегабайт не падают с неба. Любой объект размером более 85 000 байт выделяется из кучи большого объекта, а не для обычной генерации GC-кучи. Распределение LOH не уплотняется, они слишком велики и часто не собираются. Для этого требуется коллекция # 2, они не происходят очень часто.

И выделение как это имеет задержанные эффекты, причина, по которой вы не видите GC.Collect(), делают многое, чтобы уменьшить число. Вы также используете много оперативной памяти. Windows не распаковывает страницы памяти, пока это не произойдет. Обычно, потому что другому процессу требуется оперативная память. И вы поглощаете большое количество адресных пространств виртуальной памяти. Опять диспетчер памяти Windows не торопится де-выделить это пространство. Это нормально, это виртуально. Это ничего не стоит. В противном случае неясно, на каком количестве вы смотрите. Самая большая причина, по которой GC.Collect() имеет мало эффекта, заключается в том, что MemoryStream все еще имеет ссылку на массив. Вызов метода Dispose() не меняет этого. И последнее, но не менее важное: дрожание удаляет нулевые присвоения локальным переменным при создании и запуске версии Release.

Простым решением является Повторное использование Буфер. Выделите его вне цикла for(). Это поможет много, если вы также настроите SendChunk(), чтобы принять аргумент длиной. И просто уменьшите размер куска, 100 мегабайт слишком много. Это происходит по сети в большинстве сценариев WCF, размер сетевых блоков обычно составляет всего 1500 байтов. Размер буфера 4096 байт для ввода-вывода в большинстве случаев примерно прав.

+0

Благодарим вас за исчерпывающий ответ. Я буду повторно использовать буфер, как вы предложили. Но то, что я не совсем понимаю, заключается в том, какой недостаток он заставит меня использовать 100 мб кусков с точки зрения WCF или сети. И аргумент lenght не так полезен в моем случае здесь, я думаю, потому что я использую этот подход только тогда, когда я получил файлы более 100 мб. –

+0

Недостатком является то, что нет никакого преимущества в использовании большого количества памяти. –

+0

Я думал, может быть, это исчерпало бы службу WCF, так как будет меньше звонков при отправке, например, 4 ГБ файлов. Неужели я ошибаюсь? –

Смежные вопросы