Информация об изменениях

Сообщение WebApi и GC от 14.12.2016 14:48

Изменено 14.12.2016 14:49 Jack128

Мдя. В общем такой вот наследник HttpContent нашкрябал:

  Код
        public class BufferedHttpContent: HttpContent
        {
            static readonly RecyclableMemoryStreamManager _memoryManager = new RecyclableMemoryStreamManager();
            private readonly HttpContent _content;
            private Stream _bufferedStream;

            public BufferedHttpContent(HttpContent content)
            {
                _content = content;
                _content.Headers.CopyTo(Headers, true, true);
            }

            private async Task BufferedStreamNeeded()
            {
                if (_bufferedStream == null)
                {
                    _bufferedStream = _memoryManager.GetStream();
                    await _content.CopyToAsync(_bufferedStream).ConfigureAwait(continueOnCapturedContext: false);
                    _bufferedStream.Position = 0;
                }
            }

            
            protected override async Task<Stream> CreateContentReadStreamAsync()
            {
                if (_content is StringContent || _content is StreamContent)
                    return await _content.ReadAsStreamAsync();
                await BufferedStreamNeeded();
                return _bufferedStream;
            }

            protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
            {
                if (_bufferedStream != null)
                    return _bufferedStream.CopyToAsync(stream);
                return _content.CopyToAsync(stream, context);
            }

            protected override bool TryComputeLength(out long length)
            {
                var l = _content.Headers.ContentLength;
                if (l != null)
                {
                    length = l.Value;
                    return true;
                }
                if (_bufferedStream != null)
                {
                    length = _bufferedStream.Length;
                    return true;
                }

                BufferedStreamNeeded().Wait();
                length = _bufferedStream.Length;
                return true;
            }

            protected override void Dispose(bool disposing)
            {
                base.Dispose(disposing);
                if (disposing)
                {
                    _bufferedStream?.Dispose();
                }
            }
        }


По сути это обертка над переданным HttpContent _content, которая, если сам _content не способен вычислить свою длину — стримит его синхронно в мелкософтовский RecyclableMemoryStream и отдает длину буфера.
вот подменил я стандартные контенты этим самопалом — и о чудо. Там где у меня раньше 10 сборок мусора 2ого поколения было — сейчас не одного. Это что ж такое, народ, в веб апи так всё плохо с памятью — или я где то в измерениях накосячил ???
WebApi и GC
Мдя. В общем такой вот наследник HttpContent нашкрябал:

  Код
        public class BufferedHttpContent: HttpContent
        {
            static readonly RecyclableMemoryStreamManager _memoryManager = new RecyclableMemoryStreamManager();
            private readonly HttpContent _content;
            private Stream _bufferedStream;

            public BufferedHttpContent(HttpContent content)
            {
                _content = content;
                _content.Headers.CopyTo(Headers, true, true);
            }

            private async Task BufferedStreamNeeded()
            {
                if (_bufferedStream == null)
                {
                    _bufferedStream = _memoryManager.GetStream();
                    await _content.CopyToAsync(_bufferedStream).ConfigureAwait(continueOnCapturedContext: false);
                    _bufferedStream.Position = 0;
                }
            }

            
            protected override async Task<Stream> CreateContentReadStreamAsync()
            {
                if (_content is StringContent || _content is StreamContent)
                    return await _content.ReadAsStreamAsync();
                await BufferedStreamNeeded();
                return _bufferedStream;
            }

            protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
            {
                if (_bufferedStream != null)
                    return _bufferedStream.CopyToAsync(stream);
                return _content.CopyToAsync(stream, context);
            }

            protected override bool TryComputeLength(out long length)
            {
                var l = _content.Headers.ContentLength;
                if (l != null)
                {
                    length = l.Value;
                    return true;
                }
                if (_bufferedStream != null)
                {
                    length = _bufferedStream.Length;
                    return true;
                }

                BufferedStreamNeeded().Wait();
                length = _bufferedStream.Length;
                return true;
            }

            protected override void Dispose(bool disposing)
            {
                base.Dispose(disposing);
                if (disposing)
                {
                    _bufferedStream?.Dispose();
                }
            }
        }


По сути это обертка над переданным HttpContent _content, которая, если сам _content не способен вычислить свою длину — стримит его синхронно в мелкософтовский RecyclableMemoryStream и отдает длину буфера.
вот подменил я стандартные контенты этим самопалом — и о чудо. Там где у меня раньше 10 сборок мусора 2ого поколения было — сейчас не одного. Это что ж такое, народ, в веб апи так всё плохо с памятью — или я где то в измерениях накосячил ???

UPDATE:
Да, webapi обычный id="Microsoft.AspNet.WebApi" version="5.2.2", никаких Core