Пример #1
0
        public static MemoryInfoResult GetMemoryInfo(SmapsReader smapsReader = null)
        {
            if (_failedToGetAvailablePhysicalMemory)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Because of a previous error in getting available memory, we are now lying and saying we have 256MB free");
                }
                return(FailedResult);
            }

            try
            {
                if (PlatformDetails.RunningOnPosix == false)
                {
                    return(GetMemoryInfoWindows());
                }

                if (PlatformDetails.RunningOnMacOsx)
                {
                    return(GetMemoryInfoMacOs());
                }

                return(GetMemoryInfoLinux(smapsReader));
            }
            catch (Exception e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Error while trying to get available memory, will stop trying and report that there is 256MB free only from now on", e);
                }
                _failedToGetAvailablePhysicalMemory = true;
                return(FailedResult);
            }
        }
        public static MachineResources GetMachineResources(SmapsReader smapsReader)
        {
            using (var currentProcess = Process.GetCurrentProcess())
            {
                var memInfo     = MemoryInformation.GetMemoryInfo(smapsReader);
                var isLowMemory = LowMemoryNotification.Instance.IsLowMemory(memInfo);
                var workingSet  = PlatformDetails.RunningOnLinux
                    ? MemoryInformation.GetRssMemoryUsage(currentProcess.Id) - memInfo.AvailableWithoutTotalCleanMemory.GetValue(SizeUnit.Bytes)
                    : currentProcess.WorkingSet64;

                var cpuInfo = CpuUsage.Calculate();

                var machineResources = new MachineResources
                {
                    TotalMemory     = memInfo.TotalPhysicalMemory.GetValue(SizeUnit.Bytes),
                    AvailableMemory = memInfo.AvailableMemory.GetValue(SizeUnit.Bytes),
                    AvailableWithoutTotalCleanMemory = memInfo.AvailableWithoutTotalCleanMemory.GetValue(SizeUnit.Bytes),
                    SystemCommitLimit     = memInfo.TotalCommittableMemory.GetValue(SizeUnit.Bytes),
                    CommittedMemory       = memInfo.CurrentCommitCharge.GetValue(SizeUnit.Bytes),
                    ProcessMemoryUsage    = workingSet,
                    IsWindows             = PlatformDetails.RunningOnPosix == false,
                    IsLowMemory           = isLowMemory,
                    LowMemoryThreshold    = LowMemoryNotification.Instance.LowMemoryThreshold.GetValue(SizeUnit.Bytes),
                    CommitChargeThreshold = LowMemoryNotification.Instance.GetCommitChargeThreshold(memInfo).GetValue(SizeUnit.Bytes),
                    MachineCpuUsage       = cpuInfo.MachineCpuUsage,
                    ProcessCpuUsage       = Math.Min(cpuInfo.MachineCpuUsage, cpuInfo.ProcessCpuUsage) // min as sometimes +-1% due to time sampling
                };

                return(machineResources);
            }
        }
Пример #3
0
        public static MemoryInfoResult GetMemoryInformationUsingOneTimeSmapsReader()
        {
            SmapsReader smapsReader = null;

            byte[][] buffers = null;
            try
            {
                if (PlatformDetails.RunningOnLinux)
                {
                    var buffer1 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                    var buffer2 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                    buffers     = new[] { buffer1, buffer2 };
                    smapsReader = new SmapsReader(new[] { buffer1, buffer2 });
                }

                return(GetMemoryInfo(smapsReader, extended: true));
            }
            finally
            {
                if (buffers != null)
                {
                    ArrayPool <byte> .Shared.Return(buffers[0]);

                    ArrayPool <byte> .Shared.Return(buffers[1]);
                }
            }
        }
