C 过度承诺的kvm性能问题
当我在带有1个pCPU和4个VCPU的虚拟机上运行基准测试程序时,我遇到了性能问题。我使用mpstat来调查可能导致问题的原因以及它是如何导致问题的。它显示了窃取时间、空闲时间和系统时间的增加 以下是我运行程序时虚拟机上mpstat的输出:C 过度承诺的kvm性能问题,c,linux,multithreading,virtualization,kvm,C,Linux,Multithreading,Virtualization,Kvm,当我在带有1个pCPU和4个VCPU的虚拟机上运行基准测试程序时,我遇到了性能问题。我使用mpstat来调查可能导致问题的原因以及它是如何导致问题的。它显示了窃取时间、空闲时间和系统时间的增加 以下是我运行程序时虚拟机上mpstat的输出: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle all 3.14 0.00 8.00 0.00 0.00 0.0
CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle
all 3.14 0.00 8.00 0.00 0.00 0.00 58.29 0.00 30.57
0 4.60 0.00 8.05 0.00 0.00 0.00 64.37 0.00 22.99
1 2.27 0.00 5.68 0.00 0.00 0.00 53.41 0.00 38.64
2 3.37 0.00 8.99 0.00 0.00 0.00 61.80 0.00 25.84
3 3.45 0.00 8.05 0.00 0.00 0.00 54.02 0.00 34.48
这是它在主机上的输出(当我运行程序时):
我(从)知道:
Steal time是虚拟CPU等待真实CPU的时间百分比
当虚拟机监控程序为另一个虚拟处理器提供服务时,CPU
我知道窃取时间的增加可能是因为我的虚拟机过度投入,但我想知道为什么我测试的其他程序没有这个问题。我不知道为什么空闲时间也会增加
我的测试程序的源代码非常大,我将其发布在github中。我不知道这是否重要,但这段代码做了一些繁忙的等待。以下是发生繁忙等待的代码:
int parsec_barrier_wait(parsec_barrier_t *barrier) {
int master;
int rv;
if(barrier==NULL) return EINVAL;
rv = pthread_mutex_lock(&barrier->mutex);
if(rv != 0) return rv;
//A (necessarily) unsynchronized polling loop followed by fall-back blocking
if(!barrier->is_arrival_phase) {
pthread_mutex_unlock(&barrier->mutex);
volatile spin_counter_t i=0;
while(!barrier->is_arrival_phase && i<SPIN_COUNTER_MAX) i++;
while((rv=pthread_mutex_trylock(&barrier->mutex)) == EBUSY);
if(rv != 0) return rv;
//Fall back to normal waiting on condition variable if necessary
while(!barrier->is_arrival_phase) {
rv = pthread_cond_wait(&barrier->cond, &barrier->mutex);
if(rv != 0) {
pthread_mutex_unlock(&barrier->mutex);
return rv;
}
}
}
//We are guaranteed to be in an arrival phase, proceed with barrier synchronization
master = (barrier->n == 0); //Make first thread at barrier the master
barrier->n++;
if(barrier->n >= barrier->max) {
//This is the last thread to arrive, don't wait instead
//start a new departure phase and wake up all other threads
barrier->is_arrival_phase = 0;
pthread_cond_broadcast(&barrier->cond);
} else {
//wait for last thread to arrive (which will end arrival phase)
//we use again an unsynchronized polling loop followed by synchronized fall-back blocking
if(barrier->is_arrival_phase) {
pthread_mutex_unlock(&barrier->mutex);
volatile spin_counter_t i=0;
while(barrier->is_arrival_phase && i<SPIN_COUNTER_MAX) i++;
while((rv=pthread_mutex_trylock(&barrier->mutex)) == EBUSY);
if(rv != 0) return rv;
//Fall back to normal waiting on condition variable if necessary
while(barrier->is_arrival_phase) {
rv = pthread_cond_wait(&barrier->cond, &barrier->mutex);
if(rv != 0) {
pthread_mutex_unlock(&barrier->mutex);
return rv;
}
}
}
}
barrier->n--;
//last thread to leave barrier starts a new arrival phase
if(barrier->n == 0) {
barrier->is_arrival_phase = 1;
pthread_cond_broadcast(&barrier->cond);
}
pthread_mutex_unlock(&barrier->mutex);
return (master ? PARSEC_BARRIER_SERIAL_THREAD : 0);
}
int parsec\u barrier\u wait(parsec\u barrier\u t*barrier){
国际大师;
int-rv;
如果(barrier==NULL)返回EINVAL;
rv=pthread\u mutex\u lock(&barrier->mutex);
如果(rv!=0)返回rv;
//一个(必要的)非同步轮询循环,随后是回退阻塞
如果(!屏障->为到达阶段){
pthread_mutex_unlock(&barrier->mutex);
挥发性自旋计数器i=0;
而(!barrier->is_arrival_phase&&imutex))==EBUSY);
如果(rv!=0)返回rv;
//如有必要,返回到正常等待条件变量
而(!屏障->是到达阶段){
rv=pthread\u cond\u wait(&barrier->cond,&barrier->mutex);
如果(rv!=0){
pthread_mutex_unlock(&barrier->mutex);
返回rv;
}
}
}
//我们保证处于到达阶段,继续进行屏障同步
master=(barrier->n==0);//使barrier处的第一个线程成为master
势垒->n++;
如果(屏障->n>=屏障->最大值){
//这是最后一个到达的线程,不要等待
//启动一个新的离开阶段并唤醒所有其他线程
屏障->是到达阶段=0;
pthread_cond_广播(&barrier->cond);
}否则{
//等待最后一个线程到达(将结束到达阶段)
//我们再次使用一个不同步的轮询循环,然后是同步的回退阻塞
如果(屏障->是到达阶段){
pthread_mutex_unlock(&barrier->mutex);
挥发性自旋计数器i=0;
而(屏障->是到达阶段(&imutex))==EBUSY);
如果(rv!=0)返回rv;
//如有必要,返回到正常等待条件变量
while(屏障->是到达阶段){
rv=pthread\u cond\u wait(&barrier->cond,&barrier->mutex);
如果(rv!=0){
pthread_mutex_unlock(&barrier->mutex);
返回rv;
}
}
}
}
势垒->n-;
//离开屏障的最后一个线程开始新的到达阶段
如果(屏障->n==0){
屏障->是到达阶段=1;
pthread_cond_广播(&barrier->cond);
}
pthread_mutex_unlock(&barrier->mutex);
返回(主线程?PARSEC_BARRIER_串行_线程:0);
}
任何想法都将不胜感激。窃取时间可能更高,因为您的vcpu总利用率更高(来自旋转)。空闲时间有点不寻常,但我怀疑它代表的是非虚拟化的CPU时间。@Sneftel您能解释更多吗?您所说的非虚拟化CPU时间是什么意思?虚拟机知道它的CPU是虚拟化的吗?偷取时间可能更高,因为你有更高的整体vcpu利用率(来自旋转)。空闲时间有点不寻常,但我怀疑它代表的是非虚拟化的CPU时间。@Sneftel您能解释更多吗?您所说的非虚拟化CPU时间是什么意思?虚拟机是否知道其CPU已虚拟化?
int parsec_barrier_wait(parsec_barrier_t *barrier) {
int master;
int rv;
if(barrier==NULL) return EINVAL;
rv = pthread_mutex_lock(&barrier->mutex);
if(rv != 0) return rv;
//A (necessarily) unsynchronized polling loop followed by fall-back blocking
if(!barrier->is_arrival_phase) {
pthread_mutex_unlock(&barrier->mutex);
volatile spin_counter_t i=0;
while(!barrier->is_arrival_phase && i<SPIN_COUNTER_MAX) i++;
while((rv=pthread_mutex_trylock(&barrier->mutex)) == EBUSY);
if(rv != 0) return rv;
//Fall back to normal waiting on condition variable if necessary
while(!barrier->is_arrival_phase) {
rv = pthread_cond_wait(&barrier->cond, &barrier->mutex);
if(rv != 0) {
pthread_mutex_unlock(&barrier->mutex);
return rv;
}
}
}
//We are guaranteed to be in an arrival phase, proceed with barrier synchronization
master = (barrier->n == 0); //Make first thread at barrier the master
barrier->n++;
if(barrier->n >= barrier->max) {
//This is the last thread to arrive, don't wait instead
//start a new departure phase and wake up all other threads
barrier->is_arrival_phase = 0;
pthread_cond_broadcast(&barrier->cond);
} else {
//wait for last thread to arrive (which will end arrival phase)
//we use again an unsynchronized polling loop followed by synchronized fall-back blocking
if(barrier->is_arrival_phase) {
pthread_mutex_unlock(&barrier->mutex);
volatile spin_counter_t i=0;
while(barrier->is_arrival_phase && i<SPIN_COUNTER_MAX) i++;
while((rv=pthread_mutex_trylock(&barrier->mutex)) == EBUSY);
if(rv != 0) return rv;
//Fall back to normal waiting on condition variable if necessary
while(barrier->is_arrival_phase) {
rv = pthread_cond_wait(&barrier->cond, &barrier->mutex);
if(rv != 0) {
pthread_mutex_unlock(&barrier->mutex);
return rv;
}
}
}
}
barrier->n--;
//last thread to leave barrier starts a new arrival phase
if(barrier->n == 0) {
barrier->is_arrival_phase = 1;
pthread_cond_broadcast(&barrier->cond);
}
pthread_mutex_unlock(&barrier->mutex);
return (master ? PARSEC_BARRIER_SERIAL_THREAD : 0);
}