usage:

SystemEnvironment.CPULOAD

SystemEnvironment.AvailablePhysicalMemory

SystemEnvironment.UsedPhysicalMemory

SystemEnvironment.TotalPhysicalMemory

 

SystemEnvironment.cs

namespace GVMServer.Ns.Deployment
{
    using System;
    using System.Collections.Concurrent;
    using System.Diagnostics;
    using System.Linq;
    using System.Net;
    using System.Net.NetworkInformation;
    using System.Net.Sockets;
    using System.Runtime.InteropServices;
    using GVMServer.DDD.Service;
    using GVMServer.Net;
    using GVMServer.Ns.Deployment.Os;
    using GVMServer.Ns.Functional;
    using Microsoft.Extensions.Configuration;
    using Thread = System.Threading.Thread;
    using Timer = GVMServer.Threading.Timer;

    public class SystemEnvironment
    {
        private static readonly Stopwatch _getMemoryStatusWath = new Stopwatch();
        private static MEMORY_INFO _memoryStatusInfo = new MEMORY_INFO();

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct MEMORY_INFO
        {
            public uint dwLength; // 当前结构体大小
            public uint dwMemoryLoad; // 当前内存使用率
            public long ullTotalPhys; // 总计物理内存大小
            public long ullAvailPhys; // 可用物理内存大小
            public long ullTotalPageFile; // 总计交换文件大小
            public long ullAvailPageFile; // 总计交换文件大小
            public long ullTotalVirtual; // 总计虚拟内存大小
            public long ullAvailVirtual; // 可用虚拟内存大小
            public long ullAvailExtendedVirtual; // 保留 这个值始终为0
        }

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GlobalMemoryStatusEx(ref MEMORY_INFO mi);

        private unsafe static MEMORY_INFO GetMemoryStatus()
        {
            lock (_getMemoryStatusWath)
            {
                if (!_getMemoryStatusWath.IsRunning || _getMemoryStatusWath.ElapsedMilliseconds >= 500)
                {
                    _getMemoryStatusWath.Restart();
                    _memoryStatusInfo.dwLength = (uint)sizeof(MEMORY_INFO);
                    if (IsWindows())
                    {
                        GlobalMemoryStatusEx(ref _memoryStatusInfo);
                    }
                    else
                    {
                        CPULinuxLoadValue.GlobalMemoryStatus(ref _memoryStatusInfo);
                    }
                }
                return _memoryStatusInfo;
            }
        }

        private static long g_llInOutNicBytesReceived = 0;
        private static long g_llInOutNicBytesSent = 0;

        private static Timer g_tmrPerSecondTickTimer = new Timer(1000);
        private static NetworkInterface m_poInOutNetworkInterface = null;
        private static string[] g_aoHostIPAddress;
        private static ConcurrentDictionary<int, Stopwatch> m_poStopWatchTable = new ConcurrentDictionary<int, Stopwatch>();

        static SystemEnvironment()
        {
            g_tmrPerSecondTickTimer.Tick += (sender, e) => OnTick(e);
            g_tmrPerSecondTickTimer.Start();

            OnTick(EventArgs.Empty);
        }

