コード例 #1
0
        private void InitializeScopeList(ManageMemoryMode mode)
        {
            m_manageResourcesScopeList.Clear();
            lock (m_syncLock)
            {
                Func <ResourceScope, bool> isEligible;
                IComparer <ResourceScope>  comparer;
                switch (mode)
                {
                case ManageMemoryMode.CancelSuspended:
                    isEligible = (scope) => scope.IsSuspended;
                    // When cancelling suspended processes, we start from the processes having the largest commit charge.
                    comparer = s_largestCommitSizeFirstComparer;
                    break;

                case ManageMemoryMode.CancellationRam:
                case ManageMemoryMode.CancellationCommit:
                    isEligible = (scope) => scope.CanCancel && scope.MemoryCounters.PeakWorkingSetMb != 0;
                    // When cancelling processes, we start from the processes having the shortest running time.
                    comparer = s_shortestRunningTimeFirstComparer;
                    break;

                case ManageMemoryMode.EmptyWorkingSet:
                    isEligible = (scope) => !scope.IsSuspended && scope.MemoryCounters.LastWorkingSetMb != 0;
                    comparer   = s_largestWorkingSetFirstComparer;
                    break;

                case ManageMemoryMode.Suspend:
                    isEligible = (scope) => !scope.IsSuspended && scope.MemoryCounters.PeakWorkingSetMb != 0;
                    comparer   = s_largestWorkingSetFirstComparer;
                    break;

                case ManageMemoryMode.Resume:
                    isEligible = (scope) => scope.IsSuspended;
                    // When resuming processes, we start from the processes having the longest running time.
                    comparer = s_longestRunningTimeFirstComparer;
                    break;

                default:
                    isEligible = null;
                    comparer   = null;
                    Contract.Assert(false, $"Unknown mode: {mode}");
                    break;
                }

                foreach (var scope in m_pipResourceScopes.Values)
                {
                    if (isEligible(scope))
                    {
                        m_manageResourcesScopeList.Add(scope);
                    }
                }

                m_manageResourcesScopeList.Sort(comparer);
            }
        }
コード例 #2
0
        private void ManageResourcesByPreference(ManageMemoryMode mode, int requiredSize)
        {
            // Resume and EmptyWorkingSet can be called for all items in the list.
            // However, cancellation and suspend should keep one item untouchable to keep the scheduler progressing.
            int allowedCount = (mode == ManageMemoryMode.Resume || mode == ManageMemoryMode.EmptyWorkingSet) ?
                               m_manageResourcesScopeList.Count :
                               m_manageResourcesScopeList.Count - 1;

            for (int i = 0; i < m_manageResourcesScopeList.Count && requiredSize > 0 && allowedCount > 0; i++)
            {
                var scope = m_manageResourcesScopeList[i];

                int sizeMb = 0;

                switch (mode)
                {
                case ManageMemoryMode.CancellationRam:
                case ManageMemoryMode.CancellationCommit:
                case ManageMemoryMode.CancelSuspended:
                {
                    sizeMb = mode == ManageMemoryMode.CancellationRam ? scope.MemoryCounters.LastWorkingSetMb : scope.MemoryCounters.LastCommitSizeMb;

                    scope.CancelAsync(ResourceScopeCancellationReason.ResourceLimits).Forget();
                    break;
                }

                case ManageMemoryMode.EmptyWorkingSet:
                case ManageMemoryMode.Suspend:
                {
                    sizeMb = scope.EmptyWorkingSet(m_loggingContext, mode == ManageMemoryMode.Suspend);
                    break;
                }

                case ManageMemoryMode.Resume:
                {
                    if (scope.RamMbNeededForResume < requiredSize)
                    {
                        sizeMb = scope.ResumeProcess(m_loggingContext);
                    }

                    break;
                }
                }

                requiredSize -= sizeMb;
                allowedCount--;
            }
        }
コード例 #3
0
        private void ManageResourcesByPreference(ManageMemoryMode mode, int requiredSize)
        {
            int allowedCount = GetAllowedManagedResourceScopeCount(mode);

            for (int i = 0; i < m_manageResourcesScopeList.Count && requiredSize > 0 && allowedCount > 0; i++)
            {
                var scope = m_manageResourcesScopeList[i];

                int sizeMb = 0;

                switch (mode)
                {
                case ManageMemoryMode.CancellationRam:
                case ManageMemoryMode.CancellationCommit:
                case ManageMemoryMode.CancelSuspended:
                {
                    sizeMb = mode == ManageMemoryMode.CancellationRam ? scope.MemoryCounters.LastWorkingSetMb : scope.MemoryCounters.LastCommitSizeMb;

                    scope.CancelAsync(ResourceScopeCancellationReason.ResourceLimits).Forget();
                    break;
                }

                case ManageMemoryMode.EmptyWorkingSet:
                case ManageMemoryMode.Suspend:
                {
                    sizeMb = scope.EmptyWorkingSet(m_loggingContext, mode == ManageMemoryMode.Suspend);
                    break;
                }

                case ManageMemoryMode.Resume:
                {
                    if (scope.RamMbNeededForResume < requiredSize)
                    {
                        sizeMb = scope.ResumeProcess(m_loggingContext);
                    }

                    break;
                }
                }

                requiredSize -= sizeMb;
                allowedCount--;
            }
        }
コード例 #4
0
        /// <summary>
        /// Get the number of resource scopes that are allowed to be managed,
        /// according to the ManageMemoryMode requested and the state of the resource list.
        /// </summary>
        private int GetAllowedManagedResourceScopeCount(ManageMemoryMode mode)
        {
            if (mode == ManageMemoryMode.Resume || mode == ManageMemoryMode.EmptyWorkingSet)
            {
                // Resume and EmptyWorkingSet can be called for all resource scopes in the list.
                return(m_manageResourcesScopeList.Count);
            }

            // Other modes are cancellation/suspend
            // Normally, cancellation and suspend should keep one item untouchable to ensure scheduler progress.
            // However, if the remaining resource scope is a single suspended process and the request is for cancellation,
            // then that suspendend process needs to be cancelled in order to ensure scheduler progress.
            // This can happen if after having a single suspended process, the memory usage is still high.
            if (m_manageResourcesScopeList.Count == 1 && m_manageResourcesScopeList[0].IsSuspended)
            {
                return(m_manageResourcesScopeList.Count);
            }

            // In other cases, cancellation and suspend should keep one item untouchable to keep the scheduler progressing.
            return(m_manageResourcesScopeList.Count - 1);
        }
コード例 #5
0
        /// <summary>
        /// Attempt to manage resources by using the mode
        /// </summary>
        public void TryManageResources(int requiredSizeMb, ManageMemoryMode mode)
        {
            if (requiredSizeMb <= 0)
            {
                return;
            }

            if (Interlocked.CompareExchange(ref m_manageResourcesReentrancyCheck, 1, 0) == 0)
            {
                try
                {
                    InitializeScopeList(mode);
                    ManageResourcesByPreference(mode, requiredSizeMb);
                }
                finally
                {
                    m_manageResourcesReentrancyCheck = 0;
                }
            }

            LastRequiredSizeMb   = requiredSizeMb;
            LastManageMemoryMode = mode;
        }
コード例 #6
0
 private void RunResourceManager(ProcessResourceManager resourceManager, int requiredSizeMb, ManageMemoryMode mode)
 {
     resourceManager.RefreshMemoryCounters();
     resourceManager.TryManageResources(requiredSizeMb, mode);
 }