示例#1
0
        /// <summary>
        /// Get textual statistics about the buffer pool.
        /// </summary>
        public static string GetStatistics(bool showEmptyBuffers = true)
        {
            rwLock.EnterReadLock();
            try
            {
                statiscticsBuilder.Length = 0;
                statiscticsBuilder.AppendFormat("Pooled array reused count: {0:N0}\n", GetBuffers);
                statiscticsBuilder.AppendFormat("Release call count: {0:N0}\n", ReleaseBuffers);
                statiscticsBuilder.AppendFormat("PoolSize: {0:N0}\n", PoolSize);
                statiscticsBuilder.AppendFormat("Buffers: {0}\n", FreeBuffers.Count);

                for (int i = 0; i < FreeBuffers.Count; ++i)
                {
                    BufferStore       store   = FreeBuffers[i];
                    List <BufferDesc> buffers = store.buffers;

                    if (showEmptyBuffers || buffers.Count > 0)
                    {
                        statiscticsBuilder.AppendFormat("- Size: {0:N0} Count: {1:N0}\n", store.Size, buffers.Count);
                    }
                }

                return(statiscticsBuilder.ToString());
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }
示例#2
0
        /// <summary>
        /// Internal function called by the plugin to remove old, non-used buffers.
        /// </summary>
        internal static void Maintain()
        {
            DateTime now = DateTime.UtcNow;

            if (!_isEnabled || lastMaintenance + RunMaintenanceEvery > now)
            {
                return;
            }
            lastMaintenance = now;

            //if (HTTPManager.Logger.Level == Logger.Loglevels.All)
            //    HTTPManager.Logger.Information("VariableSizedBufferPool", "Before Maintain: " + GetStatistics());

            DateTime olderThan = now - RemoveOlderThan;

            rwLock.EnterWriteLock();
            try
            {
                for (int i = 0; i < FreeBuffers.Count; ++i)
                {
                    BufferStore       store   = FreeBuffers[i];
                    List <BufferDesc> buffers = store.buffers;

                    for (int cv = buffers.Count - 1; cv >= 0; cv--)
                    {
                        BufferDesc desc = buffers[cv];

                        if (desc.released < olderThan)
                        {
                            // buffers stores available buffers ascending by age. So, when we find an old enough, we can
                            //  delete all entries in the [0..cv] range.

                            int removeCount = cv + 1;
                            buffers.RemoveRange(0, removeCount);
                            PoolSize -= (int)(removeCount * store.Size);
                            break;
                        }
                    }

                    if (RemoveEmptyLists && buffers.Count == 0)
                    {
                        FreeBuffers.RemoveAt(i--);
                    }
                }
            }
            finally
            {
                rwLock.ExitWriteLock();
            }

            //if (HTTPManager.Logger.Level == Logger.Loglevels.All)
            //    HTTPManager.Logger.Information("VariableSizedBufferPool", "After Maintain: " + GetStatistics());
        }
示例#3
0
        private static void AddFreeBuffer(byte[] buffer)
        {
            int bufferLength = buffer.Length;

            for (int i = 0; i < FreeBuffers.Count; ++i)
            {
                BufferStore store = FreeBuffers[i];

                if (store.Size == bufferLength)
                {
                    // We highly assume here that every buffer will be released only once.
                    //  Checking for double-release would mean that we have to do another O(n) operation, where n is the
                    //  count of the store's elements.

                    if (IsDoubleReleaseCheckEnabled)
                    {
                        for (int cv = 0; cv < store.buffers.Count; ++cv)
                        {
                            var entry = store.buffers[cv];
                            if (ReferenceEquals(entry.buffer, buffer))
                            {
                                HTTPManager.Logger.Error("VariableSizedBufferPool", "Buffer already added to the pool!");
                                return;
                            }
                        }
                    }

                    store.buffers.Add(new BufferDesc(buffer));
                    return;
                }

                if (store.Size > bufferLength)
                {
                    FreeBuffers.Insert(i, new BufferStore(bufferLength, buffer));
                    return;
                }
            }

            // When we reach this point, there's no same sized or larger BufferStore present, so we have to add a new one
            //  to the end of our list.
            FreeBuffers.Add(new BufferStore(bufferLength, buffer));
        }
示例#4
0
        private static BufferDesc FindFreeBuffer(long size, bool canBeLarger)
        {
            rwLock.EnterUpgradeableReadLock();
            try
            {
                for (int i = 0; i < FreeBuffers.Count; ++i)
                {
                    BufferStore store = FreeBuffers[i];

                    if (store.buffers.Count > 0 && (store.Size == size || (canBeLarger && store.Size > size)))
                    {
                        // Getting the last one has two desired effect:
                        //  1.) RemoveAt should be quicker as it don't have to move all the remaining entries
                        //  2.) Old, non-used buffers will age. Getting a buffer and putting it back will not keep buffers fresh.

                        BufferDesc lastFree = store.buffers[store.buffers.Count - 1];

                        rwLock.EnterWriteLock();
                        try
                        {
                            store.buffers.RemoveAt(store.buffers.Count - 1);
                        }
                        finally
                        {
                            rwLock.ExitWriteLock();
                        }

                        return(lastFree);
                    }
                }
            }
            finally
            {
                rwLock.ExitUpgradeableReadLock();
            }

            return(BufferDesc.Empty);
        }
示例#5
0
        /// <summary>
        /// Get textual statistics about the buffer pool.
        /// </summary>
        public static string GetStatistics(bool showEmptyBuffers = true)
        {
            rwLock.EnterReadLock();
            try
            {
                statiscticsBuilder.Length = 0;
                statiscticsBuilder.AppendFormat("Pooled array reused count: {0:N0}\n", GetBuffers);
                statiscticsBuilder.AppendFormat("Release call count: {0:N0}\n", ReleaseBuffers);
                statiscticsBuilder.AppendFormat("PoolSize: {0:N0}\n", PoolSize);
                statiscticsBuilder.AppendFormat("Buffers: {0}\n", FreeBuffers.Count);

                for (int i = 0; i < FreeBuffers.Count; ++i)
                {
                    BufferStore       store   = FreeBuffers[i];
                    List <BufferDesc> buffers = store.buffers;

                    if (showEmptyBuffers || buffers.Count > 0)
                    {
                        statiscticsBuilder.AppendFormat("- Size: {0:N0} Count: {1:N0}\n", store.Size, buffers.Count);
                    }
                }

#if UNITY_EDITOR
                if (EnableDebugStackTraceCollection)
                {
                    lock (getStackStats)
                    {
                        int sum = 0;
                        foreach (var kvp in getStackStats)
                        {
                            sum += kvp.Value;
                        }

                        statiscticsBuilder.AppendFormat("Get stacks: {0:N0}\n", sum);

                        foreach (var kvp in getStackStats)
                        {
                            statiscticsBuilder.AppendFormat("- {0:N0}: {1}\n", kvp.Value, kvp.Key);
                        }
                    }

                    lock (releaseStackStats)
                    {
                        int sum = 0;
                        foreach (var kvp in releaseStackStats)
                        {
                            sum += kvp.Value;
                        }

                        statiscticsBuilder.AppendFormat("Release stacks: {0:N0}\n", sum);

                        foreach (var kvp in releaseStackStats)
                        {
                            statiscticsBuilder.AppendFormat("- {0:N0}: {1}\n", kvp.Value, kvp.Key);
                        }
                    }
                }
#endif

                return(statiscticsBuilder.ToString());
            }
            finally
            {
                rwLock.ExitReadLock();
            }
        }