2010-07-28 6 views
3

궁극적으로 최종 사용자 웹 경험을 제공하는 고성능 대용량 데이터 엔진에서 성능 튜닝을하고 있습니다. 구체적으로 말하자면, 나에게 위임 한 자료는 멀티 스레드 파일 IO 및 데이터를 로컬 캐시에 메모리 매핑하는 것과 관련이 있습니다. 타이밍 폴을 분리하기 위해 테스트 애플리케이션을 작성하는 과정에서 몇 가지 질문이 제기되었습니다. 시스템 파일 열기 (open(O_RDONLY)) 호출 만 수행하도록 코드가 최소화되었습니다. 이 쿼리의 결과로 기본적인 저수준 시스템 프로세스를 이해하고 완전한 예측 (또는 최소한 관계형) 타이밍 모델을 이해하는 데 도움이되기를 바랍니다. 제안은 언제나 환영합니다. 우리는 타이밍 장벽에 부딪 혔으며 행동을 이해하고 그 장벽이 깨질 수 있는지 판단하려고합니다.File open()에 대한 Linux 멀티 스레드 성능 향상

테스트 프로그램 아래에 명시된 바와 같이

  1. 은 GNU C 컴파일러를 이용하여 컴파일 된 C에 기록된다;
  2. 발견 된 문제를 단일 시스템 파일 "open()"로 분리하기 위해 최소한으로 작성되었습니다.
  3. 요청 된 수의 pthread를 동시에 실행하도록 구성 할 수 있습니다.
  4. ~ 8K 크기의 1000 개의 텍스트 파일 목록을로드합니다.
  5. 은 속성 수정없이 (간단히) 스레드를 생성합니다.
  6. 각 스레드는 단일 스레드가 모든 1000 개의 파일을 열어야하는 방식으로 파일 목록이 고갈 될 때까지 미리 결정된 파일 목록에서 다음 사용 가능한 파일에 대해 여러 순차 파일 열기() 호출을 수행합니다. 이론적으로 500 개의 파일 (아직 검증되지 않음) 등을 열 수 있습니다.

우리는 스레드 수, 파일 크기 및 파일이 로컬 또는 원격 서버에 있는지 여부를 매개 변수에 따라 여러 번 테스트했습니다. 몇 가지 질문이 제기되었습니다. (원격 파일 열기)

관찰 결과

  1. 파일 오픈 시간은 (예상 의한 캐싱을 제기)를 통해 처음으로 높다;
  2. 하나의 스레드로 테스트 응용 프로그램을 실행하면 모든 원격 파일을로드하는 데 X 초가 걸립니다.
  3. 시스템에서 사용 가능한 CPU 수와 스레드 수를 1로 계산하여 앱을 실행하면 CPU 수 (nX 초)에 비례 한 시간이 걸리는 것으로 보입니다.
  4. 스레드 수> #CPUs를 사용하여 응용 프로그램을 실행하면 #CPUs 스레드로 실행하는 데 걸리는 시간과 대략 동일한 값으로 수평이되는 것처럼 보이는 런타임이 발생합니다 (우연의 일치입니까, 체계적인 한도입니까? ?).
  5. 여러 동시 프로세스 (예 : 동일한 테스트 응용 프로그램의 동시 인스턴스 25 개)를 실행하면 선택한 스레드 수에 대한 프로세스 수와 대략 선형 인 시간이됩니다.다른 서버에 응용 프로그램을 실행
  6. 는 (로컬에 존재하는 파일 열기) 비슷한 결과

관찰 된 결과를 보여줍니다 크기 빠른 시간

  1. 주문 (예상 할 수있는대로를);
  2. 스레드 수를 늘리면 약 4-5 개의 활성 스레드에서 LOW 타이밍 변곡점이 발생하고 스레드 수가 CPU 수와 같아 질 때까지 다시 증가하고 다시 레벨이 해제됩니다.
  3. 여러 개의 동시 프로세스 (동일한 테스트)를 실행하면 일정한 스레드 수에 대한 프로세스 수와 대략 선형 인 시간이됩니다 (위의 5 번과 동일한 결과).