        protected static void OnTick(EventArgs e)
        {
            // 刷新当前出入流量网卡的信息
            do
            {
                NetworkInterface poInOutNetworkInterface = QUERY_INOUT_NETWORK_INTERFACE();
                if (m_poInOutNetworkInterface == null || m_poInOutNetworkInterface.Name != poInOutNetworkInterface?.Name)
                {
                    IPInterfaceStatistics poIPInterfaceStatistics = poInOutNetworkInterface?.GetIPStatistics();
                    if (poIPInterfaceStatistics != null)
                    {
                        g_llInOutNicBytesReceived = poIPInterfaceStatistics.BytesReceived;
                        g_llInOutNicBytesSent = poIPInterfaceStatistics.BytesSent;
                    }

                    PerSecondBytesSent = 0;
                    PerSecondBytesReceived = 0;
                }
                else
                {
                    IPInterfaceStatistics poIPInterfaceStatistics = poInOutNetworkInterface.GetIPStatistics();
                    if (poIPInterfaceStatistics != null)
                    {
                        PerSecondBytesSent = poIPInterfaceStatistics.BytesReceived - g_llInOutNicBytesReceived;
                        PerSecondBytesReceived = poIPInterfaceStatistics.BytesSent - g_llInOutNicBytesSent;

                        g_llInOutNicBytesReceived = poIPInterfaceStatistics.BytesReceived;
                        g_llInOutNicBytesSent = poIPInterfaceStatistics.BytesSent;
                    }
                }
                m_poInOutNetworkInterface = poInOutNetworkInterface;
            } while (false);

            // 刷新当前主机节点的网络链路畅通的数字地址
            do
            {
                var aoHostIPAddress = SocketClient.GetActivityIPAddress().Select(i => i.ToString()).ToList();
                var application = ServiceObjectContainer.Get<BaseApplication>();
                if (application != null)
                {
                    var s = application.GetConfiguration().GetSection("HostAddresses").Get<string[]>();
                    if (s != null && s.Length > 0)
                    {
                        int index = 0;
                        foreach (string i in s)
                        {
                            if (string.IsNullOrEmpty(i))
                            {
                                continue;
                            }

                            string x = i.TrimStart().TrimEnd();
                            if (string.IsNullOrEmpty(x))
                            {
                                continue;
                            }

                            aoHostIPAddress.Insert(index++, x);
                        }
                    }
                }
                g_aoHostIPAddress = aoHostIPAddress.ToArray();
            } while (false);
            if (IsWindows())
            {
                CPUWin32LoadValue.Refresh();
            }
            else
            {
                CPULinuxLoadValue.Refresh();
            }
        }

        public unsafe static bool Equals(IPAddress x, IPAddress y)
        {
            if (x == null && y == null)
                return true;
            if (x.AddressFamily != y.AddressFamily)
                return false;

            byte[] bx = x.GetAddressBytes();
            byte[] by = y.GetAddressBytes();
            if (bx.Length != by.Length)
                return false;

            fixed (byte* pinnedX = bx)
            {
                fixed (byte* pinnedY = by)
                {
                    if (bx.Length == 4)
                        return *(uint*)pinnedX == *(uint*)pinnedY; // 32bit
                    else if (bx.Length == 8)
                        return *(ulong*)pinnedX == *(ulong*)pinnedY; // 64bit
                    else if (bx.Length == 16)
                        return *(decimal*)pinnedX == *(decimal*)pinnedY; // 128bit
                    else if (bx.Length == 2)
                        return *(ushort*)pinnedX == *(ushort*)pinnedY; // 16bit
                    else if (bx.Length == 1)
                        return *pinnedX == *pinnedY;
                    else
                    {
                        for (int i = 0; i < bx.Length; ++i)
                            if (pinnedX[i] != pinnedY[i])
                                return false;
                        return true;
                    }
                }
            }
        }

        private static NetworkInterface QUERY_INOUT_NETWORK_INTERFACE()
        {
            return NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault(ni =>
            {
                if (ni.NetworkInterfaceType != NetworkInterfaceType.Ethernet &&
                    ni.NetworkInterfaceType != NetworkInterfaceType.Wireless80211 &&
                    ni.NetworkInterfaceType != NetworkInterfaceType.Ppp) // PPPOE宽带拨号
                {
                    return false;
                }

                if (ni.OperationalStatus != OperationalStatus.Up)
                {
                    return false;
                }

                foreach (var addressInfo in ni.GetIPProperties().UnicastAddresses)
                {
                    if (addressInfo.Address.AddressFamily != AddressFamily.InterNetwork)
                    {
                        continue;
                    }

                    if (Equals(addressInfo.Address, IPAddress.Any)
                        || Equals(addressInfo.Address, IPAddress.None)
                        || Equals(addressInfo.Address, IPAddress.Broadcast)
                        || Equals(addressInfo.Address, IPAddress.Loopback))
                    {
                        continue;
                    }

                    if (IsWindows())
                    {
                        if (addressInfo.DuplicateAddressDetectionState == DuplicateAddressDetectionState.Preferred)
                        {
                            return true;
                        }
                    }
                    else
                    {
                        return true;
                    }
                }
                return false;
            });
        }

