예제 #1
0
        private static MemoryInfoResult GetMemoryInfoLinux(SmapsReader smapsReader, bool extended)
        {
            var fromProcMemInfo = new ProcMemInfoResults();

            GetFromProcMemInfo(smapsReader, ref fromProcMemInfo);

            var totalPhysicalMemoryInBytes = fromProcMemInfo.TotalMemory.GetValue(SizeUnit.Bytes);

            var cgroupMemoryLimit    = KernelVirtualFileSystemUtils.ReadNumberFromCgroupFile(CgroupMemoryLimit);
            var cgroupMaxMemoryUsage = KernelVirtualFileSystemUtils.ReadNumberFromCgroupFile(CgroupMaxMemoryUsage);
            // here we need to deal with _soft_ limit, so we'll take the largest of these values
            var maxMemoryUsage = Math.Max(cgroupMemoryLimit ?? 0, cgroupMaxMemoryUsage ?? 0);

            if (maxMemoryUsage != 0 && maxMemoryUsage <= totalPhysicalMemoryInBytes)
            {
                // running in a limited cgroup
                var commitedMemoryInBytes = 0L;
                var cgroupMemoryUsage     = LowMemoryNotification.Instance.UseTotalDirtyMemInsteadOfMemUsage // RDBS-45
                    ? fromProcMemInfo.TotalDirty.GetValue(SizeUnit.Bytes)
                    : KernelVirtualFileSystemUtils.ReadNumberFromCgroupFile(CgroupMemoryUsage);

                if (cgroupMemoryUsage != null)
                {
                    commitedMemoryInBytes = cgroupMemoryUsage.Value;
                    fromProcMemInfo.Commited.Set(commitedMemoryInBytes, SizeUnit.Bytes);
                    fromProcMemInfo.MemAvailable.Set(maxMemoryUsage - cgroupMemoryUsage.Value, SizeUnit.Bytes);
                    var realAvailable = maxMemoryUsage - cgroupMemoryUsage.Value + fromProcMemInfo.SharedCleanMemory.GetValue(SizeUnit.Bytes);
                    if (realAvailable < 0)
                    {
                        realAvailable = 0;
                    }
                    fromProcMemInfo.AvailableWithoutTotalCleanMemory.Set(realAvailable, SizeUnit.Bytes);
                }

                fromProcMemInfo.TotalMemory.Set(maxMemoryUsage, SizeUnit.Bytes);
                fromProcMemInfo.CommitLimit.Set(Math.Max(maxMemoryUsage, commitedMemoryInBytes), SizeUnit.Bytes);
            }

            var workingSet = new Size(0, SizeUnit.Bytes);

            if (smapsReader != null)
            {
                // extended info is needed
                workingSet.Set(GetRssMemoryUsage(), SizeUnit.Bytes);
            }

            return(BuildPosixMemoryInfoResult(
                       fromProcMemInfo.MemAvailable,
                       fromProcMemInfo.TotalMemory,
                       fromProcMemInfo.Commited,
                       fromProcMemInfo.CommitLimit,
                       fromProcMemInfo.AvailableWithoutTotalCleanMemory,
                       fromProcMemInfo.SharedCleanMemory,
                       workingSet,
                       extended));
        }