Пример #4
0
        public void ParsesSmapsProperly()
        {
            var assembly    = typeof(SmapsReaderTests).Assembly;
            var smapsReader = new SmapsReader(new[]
            {
                new byte[SmapsReader.BufferSize], new byte[SmapsReader.BufferSize]
            });

            SmapsReader.SmapsReadResult <SmapsTestResult> result;

            using (var fs =
                       assembly.GetManifestResourceStream("SlowTests.Data.RavenDB_15159.12119.smaps.gz"))
                using (var deflated = new GZipStream(fs, CompressionMode.Decompress))
                    using (var smapsStream = new FakeProcSmapsEntriesStream(deflated))
                    {
                        result = smapsReader
                                 .CalculateMemUsageFromSmaps <SmapsTestResult>(smapsStream, pid: 1234);
                    }

            // 385 .buffers
            // 181 .voron
            Assert.Equal(385 + 181, result.SmapsResults.Entries.Count);

            // cat 12119.smaps | grep -e "rw-s" -A 3 | awk '$1 ~ /Rss/ {sum += $2} END {print sum}'
            Assert.Equal(722136L * 1024, result.Rss);

            // cat 12119.smaps | grep -e "rw-s" -A 16 | awk '$1 ~ /Swap/ {sum += $2} END {print sum}'
            Assert.Equal(1348L * 1024, result.Swap);
        }
Пример #5
0
        private static MemoryInfoResult GetMemoryInfoLinux(SmapsReader smapsReader)
        {
            var fromProcMemInfo            = GetFromProcMemInfo(smapsReader);
            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     = KernelVirtualFileSystemUtils.ReadNumberFromCgroupFile(CgroupMemoryUsage);
                if (cgroupMemoryUsage != null)
                {
                    commitedMemoryInBytes = cgroupMemoryUsage.Value;
                    fromProcMemInfo.Commited.Set(commitedMemoryInBytes, SizeUnit.Bytes);
                    fromProcMemInfo.MemAvailable.Set(maxMemoryUsage - cgroupMemoryUsage.Value, SizeUnit.Bytes);
                }

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

            return(BuildPosixMemoryInfoResult(
                       fromProcMemInfo.MemAvailable,
                       fromProcMemInfo.TotalMemory,
                       fromProcMemInfo.Commited,
                       fromProcMemInfo.CommitLimit,
                       fromProcMemInfo.AvailableWithoutTotalCleanMemory,
                       fromProcMemInfo.SharedCleanMemory
                       ));
        }
Пример #6
0
        public ServerMetricCacher(RavenServer server)
        {
            _server = server;

            if (PlatformDetails.RunningOnLinux)
            {
                _smapsReader = new SmapsReader(new[] { new byte[SmapsReader.BufferSize], new byte[SmapsReader.BufferSize] });
            }
        }
Пример #7
0
        public Task MemorySmaps()
        {
            if (PlatformDetails.RunningOnLinux == false)
            {
                using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
                {
                    var rc  = Win32MemoryQueryMethods.GetMaps();
                    var djv = new DynamicJsonValue
                    {
                        ["Totals"] = new DynamicJsonValue
                        {
                            ["WorkingSet"]          = rc.WorkingSet,
                            ["SharedClean"]         = "N/A",
                            ["PrivateClean"]        = "N/A",
                            ["TotalClean"]          = rc.ProcessClean,
                            ["RssHumanly"]          = Sizes.Humane(rc.WorkingSet),
                            ["SharedCleanHumanly"]  = "N/A",
                            ["PrivateCleanHumanly"] = "N/A",
                            ["TotalCleanHumanly"]   = Sizes.Humane(rc.ProcessClean)
                        },
                        ["Details"] = rc.Json
                    };
                    using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        context.Write(write, djv);
                    }
                    return(Task.CompletedTask);
                }
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var result = new SmapsReader().CalculateMemUsageFromSmaps();
                var djv    = new DynamicJsonValue
                {
                    ["Totals"] = new DynamicJsonValue
                    {
                        ["WorkingSet"]          = result.Rss,
                        ["SharedClean"]         = result.SharedClean,
                        ["PrivateClean"]        = result.PrivateClean,
                        ["TotalClean"]          = result.SharedClean + result.PrivateClean,
                        ["RssHumanly"]          = Sizes.Humane(result.Rss),
                        ["SharedCleanHumanly"]  = Sizes.Humane(result.SharedClean),
                        ["PrivateCleanHumanly"] = Sizes.Humane(result.PrivateClean),
                        ["TotalCleanHumanly"]   = Sizes.Humane(result.SharedClean + result.PrivateClean)
                    },
                    ["Details"] = result.Json
                };

                using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                {
                    context.Write(write, djv);
                }
                return(Task.CompletedTask);
            }
        }
