示例#1
0
        private static void OnMemoryCollected(object sender, MemoryCollectedEventArgs args)
        {
            Delegate[] delegates;

            lock (_syncLock)
            {
                if (args.IsLast)
                {
                    _collecting = false;
                }

                if (_memoryCollected != null)
                {
                    delegates = _memoryCollected.GetInvocationList();
                }
                else
                {
                    delegates = new Delegate[0];
                }
            }

            foreach (Delegate @delegate in delegates)
            {
                try
                {
                    @delegate.DynamicInvoke(_strategy, args);
                }
                catch (Exception e)
                {
                    Platform.Log(LogLevel.Warn, e, "Unexpected error encountered during memory collection notification.");
                }
            }
        }
示例#2
0
 /// <summary>
 /// Fires the <see cref="MemoryCollected"/> event.
 /// </summary>
 protected void OnMemoryCollected(MemoryCollectedEventArgs args)
 {
     try
     {
         EventsHelper.Fire(_memoryCollected, this, args);
     }
     catch (Exception e)
     {
         Platform.Log(LogLevel.Warn, e, "Unexpected failure while firing memory collected event.");
     }
 }
示例#3
0
            private void OnMemoryCollected(object sender, MemoryCollectedEventArgs args)
            {
                if (args.IsLast)
                {
                    lock (_waitObject)
                    {
                        Platform.Log(LogLevel.Debug, "'Last' memory collection signal detected; releasing waiting thread.");
                        Monitor.Pulse(_waitObject);
                    }

                    lock (_syncLock)
                    {
                        --_waitingClients;
                    }
                }
            }
示例#4
0
            private void OnMemoryCollected(object sender, MemoryCollectedEventArgs args)
            {
                lock (_waitObject)
                {
                    Platform.Log(LogLevel.Debug, "Received memory collected signal; waiting to see if more memory is required.");
                    Monitor.Pulse(_waitObject);
                    if (_needMoreMemory)
                    {
                        Monitor.Wait(_waitObject);
                        args.NeedMoreMemory = _needMoreMemory;
                    }

                    if (!_needMoreMemory)
                    {
                        lock (_syncLock)
                        {
                            --_waitingClients;
                            MemoryCollected -= OnMemoryCollected;
                        }
                    }
                }
            }
示例#5
0
        public override void Collect(MemoryCollectionArgs collectionArgs)
        {
            _largeObjectEnumerator = collectionArgs.LargeObjectContainers.GetEnumerator();

            _regenerationCost = RegenerationCost.Low;

            //TODO (Time Review): Use Environment.TickCount?
            _collectionStartTime     = DateTime.Now;
            _timeSinceLastCollection = _collectionStartTime - _lastCollectionTime;
            TimeSpan thirtySeconds = TimeSpan.FromSeconds(30);

            if (_timeSinceLastCollection < thirtySeconds)
            {
                Platform.Log(LogLevel.Debug, "Time since last collection is less than 30 seconds; adjusting to 30 seconds.");
                _timeSinceLastCollection = thirtySeconds;
            }

            _maxTimeSinceLastAccess          = _timeSinceLastCollection;
            _maxTimeSinceLastAccessDecrement = TimeSpan.FromSeconds(_timeSinceLastCollection.TotalSeconds / 3);

            _totalNumberOfCollections   = 0;
            _totalBytesCollected        = 0;
            _totalLargeObjectsCollected = 0;
            _totalContainersUnloaded    = 0;

            try
            {
                CodeClock clock = new CodeClock();
                clock.Start();

                Collect();

                clock.Stop();
                PerformanceReportBroker.PublishReport("Memory", "Collect", clock.Seconds);
            }
            catch (Exception e)
            {
                Platform.Log(LogLevel.Warn, e, "Default memory management strategy failed to collect.");
            }
            finally
            {
                DateTime collectionEndTime = DateTime.Now;
                if (_totalContainersUnloaded > 0)
                {
                    _lastCollectionTime = collectionEndTime;
                }

                _largeObjectEnumerator = null;

                TimeSpan totalElapsed = collectionEndTime - _collectionStartTime;

                MemoryCollectedEventArgs finalArgs = new MemoryCollectedEventArgs(
                    _totalContainersUnloaded, _totalLargeObjectsCollected, _totalBytesCollected, totalElapsed, true);

                if (_totalNumberOfCollections != 0 ||
                    _totalBytesCollected != 0 ||
                    _totalLargeObjectsCollected != 0 ||
                    _totalContainersUnloaded != 0)
                {
                    Platform.Log(LogLevel.Info,
                                 "Large object collection summary: freed {0} MB in {1} seconds and {2} iterations, Total Containers: {3}, Total Large Objects: {4}",
                                 _totalBytesCollected / (float)OneMegabyte,
                                 totalElapsed.TotalSeconds,
                                 _totalNumberOfCollections,
                                 _totalContainersUnloaded,
                                 _totalLargeObjectsCollected);
                }

                OnMemoryCollected(finalArgs);
            }
        }