예제 #2
0
        internal static bool GetFromProcMemInfo(SmapsReader smapsReader, ref ProcMemInfoResults procMemInfoResults)
        {
            const string path = "/proc/meminfo";

            // this is different then sysinfo freeram+buffered (and the closest to the real free memory)
            // MemFree is really different then MemAvailable (while free is usually lower then the real free,
            // and available is only estimated free which sometimes higher then the real free memory)
            // for some distros we have only MemFree
            try
            {
                using (var bufferedReader = new KernelVirtualFileSystemUtils.BufferedPosixKeyValueOutputValueReader(path))
                {
                    bufferedReader.ReadFileIntoBuffer();
                    var memAvailableInKb = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(MemAvailable);
                    var memFreeInKb      = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(MemFree);
                    var totalMemInKb     = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(MemTotal);
                    var swapTotalInKb    = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(SwapTotal);
                    var commitedInKb     = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(Committed_AS);

                    var totalClean        = new Size(memAvailableInKb, SizeUnit.Kilobytes);
                    var totalDirty        = new Size(0, SizeUnit.Bytes);
                    var sharedCleanMemory = new Size(0, SizeUnit.Bytes);
                    if (smapsReader != null)
                    {
                        var result = smapsReader.CalculateMemUsageFromSmaps <SmapsReaderNoAllocResults>();
                        totalClean.Add(result.SharedClean, SizeUnit.Bytes);
                        totalClean.Add(result.PrivateClean, SizeUnit.Bytes);
                        sharedCleanMemory.Set(result.SharedClean, SizeUnit.Bytes);
                        totalDirty.Add(result.TotalDirty, SizeUnit.Bytes);
                    }

                    procMemInfoResults.MemAvailable = new Size(Math.Max(memAvailableInKb, memFreeInKb), SizeUnit.Kilobytes);
                    procMemInfoResults.TotalMemory  = new Size(totalMemInKb, SizeUnit.Kilobytes);
                    procMemInfoResults.Commited     = new Size(commitedInKb, SizeUnit.Kilobytes);

                    // on Linux, we use the swap + ram as the commit limit, because the actual limit
                    // is dependent on many different factors
                    procMemInfoResults.CommitLimit = new Size(totalMemInKb + swapTotalInKb, SizeUnit.Kilobytes);
                    procMemInfoResults.AvailableWithoutTotalCleanMemory = totalClean;
                    procMemInfoResults.SharedCleanMemory = sharedCleanMemory;
                    procMemInfoResults.TotalDirty        = totalDirty;
                }
            }
            catch (Exception ex)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Failed to read value from {path}", ex);
                }

                return(false);
            }

            return(true);
        }
예제 #3
0
        private static MemoryInfoResult GetMemoryInfoLinux(SmapsReader smapsReader, bool extended)
        {
            var fromProcMemInfo = new ProcMemInfoResults();

            GetFromProcMemInfo(smapsReader, ref fromProcMemInfo);

            var totalPhysicalMemoryInBytes = fromProcMemInfo.TotalMemory.GetValue(SizeUnit.Bytes);

            var cgroupMemoryLimit    = KernelVirtualFileSystemUtils.ReadNumberFromCgroupFile(CgroupMemoryLimit);
            var cgroupMaxMemoryUsage = KernelVirtualFileSystemUtils.ReadNumberFromCgroupFile(CgroupMaxMemoryUsage);
            // here we need to deal with _soft_ limit, so we'll take the largest of these values
            var maxMemoryUsage = Math.Max(cgroupMemoryLimit ?? 0, cgroupMaxMemoryUsage ?? 0);

            if (maxMemoryUsage != 0 && maxMemoryUsage <= totalPhysicalMemoryInBytes)
            {
                // running in a limited cgroup
                var commitedMemoryInBytes = 0L;
                var cgroupMemoryUsage     = LowMemoryNotification.Instance.UseTotalDirtyMemInsteadOfMemUsage // RDBS-45
                    ? fromProcMemInfo.TotalDirty.GetValue(SizeUnit.Bytes)
                    : KernelVirtualFileSystemUtils.ReadNumberFromCgroupFile(CgroupMemoryUsage);

                if (cgroupMemoryUsage != null)
                {
                    commitedMemoryInBytes = cgroupMemoryUsage.Value;
                    fromProcMemInfo.Commited.Set(commitedMemoryInBytes, SizeUnit.Bytes);
                    fromProcMemInfo.AvailableMemory.Set(maxMemoryUsage - cgroupMemoryUsage.Value, SizeUnit.Bytes);
                    var realAvailable = maxMemoryUsage - cgroupMemoryUsage.Value + fromProcMemInfo.SharedCleanMemory.GetValue(SizeUnit.Bytes);
                    if (realAvailable < 0)
                    {
                        realAvailable = 0;
                    }
                    fromProcMemInfo.AvailableMemoryForProcessing.Set(realAvailable, SizeUnit.Bytes);
                }

                fromProcMemInfo.TotalMemory.Set(maxMemoryUsage, SizeUnit.Bytes);
                fromProcMemInfo.CommitLimit.Set(Math.Max(maxMemoryUsage, commitedMemoryInBytes), SizeUnit.Bytes);
            }

            var workingSet = new Size(0, SizeUnit.Bytes);
            var swapUsage  = new Size(0, SizeUnit.Bytes);

            if (smapsReader != null)
            {
                // extended info is needed

                var procStatus = GetMemoryUsageFromProcStatus();
                workingSet.Set(procStatus.Rss, SizeUnit.Bytes);
                swapUsage.Set(procStatus.Swap, SizeUnit.Bytes);
            }

            SetMemoryRecords(fromProcMemInfo.AvailableMemoryForProcessing.GetValue(SizeUnit.Bytes));

            return(new MemoryInfoResult
            {
                TotalCommittableMemory = fromProcMemInfo.CommitLimit,
                CurrentCommitCharge = fromProcMemInfo.Commited,

                AvailableMemory = fromProcMemInfo.AvailableMemory,
                AvailableMemoryForProcessing = fromProcMemInfo.AvailableMemoryForProcessing,
                SharedCleanMemory = fromProcMemInfo.SharedCleanMemory,
                TotalPhysicalMemory = fromProcMemInfo.TotalMemory,
                InstalledMemory = fromProcMemInfo.TotalMemory,
                WorkingSet = workingSet,

                TotalSwapSize = fromProcMemInfo.TotalSwap,
                TotalSwapUsage = swapUsage,
                WorkingSetSwapUsage = fromProcMemInfo.WorkingSetSwap,

                IsExtended = extended
            });
        }
