问题
I have a project that dynamically loads in unknown assemblies implementing a specified interface. I don't know the contents or purposes of the assembly, other than it implementing my interface.
I need to somehow restrict the amount of processing power available to these assemblies. Processor priority is not what I'm looking for. I can't use a stopwatch and assign a certain amount of time for the assembly to run as the server might be arbitrarily busy.
Optimally I'd like to specify some completely load independent measure of CPU usage. I can run the assemblies in their own process if necessary.
Is there any way to somehow measure the total over-time CPU usage of a given thread (or process, though thread would be the optimal)?
Might I use the process performance counters, or are they, as I suspect, too unreliable? While I don't need to-the-cycle accuracy, I would need rather high accuracy to limit the computing power allocated to each assembly execution.
To extrapolate a bit on my situation. The reason I'm not looking for prioritization of the processes is that I'm not afraid of exhausting my resources, I just need to ensure I can measure "how many" resources a given assembly uses - thus my point about the server being arbitrarily busy.
Imagine the example scenario where you have two assemblies X and Y. Each of them implement a given algorithm and I want to do a primitive test of which assembly gets the job done quickest. I run each assembly and let it run until it's used "Z" resources, at which point I evaluate which assembly did the best job. In this case, I don't mind if one assembly runs at 100% CPU for three seconds, while the other one runs for 2% CPU over 5 minutes - it's the total resource usage that's important.
I'm thinking I might be able to use the CPU time perfcounter to do a crude limitation. Runt each assembly in a new thread and let it run until it's used a given amount of CPU time, at which point I'll kill the process and evaluate the results. I'm just afraid it won't be accurate enough.
回答1:
I think I remember that Terrarium did something similar to what you want I suggest taking a look at http://www.codeplex.com/terrarium2.
Unfortunately I don't think you have a easy way to do this by just configuring the AppDomain where you load the DLLs. You'll probably have to reimplement what Terrarium does.
回答2:
I'm curious why you think you can't (shouldn't) use priority for this. The people at Microsoft have spent a very long time developing the Task Scheduler that gives all threads/processes an equal shot at the CPU. If you have higher priority processes running on your machine and you don't want your program/3rd party dlls to impact that other program, then simply set your priority lower than that other program, and you won't. That's what priority is for. Even if your program is maxxing out the CPU at 100%, that other program will displace your process or threads when it wants to run, even when priorites are equal, but especially when it has a higher priority.
If you're still determined, then you're going to have to either use PerformanceCounter or a Win32 API to monitor your process/thread and use Thread.Sleep's when you exceed your threshold. This seems overly messy.
A better option (IMO) is to use a custom threadpool that lets you configure the max number of threads, queue up a thread for each assembly you load, set their priority one below normal, and monitor to determine the max number of threads that yields your desired performance limitation. A very good custom threadpool can be found here. (The .NET threadpool won't allow you to limit things which is why you need to use a custom threadpool.)
Another option if you're running on a multi-cpu machine is to use affinity to limit your program to certain cores. On a four-core machine, if you limit your program to core3, for instance, then it can go hog-wild and max out that cpu and the rest of the system will still have 3 cores to maintain high availability.
回答3:
The way most X86 operating systems work is to use preemptive thread scheduling. The OS initializes a timer on the mother board that will send an interrupt to the processor every, say 100ms. (This is an execution slice. Well behaving computationally intensive programs should typically start to wait for something putting them in wait queue before this limit.) When the processor gets the interrupt, it switches execution to the OS kernel.
Thus it should be technically impossible to limit thread execution on a single core system to something more granular than this timer.
With "fair" scheduling, you could have a spinning manager (since you're not interested in saving power) that looks at execution time of the respective threads and terminates them if they've executed for too long.
来源:https://stackoverflow.com/questions/234411/limiting-assembly-execution-number-of-cpu-cycles