Пример #8
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));
        }
Пример #9
0
        public async Task Get()
        {
            using (var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync())
            {
                using (var writer = new NotificationCenterWebSocketWriter(webSocket, ServerStore.ServerDashboardNotifications, ServerStore.ContextPool,
                                                                          ServerStore.ServerShutdown))
                {
                    var      isValidFor = GetDatabaseAccessValidationFunc();
                    byte[][] buffers    = null;
                    try
                    {
                        SmapsReader smapsReader = null;
                        if (PlatformDetails.RunningOnLinux)
                        {
                            var buffer1 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                            var buffer2 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                            buffers     = new[] { buffer1, buffer2 };
                            smapsReader = new SmapsReader(new[] { buffer1, buffer2 });
                        }

                        var machineResources = MachineResourcesNotificationSender.GetMachineResources(smapsReader);
                        await writer.WriteToWebSocket(machineResources.ToJson());

                        using (var cts = CancellationTokenSource.CreateLinkedTokenSource(ServerStore.ServerShutdown))
                        {
                            var databasesInfo = DatabasesInfoNotificationSender.FetchDatabasesInfo(ServerStore, isValidFor, cts);
                            foreach (var info in databasesInfo)
                            {
                                await writer.WriteToWebSocket(info.ToJson());
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        if (Logger.IsInfoEnabled)
                        {
                            Logger.Info("Failed to send the initial server dashboard data", e);
                        }
                    }
                    finally
                    {
                        if (buffers != null)
                        {
                            ArrayPool <byte> .Shared.Return(buffers[0]);

                            ArrayPool <byte> .Shared.Return(buffers[1]);
                        }
                    }

                    await writer.WriteNotifications(isValidFor);
                }
            }
        }
Пример #10
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);
        }
Пример #11
0
        public TestResourcesAnalyzerMetricCacher(ICpuUsageCalculator cpuUsageCalculator)
        {
            if (PlatformDetails.RunningOnLinux)
            {
                _smapsReader = new SmapsReader(new[] { new byte[SmapsReader.BufferSize], new byte[SmapsReader.BufferSize] });
            }

            Register(Keys.Server.CpuUsage, _cacheRefreshRate, cpuUsageCalculator.Calculate);
            Register(Keys.Server.MemoryInfo, _cacheRefreshRate, CalculateMemoryInfo);
            Register(Keys.Server.MemoryInfoExtended, _cacheRefreshRate, CalculateMemoryInfoExtended);
        }
Пример #12
0
            public TestResourcesAnalyzerMetricCacher(ICpuUsageCalculator cpuUsageCalculator)
            {
                if (PlatformDetails.RunningOnLinux)
                {
                    _smapsReader = new SmapsReader(new[] { new byte[SmapsReader.BufferSize], new byte[SmapsReader.BufferSize] });
                }

                Register(MetricCacher.Keys.Server.CpuUsage, TimeSpan.FromSeconds(1), cpuUsageCalculator.Calculate);
                Register(MetricCacher.Keys.Server.MemoryInfo, TimeSpan.FromSeconds(1), CalculateMemoryInfo);
                Register(MetricCacher.Keys.Server.MemoryInfoExtended, TimeSpan.FromSeconds(1), CalculateMemoryInfoExtended);
            }
Пример #13
0
        public LowMemoryMonitor()
        {
            if (PlatformDetails.RunningOnLinux)
            {
                var buffer1 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                var buffer2 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                _buffers     = new[] { buffer1, buffer2 };
                _smapsReader = new SmapsReader(_buffers);
            }
        }
        protected override async Task DoWork()
        {
            var now      = DateTime.UtcNow;
            var timeSpan = now - _lastSentNotification;

            if (timeSpan < _notificationsThrottle)
            {
                await WaitOrThrowOperationCanceled(_notificationsThrottle - timeSpan);
            }

            byte[][] buffers = null;
            try
            {
                if (CancellationToken.IsCancellationRequested)
                {
                    return;
                }

                if (_watchers.Count == 0)
                {
                    return;
                }

                SmapsReader smapsReader = null;
                if (PlatformDetails.RunningOnLinux)
                {
                    var buffer1 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                    var buffer2 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                    buffers     = new [] { buffer1, buffer2 };
                    smapsReader = new SmapsReader(new[] { buffer1, buffer2 });
                }
                var machineResources = GetMachineResources(smapsReader);
                foreach (var watcher in _watchers)
                {
                    // serialize to avoid race conditions
                    // please notice we call ToJson inside a loop since DynamicJsonValue is not thread-safe
                    watcher.NotificationsQueue.Enqueue(machineResources.ToJson());
                }
            }
            finally
            {
                _lastSentNotification = DateTime.UtcNow;
                if (buffers != null)
                {
                    ArrayPool <byte> .Shared.Return(buffers[0]);

                    ArrayPool <byte> .Shared.Return(buffers[1]);
                }
            }
        }