예제 #4
0
        private static bool GetFromProcMemInfo(SmapsReader smapsReader, ref ProcMemInfoResults procMemInfoResults)
        {
            const string path = "/proc/meminfo";

            // this is different then sysinfo freeram+buffered (and the closest to the real free memory)
            // MemFree is really different then MemAvailable (while free is usually lower then the real free,
            // and available is only estimated free which sometimes higher then the real free memory)
            // for some distros we have only MemFree
            try
            {
                using (var bufferedReader = new KernelVirtualFileSystemUtils.BufferedPosixKeyValueOutputValueReader(path))
                {
                    bufferedReader.ReadFileIntoBuffer();
                    var memAvailableInKb = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(MemAvailable);
                    var memFreeInKb      = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(MemFree);
                    var totalMemInKb     = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(MemTotal);
                    var swapTotalInKb    = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(SwapTotal);
                    var commitedInKb     = bufferedReader.ExtractNumericValueFromKeyValuePairsFormattedFile(Committed_AS);

                    var totalClean        = new Size(0, SizeUnit.Kilobytes);
                    var totalDirty        = new Size(0, SizeUnit.Bytes);
                    var sharedCleanMemory = new Size(0, SizeUnit.Bytes);
                    var swapWorkingSet    = new Size(0, SizeUnit.Bytes);
                    if (smapsReader != null)
                    {
                        var result = smapsReader.CalculateMemUsageFromSmaps <SmapsReaderNoAllocResults>();
                        totalClean.Add(result.SharedClean, SizeUnit.Bytes);
                        totalClean.Add(result.PrivateClean, SizeUnit.Bytes);
                        sharedCleanMemory.Set(result.SharedClean, SizeUnit.Bytes);
                        totalDirty.Add(result.TotalDirty, SizeUnit.Bytes);
                        swapWorkingSet.Add(result.Swap, SizeUnit.Bytes);
                    }

                    procMemInfoResults.AvailableMemory = new Size(memFreeInKb, SizeUnit.Kilobytes);
                    procMemInfoResults.TotalMemory     = new Size(totalMemInKb, SizeUnit.Kilobytes);
                    procMemInfoResults.Commited        = new Size(commitedInKb, SizeUnit.Kilobytes);

                    // on Linux, we use the swap + ram as the commit limit, because the actual limit
                    // is dependent on many different factors
                    procMemInfoResults.CommitLimit = new Size(totalMemInKb + swapTotalInKb, SizeUnit.Kilobytes);

                    // AvailableMemoryForProcessing: AvailableMemory actually does add reclaimable memory (divided by 2), so if AvailableMemory is equal or lower then the _real_ available memory
                    // If it is lower the the real value because of RavenDB's Clean memory - then we use 'totalClean' as reference
                    // Otherwise - either it is correct value, or it is lower because of (clean or dirty memory of) another process
                    var availableMemoryForProcessing = new Size(Math.Max(memAvailableInKb, memFreeInKb), SizeUnit.Kilobytes);
                    procMemInfoResults.AvailableMemoryForProcessing = Size.Max(availableMemoryForProcessing, totalClean);

                    procMemInfoResults.SharedCleanMemory = sharedCleanMemory;
                    procMemInfoResults.TotalDirty        = totalDirty;
                    procMemInfoResults.TotalSwap         = new Size(swapTotalInKb, SizeUnit.Kilobytes);
                    procMemInfoResults.WorkingSetSwap    = swapWorkingSet;
                }
            }
            catch (Exception ex)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info($"Failed to read value from {path}", ex);
                }

                return(false);
            }

            return(true);
        }