또한 로컬 열기는 약 .01 ms이고 순차적 네트워크 열기는 1ms에서 100 배 느리다는 것을 알았습니다. 네트워크 파일을 열면 8 개의 스레드로 최대 8 배의 선형 처리량이 증가하지만 9 개 이상의 스레드는 아무 것도 처리하지 않습니다. 8 회의 동시 요청 이후에 네트워크 공개 통화가 차단되는 것 같습니다. 우리가 예상 한 것은 네트워크 라운드 트립과 동일한 초기 지연이었고 로컬과 거의 동일한 처리량이었습니다. 아마도 100 배 이상 오래 걸리는 로컬 및 원격 시스템에서 수행되는 추가 뮤텍스 잠금이있을 수 있습니다. 초래

  1. 실행 여러 스레드 : 아마도에만 8

    예상 결과와 질문이 이와 같은 포럼에서 테스트 또는 답변에 의해 하나 답변을 보유하고 원격 호출의 일부 내부 큐가 더 짧은 시간에 동일한 작업;

  2. 최적의 스레드 수가 있습니까?
  3. 스레드 수와 사용 가능한 CPU 수 사이에 관계가 있습니까?
  4. 8-10 파일 제한이 준수되는 다른 체계적인 이유가 있습니까?
  5. "open()"에 대한 시스템 호출이 멀티 스레딩 프로세스에서 어떻게 작동합니까?
  6. 각 스레드는 컨텍스트 전환 시간 슬라이스를 얻습니다.
  7. open() 호출이 차단되고 파일이 파일 캐시로 열리거나로드 될 때까지 대기합니까? 또는 작업이 진행되는 동안 호출이 컨텍스트 전환을 허용합니까?
  8. open()이 완료되면 스케줄러가 해당 스레드의 우선 순위를 다시 지정하여 스레드가 라운드 로빈 방식으로 돌아갈 때까지 대기해야합니까?
  9. 1000 개의 파일이있는 마운트 볼륨이 읽기 전용으로 설정되었거나 읽기/쓰기로 설정하면 차이가 있습니까?
  10. 전체 경로와 함께 open()이 호출되면 stat() 경로의 각 요소가? 파일 트리 목록에서 공통 디렉토리를 열고() 공용 디렉토리 아래에있는 파일을 상대 경로로 open()하는 것이 더 합리적입니까?

개발 테스트 설정 :

Red Hat Enterprise Linux Server release 5.4 (Tikanga) 

8-CPUS, each with characteristics as shown below: 

processor  : 0 
vendor_id  : GenuineIntel 
cpu family  : 6 
model   : 23 
model name  : Intel(R) Xeon(R) CPU   X5460 @ 3.16GHz 
stepping  : 6 
cpu MHz   : 1992.000 
cache size  : 6144 KB 
physical id  : 0 
siblings  : 4 
core id   : 1 
cpu cores  : 4 
apicid   : 1 
fpu    : yes 
fpu_exception : yes 
cpuid level  : 10 
wp    : yes 
flags   : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm constant_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 lahf_lm 
bogomips  : 6317.47 
clflush size : 64 
cache_alignment : 64 
address sizes : 38 bits physical, 48 bits virtual 
power management: 

GNU C compiler, version: 
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46) 
+0

Dude, 많은 질문 중 하나입니다. 가독성을 높이려면 btw 형식을 읽어보십시오. – mvds

+0

그래서 벤치 마크 된 그래프를 삽입 할 수 있다면 정말 유용 할 것입니다. – stsquad

답변

1

이 당신의 문제 중 하나이지만, 사용 될 수 있습니다 경우 확실하지.

단일 SATA 디스크에서 수천 회의 무작위 판독을 최적화하면서 나를 비난 한 것은 논 블로킹 I/O를 수행하는 것이 여분의 스레드없이 깨끗한 방법으로 그렇게 쉽지 않다는 것입니다.

블로킹 장치에 비 블로킹 read()을 발행하는 것은 불가능합니다 (현재). 즉, 디스크가 필요로하는 5ms 탐색 시간 (그리고 5ms는 3GHz에서 영원)을 차단합니다. O_NONBLOCK에서 open()까지만 지정하면 CD 버너 등으로 이전 버전과의 호환성을 확보하기위한 용도로 사용되었습니다 (이는 다소 모호한 문제였습니다). 일반적으로 open()은 아무 것도 차단하거나 캐시하지 않습니다. 대부분 파일 입출력을 처리하기위한 것입니다.

제게는 mmap()이 가능한 한 디스크 처리에 가까워졌습니다. madvise()mincore()을 사용하여 디스크의 NCQ 기능을 완전히 활용할 수있었습니다. 이는 뛰어난 요청의 대기열 깊이를 변경하여 간단히 입증되었습니다. 이는 10k 읽기를 수행하는 데 걸린 총 시간에 반비례하는 것으로 나타났습니다.

64 비트 메모리 어드레싱 덕분에 mmap()을 사용하여 전체 디스크를 메모리에 매핑해도 아무런 문제가 없습니다. (32 비트 플랫폼에서는 mmap64()을 사용하여 필요한 디스크 부분을 매핑해야합니다.)