C 过度承诺的kvm性能问题

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

当我在带有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.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);
}