        public static long PerSecondBytesSent { get; set; }

        public static long PerSecondBytesReceived { get; set; }

        public static double CPULOAD
        {
            get
            {
                if (IsWindows())
                {
                    return CPUWin32LoadValue.CPULOAD;
                }
                return CPULinuxLoadValue.CPULOAD;
            }
        }

        public static long AvailablePhysicalMemory => GetMemoryStatus().ullAvailPhys;

        public static long UsedPhysicalMemory
        {
            get
            {
                MEMORY_INFO mi = GetMemoryStatus();
                return (mi.ullTotalPhys - mi.ullAvailPhys);
            }
        }

        public static bool IsWindows()
        {
            var platform = Environment.OSVersion.Platform;
            return platform == PlatformID.Win32NT;
        }

        public static long TotalPhysicalMemory => GetMemoryStatus().ullTotalPhys;

        public static long PrivateWorkingSet => Environment.WorkingSet;

        public static int ProcessorCount => Environment.ProcessorCount;

        public static string[] GetHostIPAddress() => g_aoHostIPAddress;

        public static NetworkInterface GetInOutNetworkInterface() => m_poInOutNetworkInterface;

        public static int ClockSleepTime(int maxConcurrent)
        {
            int intManagedThreadId = Thread.CurrentThread.ManagedThreadId;
            lock (m_poStopWatchTable)
            {
                if (!m_poStopWatchTable.TryGetValue(intManagedThreadId, out Stopwatch poStopWatch) || poStopWatch == null)
                {
                    poStopWatch = new Stopwatch();
                    poStopWatch.Start();
                    m_poStopWatchTable[intManagedThreadId] = poStopWatch;
                }
                long llElapsedWatchTicks = poStopWatch.ElapsedTicks;
                double dblTotalMilliseconds = llElapsedWatchTicks / 10000.00;
                if (dblTotalMilliseconds < 1)
                {
                    return 0;
                }
                poStopWatch.Restart();
            }
            const double MAX_USE_LOAD = NsLoadbalancing.MAX_CPULOAD_ULTIMATE_NOT_EXCEEDING;
            if (maxConcurrent <= 0)
            {
                return 0;
            }
            double dblUseLoad = SystemEnvironment.CPULOAD;
            if (dblUseLoad < MAX_USE_LOAD) // 控制CPU利用率
            {
                return 0;
            }
            else
            {
                double dblAviLoad = unchecked(dblUseLoad - MAX_USE_LOAD);
                double dblSleepTime = unchecked(dblAviLoad / maxConcurrent);
                dblSleepTime = Math.Ceiling(dblSleepTime);
                if (dblSleepTime < 1)
                {
                    dblSleepTime = 1;
                }
                return unchecked((int)dblSleepTime);
            }
        }
    }
}

CPUWin32LoadValue.cs

namespace GVMServer.Ns.Deployment.Os
{
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.ComTypes;

    static class CPUWin32LoadValue
    {
        private static ulong g_tsSysDeltaTime = 0;
        private static ulong g_tsSysLastTime = 0;

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GetProcessTimes(IntPtr hProcess, out FILETIME
            lpCreationTime, out FILETIME lpExitTime, out FILETIME lpKernelTime,
            out FILETIME lpUserTime);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern void GetSystemTimeAsFileTime(out FILETIME lpExitTime);

        private static DateTime FiletimeToDateTime(FILETIME fileTime)
        {
            //NB! uint conversion must be done on both fields before ulong conversion
            ulong hFT2 = unchecked((((ulong)(uint)fileTime.dwHighDateTime) << 32) | (uint)fileTime.dwLowDateTime);
            return DateTime.FromFileTimeUtc((long)hFT2);
        }

        private static TimeSpan FiletimeToTimeSpan(FILETIME fileTime)
        {
            //NB! uint conversion must be done on both fields before ulong conversion
            ulong hFT2 = unchecked((((ulong)(uint)fileTime.dwHighDateTime) << 32) |
                (uint)fileTime.dwLowDateTime);
            return TimeSpan.FromTicks((long)hFT2);
        }

