이전 블로그 포스팅 불가능하다고 하지 말고 sleep을 nodejs로 구현하세요에서 nodejs 애드온 사용법을 소개한 적이 있습니다. 오늘의 주제는 여전히 애드온입니다. 계속해서 c/c의 기능을 탐색하고 nodejs의 약점을 보완하세요.
저는 nodejs의 성능 문제에 대해 여러 번 언급했습니다. 실제로 언어 자체에 관한 한 nodejs의 성능은 여전히 매우 높습니다. 비록 대부분의 정적 언어만큼 좋지는 않지만 다른 동적 언어에 비해 격차는 크지 않습니다. . 그런데 nodejs가 CPU 집약적인 시나리오를 수행할 수 없다고 자주 말하는 이유는 무엇입니까? 단일 스레드 특성으로 인해 CPU 집약적인 시나리오에서는 CPU를 완전히 활용할 수 없습니다. 컴퓨터 과학에는 유명한 암달의 법칙이 있습니다:
총 작업 부하 W를 두 부분, 즉 직렬 계산만 가능한 Ws와 병렬 계산이 가능한 Wp로 분해할 수 있다고 가정합니다. 그러면 p개 CPU의 병렬 컴퓨팅의 경우 속도 향상 시간을 통해 성능을 향상시킬 수 있습니다. 암달의 법칙은 병렬 처리가 할 수 있는 것과 할 수 없는 것을 설명합니다. 이는 이상적인 상황이지만 실제 상황은 훨씬 더 복잡할 것입니다. 예를 들어, 동시성은 리소스에 대한 경합을 야기하여 다양한 잠금을 추가해야 하며, 이로 인해 종종 병렬성이 대기 상태로 남게 됩니다. 또한 동시성은 운영 체제가 스레드 스케줄링을 전환하는 데 추가 시간 오버헤드를 발생시켜 Ws를 증가시킵니다. 그러나 작업에서 Wp가 Ws보다 훨씬 크고 여러 CPU 코어를 사용할 수 있는 경우 병렬 처리로 인한 성능 향상은 상당합니다.
자, nodejs로 돌아갑니다. 계산 시나리오를 상상해 봅시다: 4,000,000 내의 소수의 수를 계산하십시오. 이 시나리오를 프로그래밍하면 나누기 작업이 주로 사용되며 메모리 및 객체와 같은 작업은 포함되지 않습니다. 이론적으로 nodejs가 상대적으로 빠른 속도로 실행되고 c보다 크게 뒤처지지 않도록 보장할 수 있어 편리합니다. 비교.
JavaScript에서 소수를 찾는 방법은 이 블로그에서 제공됩니다. 직접 복사하세요.
다른 C 언어 버전 작성:
bool zishu(int num){
If (num == 1) {
false를 반환합니다.
}
If (숫자 == 2) {
true를 반환합니다.
}
for (int i = 2; i <= sqrt(num); i ) {
If (num % i == 0) {
false를 반환합니다.
}
}
true를 반환합니다.
};
nodejs에서는 1부터 4000000까지의 루프를 사용하여 소수를 검색합니다. C 언어에서는 여러 스레드를 설정하고 개수를 4000000으로 정의합니다. 각 스레드는 다음을 수행합니다. 개수가 0보다 크면 제거합니다. count의 값이며, 소수인지 여부를 계산하고 count를 1씩 감소시킵니다. 이 아이디어에 따르면 자바스크립트 버전은 작성하기 쉽습니다.
for (j = 1; j < 4000000; j ) {
If(zhishu(j)){
백작 ;
}
}
가장 어려운 점은 C 언어의 다중 스레드 프로그래밍입니다. c/c 초기에는 병렬 컴퓨팅의 필요성을 고려하지 않았기 때문에 표준 라이브러리에서는 멀티스레딩 지원이 제공되지 않았습니다. 운영 체제마다 일반적으로 구현이 다릅니다. 이 문제를 피하기 위해 우리는 pthread를 사용하여 스레드를 처리합니다.
pthread 최신 버전을 다운로드하세요. gyp에 익숙하지 않아서 링크 의존성 lib를 수정하는데 시간이 많이 걸렸고, 결국 제 방법은 pthread의 소스코드를 프로젝트 디렉토리에 직접 넣고, 소스코드에 pthread.c를 추가하는 방법이었습니다. 바인딩.gyp에 목록을 작성하고, 프로젝트 컴파일 시 pthread를 한 번 컴파일합니다. 수정된 바인딩.gyp은 다음과 같습니다.
물론 내 방법은 매우 번거롭습니다. lib에 대한 참조를 추가하고 pthread에 디렉터리를 포함하기만 하고 종속성 문제가 없다면 내 방법을 사용할 필요가 없습니다.
그럼 C/C 멀티스레딩에 대해 자세히 알아보고 스레드 처리 기능을 정의해 보겠습니다.
void *thread_p(void *null){
정수 숫자, x=0;
하세요{
pthread_mutex_lock(&잠금);
숫자=개수--;
pthread_mutex_unlock(&lock);
If(숫자>0){
If(zhishu(num))x ;
}그 외{
휴식;
}
}동안(true);
표준::cout<<' '<
null을 반환합니다.
}
스레드 간에는 count 변수가 서로 경쟁합니다. 동시에 하나의 스레드만 count 변수를 작동할 수 있도록 해야 합니다. pthread_mutex_t lock;을 통해 뮤텍스 잠금을 추가합니다. pthread_mutex_lock(&lock);이 실행되면 스레드는 잠금 상태를 확인하고 잠금이 해제되면 후속 코드 실행을 차단하고 후속 코드를 실행합니다. 이에 따라 pthread_mutex_unlock(&lock);은 잠금 상태를 잠금 해제하는 것입니다.
컴파일러는 컴파일하는 동안 컴파일 최적화를 수행하므로 문이 명확하게 아무것도 수행하지 않고 다른 문 실행에 영향을 주지 않으면 컴파일러에 의해 최적화됩니다. 위의 코드에는 소수의 개수를 세는 코드를 추가했습니다. 그렇지 않은 경우에는 다음과 같습니다.
은 컴파일러에 의해 직접 건너뛰어 실제로 실행되지 않습니다.
애드온을 추가하는 작성 방법이 도입되었습니다. 자바스크립트에서 스레드 수를 나타내는 매개변수를 받은 다음 c에서 지정된 수의 스레드를 생성하여 소수 검색을 완료합니다. 전체 코드:
정수=4000000;
pthread_t tid[MAX_THREAD];
pthread_mutex_t 잠금;
void *thread_p(void *null){
정수 숫자, x=0;
하세요{
pthread_mutex_lock(&잠금);
숫자=개수--;
pthread_mutex_unlock(&잠금);
if(숫자>0){
if(zhishu(num))x ;
}그밖에{
휴식;
}
}동안(true);
표준::cout
pthread_exit(NULL);
null을 반환합니다.
}
NAN_METHOD(즈슈){
NanScope();
pthread_mutex_init(&lock,NULL);
double arg0=args[0]->NumberValue();
int c=0;
for (int j = 0; j
pthread_create(&tid[j],NULL,thread_p,NULL);
}
for (int j = 0; j
pthread_join(tid[j],NULL);
}
NanReturnUndefine();
}
void Init(Handle
NODE_MODULE(안녕하세요, Init);
phread_create可以创建线程, 默认是joinable, 这个时候子线程受程;主线程;phread_join阻塞住主线程,等待子线程join,直到子线程退出。如果子线程已退流,则phread_join不会做任何事。所以对所有的线程city执行thread_join,可以保证所有的线程退流后才会例主线程继续进行。
完善一下nodejs脚本:
console.time("c");
zishu_c(100);
console.timeEnd("c");
console.time("js");
var 개수=0;
for (j = 1; j
if(zhishu(j)){
카운트 ;
}
}
console.log(개수);
console.timeEnd("js");
테스트 결과 살펴보기:
단일 스레드에서는 C/C의 실행 속도가 nodejs의 181%이지만 동적 언어에서는 이 결과가 여전히 매우 좋다고 생각합니다. 듀얼 스레드를 사용할 때 속도 향상이 가장 뚜렷하게 나타납니다. 이는 내 컴퓨터에 듀얼 코어 4스레드 CPU가 있고 현재 처리에 두 개의 코어가 사용되고 있을 가능성이 있기 때문입니다. 이때 속도는 스레드가 4개 있을 때 최대치에 이르며, 스레드 수를 늘려도 속도는 향상될 수 없습니다. 위의 암달의 법칙에서 p는 4의 상한에 도달했습니다. 더 많은 스레드를 추가하면 운영 체제 프로세스 스케줄링 시간과 잠금 시간이 늘어납니다. CPU 시간에 대한 경쟁도 증가하지만 전반적으로 Ws의 증가는 더욱 뚜렷해지고 성능은 저하됩니다. 유휴 컴퓨터에서 이 실험을 수행하면 데이터가 더 좋아질 것입니다.
이 실험을 통해 CPU 집약적인 작업의 경우 계산에 더 많은 메모리, 문자열, 배열, 재귀 등이 포함되면 효율성이 크게 향상된다는 결론을 내릴 수 있습니다. (추후 검증 예정) 성능 향상은 더욱 놀랍습니다. 동시에 멀티 스레드를 합리적으로 사용하면 처리 효율성이 효과적으로 향상될 수 있지만 스레드가 많다고 해서 항상 더 나은 것은 아닙니다. 기계의 조건에 따라 적절하게 구성해야 합니다.
Nodejs 자체는 실제로 CPU 집약적인 작업을 잘 처리하지 못하지만, 이 글의 경험으로 볼 때 이 장애물을 극복하는 것이 불가능하지는 않다고 생각합니다.