Можете ли вы ограничить использование ЦП для .NET Process Object? - PullRequest
8 голосов
/ 20 марта 2012

Приложение, которое я помогаю, запускает компонент, написанный на C.

Процесс C делает довольно тяжелый перебор, и, если вы неосторожны, он действительно может забить ваш процессор.

Есть ли способ установить предел для внешних процессов, порожденных .NET?

Я видел этот artivcle при установке ограничения жесткой памяти на уровне ОС, есть ли подобное дляCPU

Ответы [ 2 ]

9 голосов
/ 11 июля 2015

У меня была такая же проблема. Я решил это с помощью SetInformationJobObject Kernel32 Win Api и JOBOBJECT_CPU_RATE_CONTROL_INFORMATION struct.

Моя большая проблема состояла в том, чтобы представить эту структуру в c # (использует "union"). Надеюсь, я нашел «моно» описание этой структуры.

[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;
}

Чтобы активировать ограничение процессора:

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

Образец ниже полностью функционален.

Надеюсь, это поможет.

С уважением

-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 !");
    }
}
9 голосов
/ 20 марта 2012

Не в Windows. Однако вы можете снизить приоритет процесса, что снизит вероятность того, что проблемный процесс будет запланирован на ЦП, и будет мешать другим (предположительно, с более высоким приоритетом) приложениям. Например, из http://dotnet -concepts-queries-interviews.blogspot.com / 2007/05 / как установить приоритет процесса в net.html :

Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.BelowNormal;

Имейте в виду, что если у вас больше ничего не запущено на коробке, вы, вероятно, хотите, чтобы этот процесс потреблял весь доступный процессор.

Вы также можете установить привязку к процессору, если он установлен на многопроцессорном блоке, ограничивая обработку некоторыми ядрами и оставляя другие свободными для других приложений. Обычно ОС хорошо справляется с планированием потоков приложений, поэтому установка приоритета процесса, вероятно, даст лучший общий результат. См. Как установить сходство процессоров в .NET?

...