how to slow down a process?
Suppose I have a program that runs in a given amount of time (say, three seconds). I want to run this program so that it runs n-times slower (specified on command line). How would you achieve it with (or better, without) changes to the program ?
please note that adding a sleep at the end is not a solution. The program has to run slower, not to run at full speed for the first three seconds and then do nothing for the remaining time. Also, using "nice" under unix is not a good solution either. it will run slower if other processes demand the processor, but at full speed if nothing is processor-demanding at the same time.
This is a curiosity question. Nothing serious to do related to it. The fact is that I remember 15-20 years 开发者_开发问答ago games that were simply too fast to play on new processors, because they were timed with the processor clock. You had to turn off the turbo.
Let's assume the program is a C compiled program.
One idea is to write a 'ptrace runner.' ptrace is the call that allows you to implement a debugger on platforms such as Linux and Mac.
The idea is to attach to the program and then just repeatedly tell the application to run one instruction with ptrace(PTACE_SINGLESTEP)
. If that's not slow enough, you could add a sleep between each call to ptrace in the runner program.
I wrote a simple example on my linux box how to slow down a child process with SIGSTOP and SIGCONT signals:
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
void dosomething(void){
static volatile unsigned char buffer[1000000];
for(unsigned i=0;i<1000;i++) for(unsigned j=0;j<sizeof(buffer);buffer[j++]=i){;}
}
#define RUN 1
#define WAIT 1
int main(void){
int delay=0, status, pid = fork();
if( !pid ){ kill(getpid(),SIGSTOP); dosomething(); return 0; }
do{
waitpid( pid, &status, WUNTRACED | WCONTINUED );
if( WIFSTOPPED (status) ){ sleep(delay); kill(pid,SIGCONT); }
if( WIFCONTINUED(status) && WAIT ){ sleep(RUN ); kill(pid,SIGSTOP); }
delay=WAIT;
}while( !WIFEXITED(status) && !WIFSIGNALED (status) );
}
No slowdown when WAIT
is zero, otherwise after every RUN
seconds the parent stop the child for WAIT
seconds.
Runtime results:
RUN=1 WAIT=0
---------------
real 3.905s
user 3.704s
sys 0.012s
RUN=1 WAIT=1
---------------
real 9.061s
user 3.640s
sys 0.016s
RUN=1 WAIT=2
---------------
real 13.027s
user 3.372s
sys 0.032s
cpulimit is a tool that does something like this. It works by periodically
kill -STOP
and kill -CONT
the process, which has the effect of it running slower (when averaged over time).
If you have DTrace you may be able to use it's chill() function. You could insert this chill at almost anyplace in a userland application and in multiple places. It's been used before to replicate race conditions seen on slower systems.
I ran some application in a virtual machine under ubuntu. It was really slow. You could configure the virtual machine usage of the system.
You might obfuscate the situation a little further by running a virtual machine under a virtual machine under a virtual machine, ...
精彩评论