Пример #15
0
        internal static MemoryInfoResult GetMemoryInfo(SmapsReader smapsReader = null, bool extended = false)
        {
            if (_failedToGetAvailablePhysicalMemory)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Because of a previous error in getting available memory, we are now lying and saying we have 256MB free");
                }
                return(FailedResult);
            }

            try
            {
                extended &= PlatformDetails.RunningOnLinux == false;

                MemoryInfoResult result;
                using (var process = extended ? Process.GetCurrentProcess() : null)
                {
                    if (PlatformDetails.RunningOnPosix == false)
                    {
                        result = GetMemoryInfoWindows(process, extended);
                    }
                    else if (PlatformDetails.RunningOnMacOsx)
                    {
                        result = GetMemoryInfoMacOs(process, extended);
                    }
                    else
                    {
                        result = GetMemoryInfoLinux(smapsReader, extended);
                    }
                }

                var totalScratchAllocated = GetTotalScratchAllocatedMemory();

                result.AvailableMemory.Add(-totalScratchAllocated, SizeUnit.Bytes);
                return(result);
            }
            catch (Exception e)
            {
                if (Logger.IsInfoEnabled)
                {
                    Logger.Info("Error while trying to get available memory, will stop trying and report that there is 256MB free only from now on", e);
                }
                _failedToGetAvailablePhysicalMemory = true;
                return(FailedResult);
            }
        }
        public MachineResourcesNotificationSender(string resourceName,
                                                  ConcurrentSet <ConnectedWatcher> watchers, TimeSpan notificationsThrottle, CancellationToken shutdown)
            : base(resourceName, shutdown)
        {
            _watchers = watchers;
            _notificationsThrottle = notificationsThrottle;

            if (PlatformDetails.RunningOnLinux)
            {
                var buffer1 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                var buffer2 = ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize);

                _buffers     = new[] { buffer1, buffer2 };
                _smapsReader = new SmapsReader(new[] { buffer1, buffer2 });
            }
        }
Пример #17
0
        public static MachineResources GetMachineResources(SmapsReader smapsReader, ICpuUsageCalculator cpuUsageCalculator)
        {
            var memInfo = MemoryInformation.GetMemoryInfo(smapsReader, extendedInfo: true);
            var cpuInfo = cpuUsageCalculator.Calculate();

            var machineResources = new MachineResources
            {
                TotalMemory     = memInfo.TotalPhysicalMemory.GetValue(SizeUnit.Bytes),
                AvailableMemory = memInfo.AvailableMemory.GetValue(SizeUnit.Bytes),
                AvailableWithoutTotalCleanMemory = memInfo.AvailableWithoutTotalCleanMemory.GetValue(SizeUnit.Bytes),
                SystemCommitLimit     = memInfo.TotalCommittableMemory.GetValue(SizeUnit.Bytes),
                CommittedMemory       = memInfo.CurrentCommitCharge.GetValue(SizeUnit.Bytes),
                ProcessMemoryUsage    = memInfo.WorkingSet.GetValue(SizeUnit.Bytes),
                IsWindows             = PlatformDetails.RunningOnPosix == false,
                IsLowMemory           = LowMemoryNotification.Instance.IsLowMemory(memInfo, smapsReader),
                LowMemoryThreshold    = LowMemoryNotification.Instance.LowMemoryThreshold.GetValue(SizeUnit.Bytes),
                CommitChargeThreshold = LowMemoryNotification.Instance.GetCommitChargeThreshold(memInfo).GetValue(SizeUnit.Bytes),
                MachineCpuUsage       = cpuInfo.MachineCpuUsage,
                ProcessCpuUsage       = cpuInfo.ProcessCpuUsage
            };

            return(machineResources);
        }
