private static ConsoleLogMuxer CreateMuxer(ConsoleLogGlobalSettings settings)
        {
            var consoleFeaturesDetector = new ConsoleFeaturesDetector();
            var consoleWriterFactory    = new ConsoleWriterFactory(consoleFeaturesDetector, settings.OutputBufferSize);
            var consoleWriter           = consoleWriterFactory.CreateWriter();
            var eventsBatcher           = new EventsBatcher(consoleFeaturesDetector);
            var eventsWriter            = new EventsWriter(eventsBatcher, consoleWriter, consoleFeaturesDetector);

            return(new ConsoleLogMuxer(eventsWriter, settings.EventsQueueCapacity, settings.EventsTemporaryBufferCapacity));
        }
        /// <summary>
        /// Initializes the memory manager with the given block requiredSize.
        /// </summary>
        /// <param name="blockSize">Size of each block that is pooled. Must be > 0.</param>
        /// <param name="largeBufferMultiple">Each large buffer will be a multiple/exponential of this value.</param>
        /// <param name="maximumBufferSize">Buffers larger than this are not pooled</param>
        /// <param name="useExponentialLargeBuffer">Switch to exponential large buffer allocation strategy</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// blockSize is not a positive number, or largeBufferMultiple is not a
        /// positive number, or maximumBufferSize is less than blockSize.
        /// </exception>
        /// <exception cref="ArgumentException">maximumBufferSize is not a multiple/exponential of largeBufferMultiple</exception>
        public RecyclableMemoryStreamManager(int blockSize, int largeBufferMultiple, int maximumBufferSize, bool useExponentialLargeBuffer)
        {
            if (blockSize <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(blockSize), blockSize, "blockSize must be a positive number");
            }

            if (largeBufferMultiple <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(largeBufferMultiple),
                                                      "largeBufferMultiple must be a positive number");
            }

            if (maximumBufferSize < blockSize)
            {
                throw new ArgumentOutOfRangeException(nameof(maximumBufferSize),
                                                      "maximumBufferSize must be at least blockSize");
            }

            BlockSize                 = blockSize;
            LargeBufferMultiple       = largeBufferMultiple;
            MaximumBufferSize         = maximumBufferSize;
            UseExponentialLargeBuffer = useExponentialLargeBuffer;

            if (!IsLargeBufferSize(maximumBufferSize))
            {
                throw new ArgumentException(string.Format("maximumBufferSize is not {0} of largeBufferMultiple",
                                                          UseExponentialLargeBuffer ? "an exponential" : "a multiple"),
                                            nameof(maximumBufferSize));
            }

            _smallPool = new ConcurrentStack <byte[]>();
            var numLargePools = useExponentialLargeBuffer
                                // ReSharper disable once PossibleLossOfFraction
                                // Not our code assume loss is intentional
                                ? (int)Math.Log(maximumBufferSize / largeBufferMultiple, 2) + 1
                                : maximumBufferSize / largeBufferMultiple;

            // +1 to store size of bytes in use that are too large to be pooled
            _largeBufferInUseSize = new long[numLargePools + 1];
            _largeBufferFreeSize  = new long[numLargePools];

            _largePools = new ConcurrentStack <byte[]> [numLargePools];

            for (var i = 0; i < _largePools.Length; ++i)
            {
                _largePools[i] = new ConcurrentStack <byte[]>();
            }

            Counter = new Counters(this);
            EventsWriter.MemoryStreamManagerInitialized(blockSize, largeBufferMultiple, maximumBufferSize);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Returns the buffer to the large pool
        /// </summary>
        /// <param name="buffer">The buffer to return.</param>
        /// <param name="tag">The tag of the stream returning this buffer, for logging if necessary.</param>
        /// <exception cref="ArgumentNullException">buffer is null</exception>
        /// <exception cref="ArgumentException">
        /// buffer.Length is not a multiple/exponential of LargeBufferMultiple (it did not
        /// originate from this pool)
        /// </exception>
        internal void ReturnLargeBuffer(byte[] buffer, string tag)
        {
            if (buffer == null)
            {
                throw new ArgumentNullException(nameof(buffer));
            }

            if (!IsLargeBufferSize(buffer.Length))
            {
                throw new ArgumentException(
                          string.Format("buffer did not originate from this memory manager. The size is not {0} of ",
                                        UseExponentialLargeBuffer ? "an exponential" : "a multiple") +
                          LargeBufferMultiple);
            }

            var poolIndex = GetPoolIndex(buffer.Length);

            if (poolIndex < _largePools.Length)
            {
                if ((_largePools[poolIndex].Count + 1) * buffer.Length <= MaximumFreeLargePoolBytes ||
                    MaximumFreeLargePoolBytes == 0)
                {
                    _largePools[poolIndex].Push(buffer);
                    Interlocked.Add(ref _largeBufferFreeSize[poolIndex], buffer.Length);
                }
                else
                {
                    EventsWriter.MemoryStreamDiscardBuffer(Events.MemoryStreamBufferType.Large, tag,
                                                           Events.MemoryStreamDiscardReason.EnoughFree);
                    ReportLargeBufferDiscarded(Events.MemoryStreamDiscardReason.EnoughFree);
                }
            }
            else
            {
                // This is a non-poolable buffer, but we still want to track its size for inuse
                // analysis. We have space in the inuse array for this.
                poolIndex = _largeBufferInUseSize.Length - 1;

                EventsWriter.MemoryStreamDiscardBuffer(Events.MemoryStreamBufferType.Large, tag,
                                                       Events.MemoryStreamDiscardReason.TooLarge);
                ReportLargeBufferDiscarded(Events.MemoryStreamDiscardReason.TooLarge);
            }

            Interlocked.Add(ref _largeBufferInUseSize[poolIndex], -buffer.Length);

            ReportUsageReport(_smallPoolInUseSize, _smallPoolFreeSize, LargePoolInUseSize,
                              LargePoolFreeSize);
        }
