2012-03-20 20 views
8

Aplikacja Przyczynia się do uruchomienia komponentu napisanego w C.Czy można ograniczyć użycie procesora w obiekcie procesu .NET?

Proces C wykonuje dość ciężkie zgniatanie, a jeśli nie jesteś ostrożny, możesz naprawdę uderzyć w procesor.

Czy istnieje sposób na ustawienie limitu zewnętrznych procesów spawnowanych przez .NET?

Widziałem this artivcle w sprawie ustawiania twardego limitu pamięci na poziomie systemu operacyjnego, czy jest coś podobnego dla procesora?

+3

Można zmienić priorytet procesu za (myślę, że może to być nawet opcję w 'ProcessStartInfo'). To naprawdę nie ogranicza czasu procesora, ale pozwoli systemowi operacyjnemu na priorytetowe traktowanie innych procesów. –

Odpowiedz

9

Nie w systemie Windows. Można jednak obniżyć priorytet procesu, co zmniejszy prawdopodobieństwo, że problematyczny proces zostanie zaplanowany na procesorze i wpłynie na inne aplikacje (prawdopodobnie o wyższym priorytecie). Na przykład, od http://dotnet-concepts-queries-interviews.blogspot.com/2007/05/how-to-set-process-priority-in-net.html:

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

pamiętać, jeśli nie masz nic innego działającego na polu, prawdopodobnie chcą tego procesu zużyje wszystkie dostępne CPU.

Możesz również ustawić powinowactwo jednostki centralnej, jeśli jest ono umieszczone na pudełku z wieloma procesorami, ograniczając przetwarzanie do określonych rdzeni i pozostawiając inne wolne dla innych aplikacji. Zasadniczo system operacyjny dobrze radzi sobie z tworzeniem wątków aplikacji, więc ustawienie priorytetu procesu prawdopodobnie będzie miało lepszy ogólny wynik. Zobacz How Can I Set Processor Affinity in .NET?

+3

Warto zauważyć ** ta odpowiedź jest niepoprawna ** biorąc pod uwagę aktualne wersje systemu Windows; można to zrobić za pomocą API 'Job Object' w Win2012/Win8, w czasie, gdy odpowiedź na to pytanie, można użyć' NtSetInformationProcess' 'QUOTA_LIMITS_EX :: CPU_RATE_LIMIT' w Vista/Win7/Win2008. Zanim zrezygnujesz, przejrzyj inne odpowiedzi i materiały online. Ponadto ustawienie klasy priorytetu wpływa również na stawki IO, a nie tylko na częstość procesora, co może mieć niezamierzone skutki, jeśli celem NIE jest obniżenie przepustowości we/wy. –

+0

@ShaunWilson Czy masz działający przykład kodu, który to pokazuje? Nie udało mi się jeszcze tego sprawić. – i3arnon

7

Miałem ten sam problem. Rozwiązałem to za pomocą struktury SetInformationJobObject Kernel32 Win Api i JOBOBJECT_CPU_RATE_CONTROL_INFORMATION.

Moim większym problemem było przedstawienie tej struktury w języku C# (używa "unii"). Mam nadzieję, że znalazłem "mono" opis tej struktury.

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

Aktywacja ograniczenie CPU:

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

Poniższy przykład jest w pełni funkcjonalny.

Mam nadzieję, że to pomoże.

poważaniem

-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

Fascynujące, zawsze zapominam o obiektach zadań systemu Windows, może być całkiem przydatne. Niestety flaga 'JobObjectCpuRateControlInformation' jest obsługiwana tylko w Win8 i nowszych wersjach. –

+0

Niestety, tak .... Użyłem go do zarządzania procesami w serwerze Windows 2012 (wymagania bezpieczeństwa). –

+0

Dziękuję za Twój kod. Ten kod działa dla mnie, ale po prostu zastanawiam się, czy ustawiam limit CPu na 45%, ale zużywa on 54-50% ... czy wiesz dlaczego? –

Powiązane problemy