2024-06-28 14:48:28 +03:00

211 lines
5.7 KiB
C#

using Esiur.Core;
using Esiur.Data;
using Esiur.Resource;
using Mono.Unix.Native;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text;
using System.Timers;
namespace AZ.Compute.Agent
{
[Resource]
public partial class Node
{
System.Timers.Timer timer;
PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;
NetworkInterface nic;
ulong totalNetworkBytes;
const double nicSpeed = 1 * 1024 * 1024; // 1 MBps
// linux
float prevCpuIdle = 0f;
float prevCpuTotal = 0f;
[Export] string id;
[Export] string ip;
[Export] float cpu;
[Export] float ram;
[Export] float network;
[Export] uint tasks;
[Export] uint cpuClock;
[Export] uint cpuMaxClock;
[Export] float networkSpeed;
[Export] Job[] jobs = new Job[0];
[Export]
public async AsyncReply<Job> Compute(string fileName, string arguments)
{
var psi = new ProcessStartInfo()
{
FileName = fileName,
Arguments = arguments
};
var p = Process.Start(psi);
var job = await Warehouse.New<Job>(fileName, null, this);
job.Process = p;
Jobs = jobs.Append(job).ToArray();
return job;
}
ulong GetNetworkLinux()
{
var netLines = File
.ReadAllLines("/proc/net/dev")
.Skip(3)
.First()
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Skip(1)
.Select(ulong.Parse)
.ToArray();
// Console.WriteLine($"NetL {netLines[0]} {netLines[8]}");
return netLines[0] + netLines[8];
}
float GetLinuxCPU(float interval = 5)
{
var cpuLine = File
.ReadAllLines("/proc/stat")
.First()
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Skip(1)
.Select(float.Parse)
.ToArray();
var idle = cpuLine[3];
var total = cpuLine.Sum();
var percent = 100.0 * (1.0 - (idle - prevCpuIdle) / (total - prevCpuTotal));
//Console.WriteLine($"CPU {percent:0.00}%");
prevCpuIdle = idle;
prevCpuTotal = total;
return (float)percent / interval;
}
float GetLinuxRAM()
{
return File
.ReadAllLines("/proc/meminfo")
.Skip(1)
.First()
.Split(' ', StringSplitOptions.RemoveEmptyEntries)
.Skip(1)
.Select(ulong.Parse)
.First() / 1024;
//Console.WriteLine("Free " + freeMem);
var pages = Syscall.sysconf(SysconfName._SC_PHYS_PAGES);
var pageSize = Syscall.sysconf(SysconfName._SC_PAGESIZE);
var ram = pages * pageSize / 1024.0f;
Console.WriteLine($"RAM {ram:0.00}%");
return ram;
}
public Node()
{
Id = System.Environment.MachineName;
nic = NetworkInterface.GetAllNetworkInterfaces().Where(x => x.OperationalStatus == OperationalStatus.Up).First();
networkSpeed = (float)(nic.Speed / 1048576.0);
totalNetworkBytes = (ulong)nic.GetIPv4Statistics().BytesReceived + (ulong)nic.GetIPv4Statistics().BytesSent;
Ip = nic.GetIPProperties().UnicastAddresses.First(x => x.Address.AddressFamily == AddressFamily.InterNetwork).Address.ToString();
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
using (ManagementObject Mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'"))
{
cpuClock = (uint)(Mo["CurrentClockSpeed"]);
cpuMaxClock = (uint)(Mo["MaxClockSpeed"]);
}
cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
}
timer = new System.Timers.Timer();
timer.Elapsed += Timer_Elapsed;
timer.Interval = 5000;
timer.Start();
}
private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
{
try
{
ulong ntb = 0;
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
ntb = (ulong)nic.GetIPv4Statistics().BytesReceived + (ulong)nic.GetIPv4Statistics().BytesSent;
Cpu = cpuCounter.NextValue();
Ram = ramCounter.NextValue();
}
else
{
ntb = GetNetworkLinux();
Cpu = GetLinuxCPU();
Ram = GetLinuxRAM();
}
Network = (float)(((ntb - totalNetworkBytes) / 5.0) / nicSpeed);
totalNetworkBytes = ntb;
//Console.WriteLine("Net " + Network + " " + ntb);
foreach (Job job in jobs)
{
if (!job.Finished)
{
job.Start = job.Start;
job.Ram = (float)(job.Process.PeakWorkingSet64 / 1048576.0);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
}
}