示例#6
0
        private void Collect(long bytesToCollect)
        {
            bool continueCollecting      = false;
            bool needMoreMemorySignalled = false;

            if (bytesToCollect <= 0)
            {
                Platform.Log(LogLevel.Debug,
                             "Memory is not above high watermark; firing collected event to check if more memory is required.");

                MemoryCollectedEventArgs args = new MemoryCollectedEventArgs(0, 0, 0, TimeSpan.Zero, false);
                OnMemoryCollected(args);
                continueCollecting = needMoreMemorySignalled = args.NeedMoreMemory;
            }
            else
            {
                continueCollecting = true;
                Platform.Log(LogLevel.Debug, "Memory *is* above high watermark; collecting ...");
            }

            if (!continueCollecting)
            {
                return;
            }

            int batchSize        = 10;
            int collectionNumber = 0;

            while (continueCollecting)
            {
                CodeClock clock = new CodeClock();
                clock.Start();

                long bytesCollected        = 0;
                int  largeObjectsCollected = 0;
                int  containersUnloaded    = 0;
                int  i = 0;

                foreach (ILargeObjectContainer container in GetNextBatchOfContainersToCollect(batchSize))
                {
                    ++i;

                    try
                    {
                        long bytesHeldBefore        = container.BytesHeldCount;
                        int  largeObjectsHeldBefore = container.LargeObjectCount;

                        container.Unload();

                        long bytesHeldAfter        = container.BytesHeldCount;
                        int  largeObjectsHeldAfter = container.LargeObjectCount;

                        int largeObjectsHeldDifference = largeObjectsHeldBefore - largeObjectsHeldAfter;
                        largeObjectsCollected += largeObjectsHeldDifference;
                        if (largeObjectsHeldDifference > 0)
                        {
                            ++containersUnloaded;
                        }

                        long bytesDifference = (bytesHeldBefore - bytesHeldAfter);
                        bytesCollected       += bytesDifference;
                        _totalBytesCollected += bytesDifference;
                    }
                    catch (Exception e)
                    {
                        Platform.Log(LogLevel.Warn, e, "An unexpected error occurred while attempting to collect large object memory.");
                    }

                    //when needMoreMemorySignalled is true, we need to be more aggressive and keep collecting.
                    if (!needMoreMemorySignalled && _totalBytesCollected >= bytesToCollect)
                    {
                        break;
                    }
                }

                batchSize *= 2;

                _totalContainersUnloaded    += containersUnloaded;
                _totalLargeObjectsCollected += largeObjectsCollected;
                ++_totalNumberOfCollections;

                clock.Stop();

                continueCollecting = i > 0;
                if (!continueCollecting)
                {
                    continue;
                }

                PerformanceReportBroker.PublishReport("Memory", "CollectionIteration", clock.Seconds);

                MemoryCollectedEventArgs args = new MemoryCollectedEventArgs(
                    containersUnloaded, largeObjectsCollected, bytesCollected, TimeSpan.FromSeconds(clock.Seconds), false);

                OnMemoryCollected(args);

                needMoreMemorySignalled = args.NeedMoreMemory;
                continueCollecting      = needMoreMemorySignalled || _totalBytesCollected < bytesToCollect;

                if (Platform.IsLogLevelEnabled(LogLevel.Debug))
                {
                    Platform.Log(LogLevel.Debug,
                                 "Large object collection #{0}: freed {1} MB in {2}, Containers Unloaded: {3}, Large Objects Collected: {4}, Need More Memory: {5}, Last Batch: {6}",
                                 ++collectionNumber, args.BytesCollectedCount / (float)OneMegabyte, clock,
                                 containersUnloaded, largeObjectsCollected, needMoreMemorySignalled, i);
                }
            }

            CollectGarbage();
        }