Пример #18
0
 public MachineResources GetMachineResources(SmapsReader smapsReader)
 {
     return(GetMachineResources(smapsReader, _server.CpuUsageCalculator));
 }
Пример #19
0
        public Task MemorySmaps()
        {
            if (PlatformDetails.RunningOnLinux == false)
            {
                using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
                    using (var process = Process.GetCurrentProcess())
                    {
                        var sharedClean = MemoryInformation.GetSharedCleanInBytes(process);
                        var rc          = Win32MemoryQueryMethods.GetMaps();
                        var djv         = new DynamicJsonValue
                        {
                            ["Totals"] = new DynamicJsonValue
                            {
                                ["WorkingSet"]          = process.WorkingSet64,
                                ["SharedClean"]         = Sizes.Humane(sharedClean),
                                ["PrivateClean"]        = "N/A",
                                ["TotalClean"]          = rc.ProcessClean,
                                ["RssHumanly"]          = Sizes.Humane(process.WorkingSet64),
                                ["SharedCleanHumanly"]  = Sizes.Humane(sharedClean),
                                ["PrivateCleanHumanly"] = "N/A",
                                ["TotalCleanHumanly"]   = Sizes.Humane(rc.ProcessClean)
                            },
                            ["Details"] = rc.Json
                        };
                        using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                        {
                            context.Write(write, djv);
                        }
                        return(Task.CompletedTask);
                    }
            }

            using (ServerStore.ContextPool.AllocateOperationContext(out JsonOperationContext context))
            {
                var buffers = new[]
                {
                    ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize),
                    ArrayPool <byte> .Shared.Rent(SmapsReader.BufferSize)
                };
                try
                {
                    var result     = new SmapsReader(buffers).CalculateMemUsageFromSmaps <SmapsReaderJsonResults>();
                    var procStatus = MemoryInformation.GetMemoryUsageFromProcStatus();
                    var djv        = new DynamicJsonValue
                    {
                        ["Totals"] = new DynamicJsonValue
                        {
                            ["WorkingSet"]            = result.Rss,
                            ["SharedClean"]           = result.SharedClean,
                            ["PrivateClean"]          = result.PrivateClean,
                            ["TotalClean"]            = result.SharedClean + result.PrivateClean,
                            ["TotalDirty"]            = result.TotalDirty, // This includes not only r-ws buffer and voron files, but also dotnet's and heap dirty memory
                            ["WorkingSetSwap"]        = result.Swap,       // Swap values sum for r-ws entries only
                            ["Swap"]                  = procStatus.Swap,
                            ["RssHumanly"]            = Sizes.Humane(result.Rss),
                            ["SwapHumanly"]           = Sizes.Humane(procStatus.Swap),
                            ["WorkingSetSwapHumanly"] = Sizes.Humane(result.Swap),
                            ["SharedCleanHumanly"]    = Sizes.Humane(result.SharedClean),
                            ["PrivateCleanHumanly"]   = Sizes.Humane(result.PrivateClean),
                            ["TotalCleanHumanly"]     = Sizes.Humane(result.SharedClean + result.PrivateClean)
                        },
                        ["Details"] = result.SmapsResults.ReturnResults()
                    };

                    using (var write = new BlittableJsonTextWriter(context, ResponseBodyStream()))
                    {
                        context.Write(write, djv);
                    }

                    return(Task.CompletedTask);
                }
                finally
                {
                    ArrayPool <byte> .Shared.Return(buffers[0]);

                    ArrayPool <byte> .Shared.Return(buffers[1]);
                }
            }
        }
Пример #20
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
            });
        }
