Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
425 views
in Technique[技术] by (71.8m points)

c# - Can you limit the CPU usage on a .NET Process Object?

An application I'm contributing to fires up a component written in C.

The C process does some pretty heavy crunching and if your not careful can really hammer your CPU.

Is there a way to set a limit to external processes spawned by .NET?

I've seen this artivcle on setting a hard memory limit at the OS level, is there a similar thing for CPU?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I had the same problem. I solved it by using SetInformationJobObject Kernel32 Win Api and JOBOBJECT_CPU_RATE_CONTROL_INFORMATION struct.

My bigger problem was to represent this structure in c# (uses "union"). Hopefully, I found a "mono" description of this structure.

[StructLayout(LayoutKind.Explicit)]
//[CLSCompliant(false)]
struct JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
{
    [FieldOffset(0)]
    public UInt32 ControlFlags;
    [FieldOffset(4)]
    public UInt32 CpuRate;
    [FieldOffset(4)]
    public UInt32 Weight;
}

To activate the Cpu limitation :

ControlFlags = 0x00000001 | 0x00000004;
CpuRate = percent of max usage  * 100 (ex 50 * 100 for a 50% limit)

The sample below is fully functional.

I hope that's help.

Kind Regards

-Thierry-

[DllImport("kernel32.dll", EntryPoint = "CreateJobObjectW", CharSet = CharSet.Unicode)]
public static extern IntPtr CreateJobObject(SecurityAttributes JobAttributes, string lpName);

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AssignProcessToJobObject(IntPtr hJob, IntPtr hProcess);

[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECTINFOCLASS JobObjectInfoClass, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);

public class SecurityAttributes
{

    public int nLength; 
    public IntPtr pSecurityDescriptor; 
    public bool bInheritHandle;

    public SecurityAttributes()
    {
        this.bInheritHandle = true;
        this.nLength = 0;
        this.pSecurityDescriptor = IntPtr.Zero;
    }
}

public enum JOBOBJECTINFOCLASS
{
    JobObjectAssociateCompletionPortInformation = 7,
    JobObjectBasicLimitInformation = 2,
    JobObjectBasicUIRestrictions = 4,
    JobObjectEndOfJobTimeInformation = 6,
    JobObjectExtendedLimitInformation = 9,
    JobObjectSecurityLimitInformation = 5,
    JobObjectCpuRateControlInformation = 15
}

[StructLayout(LayoutKind.Explicit)]
//[CLSCompliant(false)]
struct JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
{
    [FieldOffset(0)]
    public UInt32 ControlFlags;
    [FieldOffset(4)]
    public UInt32 CpuRate;
    [FieldOffset(4)]
    public UInt32 Weight;
}

public enum CpuFlags
{
    JOB_OBJECT_CPU_RATE_CONTROL_ENABLE = 0x00000001,
    JOB_OBJECT_CPU_RATE_CONTROL_WEIGHT_BASED = 0x00000002,
    JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP = 0x00000004
}

/// <summary>
/// Launch the legacy application with some options set.
/// </summary>
static void DoExecuteProgramm()
{
    // prepare the process to execute
    var startInfo = new ProcessStartInfo();
    . . . . . 
    // Start the process
    var process = Process.Start(startInfo);

    //Limit the CPU usage to 45%
    var jobHandle = CreateJobObject(null, null);
    AssignProcessToJobObject(jobHandle, process.Handle);
    var cpuLimits = new JOBOBJECT_CPU_RATE_CONTROL_INFORMATION();
    cpuLimits.ControlFlags = (UInt32)(CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | CpuFlags.JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP);
    cpuLimits.CpuRate = 45 * 100; // Limit CPu usage to 45%
    var pointerToJobCpuLimits = Marshal.AllocHGlobal(Marshal.SizeOf(cpuLimits));
    Marshal.StructureToPtr(cpuLimits, pointerToJobCpuLimits, false);
    if (!SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectCpuRateControlInformation, pointerToJobCpuLimits, (uint)Marshal.SizeOf(cpuLimits)))
    {
        Console.WriteLine("Error !");
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...