Ejemplo n.º 4
0
        public void TestSetup()
        {
            batcher = Substitute.For <IEventsBatcher>();
            batcher.BatchEvents(Arg.Any <LogEventInfo[]>(), Arg.Any <int>()).Returns(MakeBatch);

            consoleWriter = Substitute.For <IConsoleWriter>();

            colorReleaser = Substitute.For <IDisposable>();
            consoleWriter.ChangeColor(Arg.Any <ConsoleColor>()).Returns(_ => colorReleaser);

            var featuresDetector = Substitute.For <IConsoleFeaturesDetector>();

            featuresDetector.AreColorsSupported.Returns(true);

            writer = new EventsWriter(batcher, consoleWriter, featuresDetector);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Returns a buffer of arbitrary size from the large buffer pool. This buffer
        /// will be at least the requiredSize and always be a multiple/exponential of largeBufferMultiple.
        /// </summary>
        /// <param name="requiredSize">The minimum length of the buffer</param>
        /// <param name="tag">The tag of the stream returning this buffer, for logging if necessary.</param>
        /// <returns>A buffer of at least the required size.</returns>
        internal byte[] GetLargeBuffer(int requiredSize, string tag)
        {
            requiredSize = RoundToLargeBufferSize(requiredSize);

            var poolIndex = GetPoolIndex(requiredSize);

            byte[] buffer;
            if (poolIndex < _largePools.Length)
            {
                if (!_largePools[poolIndex].TryPop(out buffer))
                {
                    buffer = new byte[requiredSize];

                    EventsWriter.MemoryStreamNewLargeBufferCreated(requiredSize, LargePoolInUseSize);
                    ReportLargeBufferCreated();
                }
                else
                {
                    Interlocked.Add(ref _largeBufferFreeSize[poolIndex], -buffer.Length);
                }
            }
            else
            {
                // Buffer is too large to pool. They get a new buffer.

                // We still want to track the size, though, and we've reserved a slot
                // in the end of the inuse array for nonpooled bytes in use.
                poolIndex = _largeBufferInUseSize.Length - 1;

                // We still want to round up to reduce heap fragmentation.
                buffer = new byte[requiredSize];
                string callStack = null;
                if (GenerateCallStacks)
                {
                    // Grab the stack -- we want to know who requires such large buffers
                    callStack = Environment.StackTrace;
                }
                EventsWriter.MemoryStreamNonPooledLargeBufferCreated(requiredSize, tag, callStack);
                ReportLargeBufferCreated();
            }

            Interlocked.Add(ref _largeBufferInUseSize[poolIndex], buffer.Length);

            return(buffer);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Removes and returns a single block from the pool.
        /// </summary>
        /// <returns>A byte[] array</returns>
        internal byte[] GetBlock()
        {
            byte[] block;
            if (!_smallPool.TryPop(out block))
            {
                // We'll add this back to the pool when the stream is disposed
                // (unless our free pool is too large)
                block = new byte[BlockSize];
                EventsWriter.MemoryStreamNewBlockCreated(_smallPoolInUseSize);
                ReportBlockCreated();
            }
            else
            {
                Interlocked.Add(ref _smallPoolFreeSize, -BlockSize);
            }

            Interlocked.Add(ref _smallPoolInUseSize, BlockSize);
            return(block);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Returns the blocks to the pool
        /// </summary>
        /// <param name="blocks">Collection of blocks to return to the pool</param>
        /// <param name="tag">The tag of the stream returning these blocks, for logging if necessary.</param>
        /// <exception cref="ArgumentNullException">blocks is null</exception>
        /// <exception cref="ArgumentException">blocks contains buffers that are the wrong size (or null) for this memory manager</exception>
        internal void ReturnBlocks(ICollection <byte[]> blocks, string tag)
        {
            if (blocks == null)
            {
                throw new ArgumentNullException(nameof(blocks));
            }

            var bytesToReturn = blocks.Count * BlockSize;

            Interlocked.Add(ref _smallPoolInUseSize, -bytesToReturn);

            foreach (var block in blocks)
            {
                if (block == null || block.Length != BlockSize)
                {
                    throw new ArgumentException("blocks contains buffers that are not BlockSize in length");
                }
            }

            foreach (var block in blocks)
            {
                if (MaximumFreeSmallPoolBytes == 0 || SmallPoolFreeSize < MaximumFreeSmallPoolBytes)
                {
                    Interlocked.Add(ref _smallPoolFreeSize, BlockSize);
                    _smallPool.Push(block);
                }
                else
                {
                    EventsWriter.MemoryStreamDiscardBuffer(Events.MemoryStreamBufferType.Small, tag,
                                                           Events.MemoryStreamDiscardReason.EnoughFree);
                    ReportBlockDiscarded();
                    break;
                }
            }

            ReportUsageReport(_smallPoolInUseSize, _smallPoolFreeSize, LargePoolInUseSize,
                              LargePoolFreeSize);
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EventManager"/> class.
 /// </summary>
 /// <param name="logWriter">Used to receive loggings.</param>
 /// <param name="writer">Used to receive unparsed event messages.</param>
 public EventManager(LogWriterHandler logWriter, EventsWriter writer)
 {
     _logWriter = logWriter ?? NullWriter.Write;
     _socket    = new EventSocket(_logWriter);
     _writer    = writer;
 }