Пример #21
0
        internal int CheckMemoryStatus(SmapsReader smapsReader)
        {
            int  timeout;
            bool isLowMemory;
            long totalUnmanagedAllocations;

            (Size AvailableMemory, Size TotalPhysicalMemory, Size CurrentCommitCharge)stats;
            try
            {
                isLowMemory = GetLowMemory(out totalUnmanagedAllocations, out stats, smapsReader);
            }
            catch (OutOfMemoryException)
            {
                isLowMemory = true;
                stats       = (new Size(), new Size(), new Size());
                totalUnmanagedAllocations = -1;
            }
            if (isLowMemory)
            {
                if (LowMemoryState == false)
                {
                    try
                    {
                        if (_logger.IsInfoEnabled)
                        {
                            _logger.Info("Low memory detected, will try to reduce memory usage...");
                        }
                        AddLowMemEvent(LowMemReason.LowMemOnTimeoutChk,
                                       stats.AvailableMemory.GetValue(SizeUnit.Bytes),
                                       totalUnmanagedAllocations,
                                       stats.TotalPhysicalMemory.GetValue(SizeUnit.Bytes),
                                       stats.CurrentCommitCharge.GetValue(SizeUnit.Bytes));
                    }
                    catch (OutOfMemoryException)
                    {
                        // nothing we can do, we'll wait and try again
                    }
                }
                LowMemoryState = true;
                _clearInactiveHandlersCounter = 0;
                RunLowMemoryHandlers(true);
                timeout = 500;
            }
            else
            {
                if (LowMemoryState)
                {
                    if (_logger.IsInfoEnabled)
                    {
                        _logger.Info("Back to normal memory usage detected");
                    }
                    AddLowMemEvent(LowMemReason.BackToNormal,
                                   stats.AvailableMemory.GetValue(SizeUnit.Bytes),
                                   totalUnmanagedAllocations,
                                   stats.TotalPhysicalMemory.GetValue(SizeUnit.Bytes),
                                   stats.CurrentCommitCharge.GetValue(SizeUnit.Bytes));
                }
                LowMemoryState = false;
                RunLowMemoryHandlers(false);
                timeout = stats.AvailableMemory < _lowMemoryThreshold * 2 ? 1000 : 5000;
            }

            return(timeout);
        }
Пример #22
0
        private void MonitorMemoryUsage()
        {
            SmapsReader smapsReader = PlatformDetails.RunningOnLinux ? new SmapsReader(new[] { new byte[SmapsReader.BufferSize], new byte[SmapsReader.BufferSize] }) : null;

            NativeMemory.EnsureRegistered();
            var memoryAvailableHandles = new WaitHandle[] { _simulatedLowMemory, _shutdownRequested };
            var timeout = 5 * 1000;

            try
            {
                while (true)
                {
                    try
                    {
                        var result = WaitHandle.WaitAny(memoryAvailableHandles, timeout);
                        switch (result)
                        {
                        case WaitHandle.WaitTimeout:
                            timeout = CheckMemoryStatus(smapsReader);
                            break;

                        case 0:
                            SimulateLowMemory();
                            break;

                        case 1:     // shutdown requested
                            return;

                        default:
                            return;
                        }
                    }
                    catch (OutOfMemoryException)
                    {
                        try
                        {
                            if (_logger.IsInfoEnabled)
                            {
                                _logger.Info("Out of memory error in the low memory notification thread, will wait 5 seconds before trying to check memory status again. The system is likely running out of memory");
                            }
                        }
                        catch
                        {
                            // can't even log, nothing we can do here
                        }

                        if (_shutdownRequested.WaitOne(5000))
                        {
                            return; // shutdown requested
                        }
                    }
                }
            }
            catch (Exception e)
            {
                if (_logger.IsOperationsEnabled)
                {
                    _logger.Operations("Catastrophic failure in low memory notification", e);
                }
            }
        }
Пример #23
0
        public void Can_check_memory_status()
        {
            SmapsReader smapsReader = PlatformDetails.RunningOnLinux ? new SmapsReader(new[] { new byte[SmapsReader.BufferSize], new byte[SmapsReader.BufferSize] }) : null;

            LowMemoryNotification.Instance.CheckMemoryStatus(smapsReader);
        }
Пример #24
0
 private LowMemoryMonitor()
 {
     _smapsReader = PlatformDetails.RunningOnLinux ? new SmapsReader(new[] { new byte[SmapsReader.BufferSize], new byte[SmapsReader.BufferSize] }) : null;
 }
Пример #25
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);
        }