리눅스 퓨 텍스가 경합 할 때 시스템이 스핀 록에 많은 시간을 소비한다는 것을 관찰했습니다. 퓨 텍스가 직접적으로 사용되지 않더라도, malloc/free, rand, glib 뮤텍스 호출, futex를 호출하는 다른 시스템/라이브러리 호출을 호출 할 때도 문제가되는 것으로 나타났습니다. 이 있습니까?이 동작을 제거하는 방법은 있습니까?futex 경합시 높은 시스템 CPU 사용량
커널 2.6.32-279.9.1.el6.x86_64와 함께 CentOS 6.3을 사용하고 있습니다. 또한 kernel.org에서 직접 다운로드 한 최신 안정 커널 3.6.6을 사용해 보았습니다.
원래이 문제는 16GB RAM이 장착 된 24 코어 서버에서 발생했습니다. 이 프로세스에는 700 개의 스레드가 있습니다. "perf record"로 수집 된 데이터는 spinlock이 __lll_lock_wait_private 및 __lll_unlock_wake_private에서 호출되는 futex에서 호출되고 CPU 시간의 50 %를 소비하고 있음을 보여줍니다. gdb로 프로세스를 멈추었을 때 backtraces는 malloc과 free에서 __lll_lock_wait_private __lll_unlock_wake_private에 대한 호출이 이루어진다는 것을 보여주었습니다.
나는이 문제를 줄이려고 했으므로, 실제로 스핀 록 문제를 일으키는 퓨 텍스를 보여주는 간단한 프로그램을 작성했습니다.
시작 다음을 수행 각 스레드 8 개 스레드 : 나는 RAM 듬뿍, 8 코어 시스템에서이 작업을 실행하고
//...
static GMutex *lMethodMutex = g_mutex_new();
while (true)
{
static guint64 i = 0;
g_mutex_lock (lMethodMutex);
// Perform any operation in the user space that needs to be protected.
// The operation itself is not important. It's the taking and releasing
// of the mutex that matters.
++i;
g_mutex_unlock (lMethodMutex);
}
//...
.
"top"을 사용하여 기기가 10 % 유휴, 사용자 모드에서 10 %, 시스템 모드에서 90 %라는 것을 관찰했습니다. 나는 퓨 텍스 코드가 퓨 텍스 대기 큐를 취득해야하기 때문에이 코드는, 스핀 록에 일부 시간을 보내고 기대
50.73% [kernel] [k] _spin_lock
11.13% [kernel] [k] hpet_msi_next_event
2.98% libpthread-2.12.so [.] pthread_mutex_lock
2.90% libpthread-2.12.so [.] pthread_mutex_unlock
1.94% libpthread-2.12.so [.] __lll_lock_wait
1.59% [kernel] [k] futex_wake
1.43% [kernel] [k] __audit_syscall_exit
1.38% [kernel] [k] copy_user_generic_string
1.35% [kernel] [k] system_call
1.07% [kernel] [k] schedule
0.99% [kernel] [k] hash_futex
:
은 "반환 한 최고"를 사용하여, 나는 다음과 같은 관찰했다. 이 코드 스 니펫에서는 사용자 공간에서 실행되는 코드가 거의 없기 때문에 코드가 시스템에서 약간의 시간을 소비 할 것으로 기대합니다. 그러나 스핀 록에서 보낸 시간의 50 %는 과도한 것으로 보이는데 특히이 CPU 시간이 다른 유용한 작업을 수행하는 데 필요할 때입니다.
당신이보고 싶은 행동에 대해 몇 마디 말하고 싶을 것입니다. 나는 이것이 완전히 명확하지 않다고 느낀다. – NPE
mutex 또는 futex를 사용하여 위 예제 에서처럼 변수를 동시에 증가시키는 것은 원자량 증가 (50 ~ 500 배 정도 더 효율적)로 직접 수행 할 수 있으므로 약간 바보입니다. "실제"코드, 즉 실제로 무언가를하는 코드에서 혼잡과 시간이 낭비되는 세부 사항을 낭비하는 것을 낭비합니다. 실제 코드는 한 번에 6 개의 스레드에서 잠금을 위해 경쟁하지 않습니다. – Damon
원래, 퓨 텍스가 사용자 코드에서 직접 호출되지 않아도 문제가되는 것으로 나타났습니다. 이것은 malloc/free, rand, glib 뮤텍스 호출 및 futex를 호출하는 다른 시스템/라이브러리 호출을 호출 할 때 발생합니다. 문제 설명에 제공된 코드 스 니펫은 문제의 발생을 보여주기위한 것으로 아무런 유용한 작업을 의미하지는 않습니다. 사실 뮤텍스 호출 사이의 코드는 모든 사용자 코드가 될 수 있습니다. –