2012-03-20 5 views
8

Приложение, вносящее вклад в создание компонента, написанного на C.Можете ли вы ограничить использование ЦП на объекте .NET Process?

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

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

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

+3

Вы можете изменить приоритет процесса (я думаю, что это может быть даже вариант в 'ProcessStartInfo'). Он не ограничивает количество времени, затрачиваемого процессором, но он говорит, что ОС позволяет другим приоритетным процессам. –

ответ

9

Не в Windows. Тем не менее, вы можете снизить приоритет процесса, что уменьшит вероятность того, что проблемный процесс будет запланирован на CPU и будет мешать другим (предположительно более приоритетным) приложениям. Например, из http://dotnet-concepts-queries-interviews.blogspot.com/2007/05/how-to-set-process-priority-in-net.html:

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

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

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

+3

Стоит отметить ** этот ответ неверен ** при текущих версиях Windows; это можно сделать с помощью API-интерфейсов Job Object в Win2012/Win8, на момент ответа на этот вопрос вы могли бы использовать «NtSetInformationProcess» QUOTA_LIMITS_EX :: CPU_RATE_LIMIT 'в Vista/Win7/Win2008. Перед тем, как сдаться, просмотрите другие ответы и онлайн-материалы. Кроме того, установка класса приоритета также влияет на скорости ввода-вывода, а не только скорости процессора, которые могут иметь непреднамеренные эффекты, если ваша цель НЕ была снижать пропускную способность ввода-вывода. –

+0

@ShaunWilson У вас есть пример рабочего кода, показывающий это? Мне еще не удалось заставить эту работу работать. – i3arnon

7

У меня была та же проблема. Я решил это, используя 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; 
} 

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

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 !"); 
    } 
} 
+0

Увлекательный, я всегда забываю о объектах Windows Job, может быть весьма полезен. К сожалению, флаг JobObjectCpuRateControlInformation' поддерживается только в Win8 и более поздних версиях. –

+0

К сожалению, да .... Я использовал его для управления процессами на сервере Windows 2012 (требование безопасности). –

+0

Спасибо за ваш код. Этот код работает для меня, но мне просто интересно, что я использовал Limit CPu 45%, но он использует 54-50% ... знаете ли вы, почему?! –

Смежные вопросы