コード例 #1
0
        public bool Trim()
        {
            Debug.Assert(s_trimBuffers);
            Debug.Assert(s_allTlsBuckets != null);

            int            milliseconds = Environment.TickCount;
            MemoryPressure pressure     = GetMemoryPressure();

            PerCoreLockedStacks?[] perCoreBuckets = _buckets;
            for (int i = 0; i < perCoreBuckets.Length; i++)
            {
                perCoreBuckets[i]?.Trim((uint)milliseconds, Id, pressure, _bucketArraySizes[i]);
            }

            if (pressure == MemoryPressure.High)
            {
                foreach (KeyValuePair <T[]?[], object?> tlsBuckets in s_allTlsBuckets)
                {
                    T[]?[] buckets = tlsBuckets.Key;
                    Array.Clear(buckets, 0, buckets.Length);
                }
            }

            return(true);
        }
 public void Trim(uint tickCount, int id, MemoryPressure pressure, int bucketSize)
 {
     LockedStack[] stacks = _perCoreStacks;
     for (int i = 0; i < stacks.Length; i++)
     {
         stacks[i].Trim(tickCount, id, pressure, bucketSize);
     }
 }
 public bool Trim(uint tickCount, int id, MemoryPressure pressure, int[] bucketSizes)
 {
     LockedStack[] stacks = _perCoreStacks;
     for (int i = 0; i < stacks.Length; i++)
     {
         stacks[i].Trim(tickCount, id, pressure, bucketSizes[i]);
     }
     return(true);
 }
コード例 #4
0
        public void Trim(long now, MemoryPressure pressure, int bucketSize)
        {
            if (_count == 0)
            {
                return;
            }

            // 10 seconds under high pressure, otherwise 60 seconds
            var threshold = pressure == MemoryPressure.High ? 10000 : 60000;

            if (_ticks == 0)
            {
                _ticks = now;
                return;
            }

            if (now - _ticks <= threshold)
            {
                return;
            }

            int trimCount = 1;

            switch (pressure)
            {
            case MemoryPressure.Medium:
            {
                trimCount = 2;
                break;
            }

            case MemoryPressure.High:
            {
                if (bucketSize > 16384)
                {
                    trimCount++;
                }

                var size = Unsafe.SizeOf <T>();
                if (size > 32)
                {
                    trimCount += 2;
                }
                else if (size > 16)
                {
                    trimCount++;
                }

                break;
            }
            }

            while (_count > 0 && trimCount-- > 0)
            {
                _arrays[--_count] = null;
            }
        }
        public bool Trim()
        {
            Debug.Assert(s_trimBuffers);
            Debug.Assert(s_allTlsBuckets != null);

            int            milliseconds = Environment.TickCount;
            MemoryPressure pressure     = GetMemoryPressure();

            ArrayPoolEventSource log = ArrayPoolEventSource.Log;

            if (log.IsEnabled())
            {
                log.BufferTrimPoll(milliseconds, (int)pressure);
            }

            PerCoreLockedStacks?[] perCoreBuckets = _buckets;
            for (int i = 0; i < perCoreBuckets.Length; i++)
            {
                perCoreBuckets[i]?.Trim((uint)milliseconds, Id, pressure, _bucketArraySizes[i]);
            }

            if (pressure == MemoryPressure.High)
            {
                // Under high pressure, release all thread locals
                if (log.IsEnabled())
                {
                    foreach (KeyValuePair <T[]?[], object?> tlsBuckets in s_allTlsBuckets)
                    {
                        T[]?[] buckets = tlsBuckets.Key;
                        for (int i = 0; i < buckets.Length; i++)
                        {
                            T[]? buffer = Interlocked.Exchange(ref buckets[i], null);
                            if (buffer != null)
                            {
                                // As we don't want to take a perf hit in the rent path it
                                // is possible that a buffer could be rented as we "free" it.
                                log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id);
                            }
                        }
                    }
                }
                else
                {
                    foreach (KeyValuePair <T[]?[], object?> tlsBuckets in s_allTlsBuckets)
                    {
                        T[]?[] buckets = tlsBuckets.Key;
                        Array.Clear(buckets, 0, buckets.Length);
                    }
                }
            }

            return(true);
        }
コード例 #6
0
ファイル: A.cs プロジェクト: Xamla/graph_system
        public A(params int[] dimension)
        {
            this.Dimension = dimension;
            this.Stride    = A.BuildStride(dimension);

            int length = dimension.Length > 0 ? this.Stride[0] * dimension[0] : 0;

            this.Buffer = new T[length];
            this.count  = length;

            this.memoryPressure = this.SizeInBytes;
            MemoryPressure.Add(this.memoryPressure);
        }
コード例 #7
0
        internal SafeMILHandleMemoryPressure(long gcPressure)
        {
            _gcPressure = gcPressure;
            _refCount   = 0;

            if (_gcPressure > SMALL_BITMAP_MEM)
            {
                MemoryPressure.Add(_gcPressure);
            }
            else
            {
                GC.AddMemoryPressure(_gcPressure);
            }
        }
