示例#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.");
                }
            }
        }
 /// <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)
			{
				if (args.IsLast)
				{
					lock (_waitObject)
					{
						Platform.Log(LogLevel.Debug, "'Last' memory collection signal detected; releasing waiting thread.");
						Monitor.Pulse(_waitObject);
					}

					lock (_syncLock)
					{
						--_waitingClients;
					}
				}
			}
示例#5
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;
                        }
                    }
                }
            }
			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;
						}
					}
				}
			}
        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);
            }
        }
        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();
        }
		/// <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.");
			}
		}
		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);
			}
		}
		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();
		}