2012-03-20 29 views
8

Ứng dụng tôi đang đóng góp để kích hoạt một thành phần được viết bằng C.Bạn có thể giới hạn mức sử dụng CPU trên một đối tượng quy trình .NET không?

Quy trình C thực hiện một số crunching khá nặng và nếu bạn không cẩn thận thực sự có thể búa CPU của bạn.

Có cách nào để đặt giới hạn cho các quy trình bên ngoài được sinh ra bởi .NET không?

Tôi đã thấy this artivcle khi đặt giới hạn bộ nhớ cứng ở cấp hệ điều hành, có điều tương tự cho CPU không?

+3

Bạn có thể thay đổi ưu tiên của quá trình (Tôi nghĩ rằng nó thậm chí có thể là một lựa chọn trong 'ProcessStartInfo'). Nó không thực sự giới hạn bao nhiêu thời gian xử lý nó sẽ nhận được nhưng nó sẽ cho hệ điều hành để cho các quy trình khác được ưu tiên. –

Trả lời

9

Không có trong Windows. Tuy nhiên, bạn có thể giảm mức ưu tiên của quá trình, điều này sẽ làm giảm khả năng quá trình có vấn đề sẽ được lên lịch trên CPU và gây trở ngại cho các ứng dụng khác (có lẽ là ưu tiên cao hơn). Ví dụ, từ http://dotnet-concepts-queries-interviews.blogspot.com/2007/05/how-to-set-process-priority-in-net.html:

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

Hãy nhớ, nếu bạn không có bất cứ thứ gì chạy trên hộp, bạn có thể muốn quá trình này để tiêu thụ tất cả các CPU có sẵn.

Bạn cũng có thể đặt mối quan hệ CPU nếu nó ở trên hộp đa bộ xử lý, hạn chế xử lý đối với một số lõi nhất định và để người khác miễn phí cho các ứng dụng khác. Nói chung, hệ điều hành thực hiện tốt công việc lên lịch cho các luồng ứng dụng, vì vậy việc thiết lập mức độ ưu tiên của quá trình có thể có kết quả tổng thể tốt hơn. Xem How Can I Set Processor Affinity in .NET?

+3

Cần lưu ý ** câu trả lời này là không chính xác ** cho các phiên bản hiện tại của Windows; điều này có thể được thực hiện thông qua các API 'Job Object' trong Win2012/Win8, tại thời điểm câu hỏi này được trả lời, bạn có thể sử dụng' NtSetInformationProcess' 'QUOTA_LIMITS_EX :: CPU_RATE_LIMIT' trong Vista/Win7/Win2008. Vui lòng xem lại các câu trả lời và tài liệu trực tuyến khác trước khi từ bỏ. Hơn nữa, việc đặt lớp ưu tiên cũng ảnh hưởng đến tốc độ IO, không chỉ tỷ lệ CPU, mà có thể có các hiệu ứng không mong muốn nếu mục tiêu của bạn KHÔNG làm giảm thông lượng IO. –

+0

@ShaunWilson Bạn có mẫu mã đang hoạt động cho thấy điều này không? Tôi chưa quản lý để làm việc này. – i3arnon

7

Tôi đã gặp vấn đề tương tự. Tôi đã giải quyết nó bằng cách sử dụng cấu trúc SetInformationJobObject Kernel32 Win Api và JOBOBJECT_CPU_RATE_CONTROL_INFORMATION.

Vấn đề lớn hơn của tôi là đại diện cho cấu trúc này trong C# (sử dụng "union"). Hy vọng rằng, tôi tìm thấy một mô tả "mono" của cấu trúc này.

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

Để kích hoạt giới hạn Cpu:

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

Các mẫu dưới đây là đầy đủ chức năng.

Tôi hy vọng đó là trợ giúp.

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

Hấp dẫn, tôi luôn quên về các đối tượng Windows Job, có thể khá hữu ích. Thật không may cờ 'JobObjectCpuRateControlInformation' chỉ được hỗ trợ trong Win8 và sau đó. –

+0

Thật không may, vâng .... Tôi đã sử dụng nó để quản lý quy trình trong máy chủ Windows 2012 (yêu cầu bảo mật). –

+0

Cảm ơn bạn đã nhập mã. Mã này làm việc cho tôi nhưng tôi tự hỏi tôi đã đặt Limit CPu sử dụng đến 45% nhưng nó sử dụng 54-50% ... bạn có biết tại sao không? –

Các vấn đề liên quan