コード例 #8
0
        internal void Release()
        {
            if (Interlocked.Decrement(ref _refCount) == 0)
            {
                if (_gcPressure > SMALL_BITMAP_MEM)
                {
                    MemoryPressure.Remove(_gcPressure);
                }
                else
                {
                    GC.RemoveMemoryPressure(_gcPressure);
                }

                _gcPressure = 0;
            }
        }
コード例 #9
0
        public bool Trim()
        {
            int            milliseconds = Environment.TickCount;
            MemoryPressure pressure     = GetMemoryPressure();

            ArrayPoolEventSource log = ArrayPoolEventSource.Log;

            if (log.IsEnabled())
            {
                log.BufferTrimPoll(milliseconds, (int)pressure);
            }

            foreach (PerCoreLockedStacks bucket in _buckets)
            {
                bucket?.Trim((uint)milliseconds, Id, pressure, _bucketArraySizes);
            }

            if (pressure == MemoryPressure.High)
            {
                // Under high pressure, release all thread locals
                foreach (KeyValuePair <T[][], object> tlsBuckets in s_AllTlsBuckets)
                {
                    T[][] buckets = tlsBuckets.Key;
                    for (int i = 0; i < NumBuckets; i++)
                    {
                        T[] buffer = buckets[i];
                        buckets[i] = null;

                        if (log.IsEnabled() && buffer != null)
                        {
                            log.BufferTrimmed(buffer.GetHashCode(), buffer.Length, Id);
                        }
                    }
                }
            }

            return(true);
        }
コード例 #10
0
    public static void Main(string[] args)
    {
        if (args.Length != 2)
        {
            Usage();
            return;
        }
        long iterations = 0;

        if (!long.TryParse(args[0], out iterations))
        {
            Usage();
            return;
        }

        if (iterations == 0)
        {
            iterations = 200;
        }

        MemoryPressure mp = new MemoryPressure(iterations);

        switch (args[1].ToLower())
        {
        case "add":
            mp.AddMemoryPressure();
            break;

        case "remove":
            mp.RemoveMemoryPressure();
            break;

        default:
            Usage();
            return;
        }
    }
            public void Trim(uint tickCount, int id, MemoryPressure pressure, int bucketSize)
            {
                const uint StackTrimAfterMS      = 60 * 1000;                     // Trim after 60 seconds for low/moderate pressure
                const uint StackHighTrimAfterMS  = 10 * 1000;                     // Trim after 10 seconds for high pressure
                const uint StackRefreshMS        = StackTrimAfterMS / 4;          // Time bump after trimming (1/4 trim time)
                const int  StackLowTrimCount     = 1;                             // Trim one item when pressure is low
                const int  StackMediumTrimCount  = 2;                             // Trim two items when pressure is moderate
                const int  StackHighTrimCount    = MaxBuffersPerArraySizePerCore; // Trim all items when pressure is high
                const int  StackLargeBucket      = 16384;                         // If the bucket is larger than this we'll trim an extra when under high pressure
                const int  StackModerateTypeSize = 16;                            // If T is larger than this we'll trim an extra when under high pressure
                const int  StackLargeTypeSize    = 32;                            // If T is larger than this we'll trim an extra (additional) when under high pressure

                if (_count == 0)
                {
                    return;
                }
                uint trimTicks = pressure == MemoryPressure.High ? StackHighTrimAfterMS : StackTrimAfterMS;

                lock (this)
                {
                    if (_count > 0 && _firstStackItemMS > tickCount || (tickCount - _firstStackItemMS) > trimTicks)
                    {
                        // We've wrapped the tick count or elapsed enough time since the
                        // first item went into the stack. Drop the top item so it can
                        // be collected and make the stack look a little newer.

                        ArrayPoolEventSource log = ArrayPoolEventSource.Log;
                        int trimCount            = StackLowTrimCount;
                        switch (pressure)
                        {
                        case MemoryPressure.High:
                            trimCount = StackHighTrimCount;

                            // When pressure is high, aggressively trim larger arrays.
                            if (bucketSize > StackLargeBucket)
                            {
                                trimCount++;
                            }
                            if (Unsafe.SizeOf <T>() > StackModerateTypeSize)
                            {
                                trimCount++;
                            }
                            if (Unsafe.SizeOf <T>() > StackLargeTypeSize)
                            {
                                trimCount++;
                            }
                            break;

                        case MemoryPressure.Medium:
                            trimCount = StackMediumTrimCount;
                            break;
                        }

                        while (_count > 0 && trimCount-- > 0)
                        {
                            T[]? array = _arrays[--_count];
                            Debug.Assert(array != null, "No nulls should have been present in slots < _count.");
                            _arrays[_count] = null;

                            if (log.IsEnabled())
                            {
                                log.BufferTrimmed(array.GetHashCode(), array.Length, id);
                            }
                        }

                        if (_count > 0 && _firstStackItemMS < uint.MaxValue - StackRefreshMS)
                        {
                            // Give the remaining items a bit more time
                            _firstStackItemMS += StackRefreshMS;
                        }
                    }
                }
            }