        private static ulong FiletimeToUlong(FILETIME fileTime)
        {
            //NB! uint conversion must be done on both fields before ulong conversion
            ulong hFT2 = unchecked((((ulong)(uint)fileTime.dwHighDateTime) << 32) |
                (uint)fileTime.dwLowDateTime);
            return hFT2;
        }

        private static double QUERY_CPULOAD()
        {
            if (!SystemEnvironment.IsWindows())
            {
                return 0; 
            }

            GetSystemTimeAsFileTime(out FILETIME ftNow);

            if (!GetProcessTimes(Process.GetCurrentProcess().Handle,
                out FILETIME ftCreation,
                out FILETIME ftExit,
                out FILETIME ftKernel,
                out FILETIME ftUser))
            {
                return 0;
            }

            ulong tsCpuUsageTime = (FiletimeToUlong(ftKernel) +
                FiletimeToUlong(ftUser));
            if (g_tsSysDeltaTime == 0)
            {
                g_tsSysDeltaTime = tsCpuUsageTime;
                return 0;
            }

            ulong ftSystemNowTime = FiletimeToUlong(ftNow);
            ulong tsSysTimeDelta = ftSystemNowTime - g_tsSysLastTime;
            ulong tsSystemTimeDelta = tsCpuUsageTime - g_tsSysDeltaTime;

            double cpu_load = (tsSystemTimeDelta * 100.00d + tsSysTimeDelta / 2.00d) / tsSysTimeDelta;
            g_tsSysLastTime = ftSystemNowTime;
            g_tsSysDeltaTime = tsCpuUsageTime;

            cpu_load = cpu_load / Environment.ProcessorCount;
            if (cpu_load < 0 ||
                double.IsInfinity(cpu_load) ||
                double.IsNaN(cpu_load) ||
                double.IsNegativeInfinity(cpu_load) ||
                double.IsPositiveInfinity(cpu_load))
            {
                cpu_load = 0;
            }

            return cpu_load;
        }

        public static double CPULOAD { get; private set; }

        public static void Refresh() => CPULOAD = QUERY_CPULOAD();
    }
}

CPULinuxLoadValue.cs

namespace GVMServer.Ns.Deployment.Os
{
    using System;
    using System.IO;

    static class CPULinuxLoadValue
    {
        private static CPU_OCCUPY previous_cpu_occupy = null;
        private static readonly object syncobj = new object();

        private class CPU_OCCUPY
        {
            public string name;
            public long user;
            public long nice;
            public long system;
            public long idle;
            public long lowait;
            public long irq;
            public long softirq;
        }

        public static double CPULOAD { get; private set; }

        public static void Refresh()
        {
            CPULOAD = QUERY_CPULOAD();
        }

        private static double QUERY_CPULOAD(bool a = true)
        {
            lock (syncobj)
            {
                CPU_OCCUPY current_cpu_occupy = get_cpuoccupy();
                if (current_cpu_occupy == null || previous_cpu_occupy == null)
                {
                    previous_cpu_occupy = current_cpu_occupy;
                    return 0;
                }
                try
                {
                    long od = (previous_cpu_occupy.user + previous_cpu_occupy.nice + previous_cpu_occupy.system + previous_cpu_occupy.idle + previous_cpu_occupy.lowait + previous_cpu_occupy.irq + previous_cpu_occupy.softirq);//第一次(用户+优先级+系统+空闲)的时间再赋给od
                    long nd = (current_cpu_occupy.user + current_cpu_occupy.nice + current_cpu_occupy.system + current_cpu_occupy.idle + current_cpu_occupy.lowait + current_cpu_occupy.irq + current_cpu_occupy.softirq);//第二次(用户+优先级+系统+空闲)的时间再赋给od

                    double sum = nd - od;
                    double idle = current_cpu_occupy.idle - previous_cpu_occupy.idle;
                    double cpu_use = idle / sum;

                    if (!a)
                    {
                        idle = current_cpu_occupy.user + current_cpu_occupy.system + current_cpu_occupy.nice - previous_cpu_occupy.user - previous_cpu_occupy.system - previous_cpu_occupy.nice;
                        cpu_use = idle / sum;
                    }

                    cpu_use = (cpu_use * 100) / Environment.ProcessorCount;
                    return cpu_use;
                }
                finally
                {
                    previous_cpu_occupy = current_cpu_occupy;
                }
            }
        }

        private static string ReadArgumentValue(StreamReader sr)
        {
            string values = null;
            if (sr != null)
            {
                while (!sr.EndOfStream)
                {
                    char ch = (char)sr.Read();
                    if (ch == ' ')
                    {
                        if (values == null)
                        {
                            continue;
                        }
                        break;
                    }
                    values += ch;
                }
            }
            return values;
        }

        private static long ReadArgumentValueInt64(StreamReader sr)
        {
            string s = ReadArgumentValue(sr);
            if (string.IsNullOrEmpty(s))
            {
                return 0;
            }
            long r;
            long.TryParse(s, out r);
            return r;
        }

        private static CPU_OCCUPY get_cpuoccupy()
        {
            string path = "/proc/stat";
            if (!File.Exists(path))
            {
                return null;
            }
            FileStream stat = null;
            try
            {
                stat = File.OpenRead(path);
                if (stat == null)
                {
                    return null;
                }
            }
            catch (Exception)
            {
                return null;
            }
            using (StreamReader sr = new StreamReader(stat))
            {
                CPU_OCCUPY occupy = new CPU_OCCUPY();
                try
                {
                    occupy.name = ReadArgumentValue(sr);
                    occupy.user = ReadArgumentValueInt64(sr);
                    occupy.nice = ReadArgumentValueInt64(sr);
                    occupy.system = ReadArgumentValueInt64(sr);
                    occupy.idle = ReadArgumentValueInt64(sr);
                    occupy.lowait = ReadArgumentValueInt64(sr);
                    occupy.irq = ReadArgumentValueInt64(sr);
                    occupy.softirq = ReadArgumentValueInt64(sr);
                }
                catch (Exception)
                {
                    return null;
                }
                return occupy;
            }
        }

        public static bool GlobalMemoryStatus(ref SystemEnvironment.MEMORY_INFO mi)
        {
            string path = "/proc/meminfo";
            if (!File.Exists(path))
            {
                return false;
            }
            FileStream stat = null;
            try
            {
                stat = File.OpenRead(path);
                if (stat == null)
                {
                    return false;
                }
            }
            catch (Exception)
            {
                return false;
            }
            long? call(string line, string key)
            {
                int i = line.IndexOf(':');
                if (i < 0)
                {
                    return null;
                }
                string lk = line.Substring(0, i);
                if (string.IsNullOrEmpty(lk))
                {
                    return null;
                }
                if (lk != key)
                {
                    return null;
                }
                line = line.Substring(i + 1).TrimStart();
                if (string.IsNullOrEmpty(line))
                {
                    return null;
                }
                string[] sp = line.Split(' ');
                if (sp == null || sp.Length <= 0)
                {
                    return null;
                }
                line = sp[0];
                if (string.IsNullOrEmpty(line))
                {
                    return null;
                }
                long.TryParse(line, out long n);
                return n * 1024;
            }
            using (StreamReader sr = new StreamReader(stat))
            {
                try
                {
                    int counts = 0;
                    string line = string.Empty;
                    while (counts < 2 && !string.IsNullOrEmpty(line = sr.ReadLine()))
                    {
                        long? value = call(line, "MemTotal");
                        if (value != null)
                        {
                            counts++;
                            mi.ullTotalPhys = value.Value;
                            continue;
                        }
                        value = call(line, "MemAvailable");
                        if (value != null)
                        {
                            counts++;
                            mi.ullAvailPhys = value.Value;
                            continue;
                        }
                    }
                    return true;
                }
                catch (Exception)
                {
                    return false;
                }
            }
        }
    }
}

 

GitHub 加速计划 / li / linux-dash
6
1
下载
A beautiful web dashboard for Linux
最近提交(Master分支:3 个月前 )
186a802e added ecosystem file for PM2 4 年前
5def40a3 Add host customization support for the NodeJS version 4 年前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